排序演算法4——圖解希爾排序及其實現
阿新 • • 發佈:2018-12-16
排序演算法1——圖解氣泡排序及其實現(三種方法,基於模板及函式指標)
排序演算法2——圖解簡單選擇排序及其實現
排序演算法3——圖解直接插入排序以及折半(二分)插入排序及其實現
排序演算法4——圖解希爾排序及其實現
排序演算法5——圖解堆排序及其實現
排序演算法6——圖解歸併排序及其遞迴與非遞迴實現
排序演算法7——圖解快速排序以及不同CUTOFF的時間測試
基本思想
希爾排序對插入排序進行改進,希望通過每次交換間隔一定距離的元素,達到排序效率上的提升
基本原理是:
將待排序的一組元素按一定的間隔分為若干個序列,分別進行插入排序。
開始時設定的間隔比較大,在每輪排序中將間隔逐步減小,直到間隔為1,
也就是最後一步是簡單插入排序
然後,在5間隔排序的基礎上,做3間隔排序和1間隔排序(即直接插入排序)
可以看到,較小間隔的排序仍然保持著較大間隔的性質,即更小間隔的排序沒有把上一步的結果變壞
程式碼如下,和直接插入排序差不多
在增量序列上,可以改為除以2(最原始的)或者是其他的增量序列
或者這樣指定增量序列
使用不同的增量序列,希爾排序的整體時間複雜度就不一樣
和直接插入排序不同的是,希爾排序不是穩定的排序
選取不同增量進行排序時,可能導致數值相同的兩個元素髮生相對位置上的改變
測試結果及程式碼
#include <iostream>
template<class T>
void ShellSort(T *a, int length) {
int gap;
int i, j;
T tmp;
int Sedgewick[] = { 929, 505, 209, 109, 41, 19, 5, 1, 0 };
//int Sedgewick[] = { 127, 63, 31, 15, 7, 3, 1, 0 };
int si;
for (si = 0; Sedgewick[si] >= length; ++si);
//for (gap = length / 3; gap > 0; gap /= 3) { // 希爾增量序列
for (gap = Sedgewick[si]; gap > 0; gap = Sedgewick[++si]){
for (i = gap; i < length; ++i) { // 這裡i從gap開始是因為把第0張當做有序,於是下一張是從gap開始,這樣,把原來插入排序裡的1全部換成gap 就可以變為希爾排序了
tmp = a[i];
for (j = i; j >= gap && a[j - gap] > tmp; j-=gap) {
a[j] = a[j - gap];
}
a[j] = tmp;
}
}
}
template<class T>
void ArrShow(T *a, int length) {
for (int i = 0; i < length; ++i) {
std::cout << a[i] << " ";
}
puts("\n");
}
int main(int argc, char *argv[]) {
int test[13] = { 81, 94, 11, 96, 12, 35, 17, 95, 28, 58, 41, 75, 15 };
ArrShow(test, 13);
puts("ShellSort : ");
ShellSort(test, 13);
ArrShow(test, 13);
return 0;
}