1. 程式人生 > >排序演算法4——圖解希爾排序及其實現

排序演算法4——圖解希爾排序及其實現

排序演算法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; }