希爾排序的基本思想是將距離某個增量的記錄組成一個子序列,這樣才能保證在子序列內分別進行直接插入排序後的結果是基本有序而不是局部有序。
希爾排序算法代碼如下:
void ShellSort(SqList *L)
{
int i,j;
int increment = L->length;
do
{
increment = increment/3+1; //增量序列
for(i = increment + 1;i<L->length;i++)
{
if(L->r[i]<L->r[i - increment]) //將L->r[i]插入有序增量子表
{
L->r[0] = L->r[i]; //暫存在l->r[0]
for(j = i - increment;j > 0 && L->r[0]<L->r[j];j-=increment)
L->r[j + increment] = L->r[j]; //記錄後移,查找插入位置
L->r[j + increment] = L->r[0]; //插入
}
}
}
while(increment > 1);
}
1.程序開始運行時,此時我們假設傳入的SqList參數值爲length = 9,r[0] = {0,9,1,5,8,3,7,4,6,2}.這就是我們需要排序的序列。
2.第4行,變量increment就是那個增量,初始值讓他等於待排序的記錄數。
3.第5~19行是一個do循環,他終止條件是increment不大於1時,其實也就是增量爲1時就停止循環了。
4.第7行,這一句很關鍵,設置增量的距離,距離按照實際情況設定,執行完這裏後increment = 4.
5.第8~17行shi是一個for循環,i 從4 + 1 = 5 到 9 結束。
6.第10行,判斷r[i]與r[i - increment]的大小,r[5] = 3 小於r[1] = 9 ,滿足條件,第12行,將r[5] = 3暫存ru入r[0]中,第13~14行的循環只是爲了將r[1] = 9賦值給r[5]由於循環的增量是j-=increment,其實他就循環了一次,此時j = -3。第15行,再將r[0] = 3賦值給r[-3+4] = r[1] = 3,shi'事實上這一段代碼就幹了一件事,jiu'就是將第5位置的3和第一位置的9進行了交換。
7.循環繼續,i = 6,不滿足判斷條件,不交換數據。
8.循環繼續,i = 7,r[7] < r[3],交換兩者數據。
9.循環繼續,i = 8,r[8] < r[4],交換兩者數據。
10.循環繼續,i = 9,r[9] < r[5],交換兩者數據。有r[5] < r[1],交換兩者數據,
最終第一輪循環結束後,數組變爲r[] = {2,1,4,6,3,7,5,8,9},此時小的數2,1已經在前面了,大的數8,9已經在後面了,這就向基本有序靠近了一步,然後繼續循環,increment繼續減小,最終循環下來便會排序完成。
希爾排序複雜度:
時間複雜度O爲n的3/2次方,由於記錄是跳躍式的移動,希爾排序並不是一種有序的排序方法。