希爾排序
希爾排序是插入排序的一種,又稱“縮小增量排序”,希爾排序是直接插入排序算法的一種更高效的改進版本,關於插入排序可以看下這篇隨筆:插入排序——C語言
(圖片來源:https://www.cnblogs.com/fivestudy/p/10212306.html)
1、希爾排序的基本思想:
設待排序元素序列有n個元素,首先取一個整數increment(小於n)作為間隔將全部元素分為n/increment個子序列,所有距離為increment的元素放在同一個子序列中,在每一個子序列中分別實行直接插入排序,然后縮小間隔increment,重復上述子序列划分和排序工作,直到最后取increment=1,將所有元素放在同一個子序列中排序為止,該方法實質上是一種分組插入方法
{1,2,4,8,...}這種序列並不是很好的增量序列,使用這個增量序列的時間復雜度(最壞情形)是O(n^2)
Hibbard提出了另一個增量序列{1,3,7,...,2^k-1},這種序列的時間復雜度(最壞情形)為O(n^1.5)
Sedgewick提出了幾種增量序列,其最壞情形運行時間為O(n^1.3),其中最好的一個序列是{1,5,19,41,109,...}
3、代碼實現
1 /* 希爾排序*/
2 int num[5] = {3, 7, 1, 8, 5}; 3 int cur; 4 int i, j; 5 int length = sizeof(num)/sizeof(num[0]); 6 int incre; 7
8 incre = length / 2; 9
10 while (incre >= 1) 11 { 12 for (i = incre; i < length; i++) 13 { 14 cur = num[i]; //待排序元素
15 for (j = i - incre; j >= 0 && num[j] > cur; j = j - incre) 16 { 17 num[j + incre] = num[j]; //元素向后移動
18 } 19 num[j + incre] = cur; //插入待排序元素
20 } 21 incre = incre / 2; //增量減半
22 }
while里面的代碼其實和插入排序的代碼沒多大區別,就是在兩個for循環外面套了一個while再修改了一下內部的for循環,可以對照看一下下面列出來的插入排序的for循環
1 for (i = 1; i < length; i++) 2 { 3 cur = num[i]; //待排序元素
4 for (j = i - 1; j >= 0 && num[j] > cur; j--) 5 { 6 num[j + 1] = num[j]; 7 } 8 num[j + 1] = cur; 9 }
4、排序過程(以5,7,8,3,1,2,4,6為例)
每個分組進行插入排序后,各個分組就變成了有序的了(整體不一定有序)
此時,整個數組變的部分有序了(有序程度可能不是很高)
然后縮小增量為上個增量的一半:2,繼續划分分組,此時,每個分組元素個數多了,但是,數組變的部分有序了,插入排序效率同樣比高
同理對每個分組進行排序(插入排序),使其每個分組各自有序
最后設置增量為上一個增量的一半:1,則整個數組被分為一組,此時,整個數組已經接近有序了,插入排序效率高
同理,對這僅有的一組數據進行排序,排序完成
(圖片來源:https://blog.csdn.net/qq_39207948/article/details/80006224)
參考鏈接: