推薦視頻https://www.bilibili.com/video/av17004970/?from=search&seid=17055254545953111032
非常形象的演示了希爾排序的過程.
希爾排序嘗試與之前h個元素進行比較,這樣通過將h從一個很大的值逐漸縮小到1,一步步將一個無序數組變成有序性更強的數組。
參考zju-mooc-數據結構
圖中的注意是說,比如經過3間隔排序后的數組 依然滿足5間隔有序,同理經過1間隔排序后的數組依然是滿足3間隔有序的。
這個例子是說8間隔有序的話,那么4,2都可能有序,那么進行8,4,2間隔的排序就是一種浪費.
void shellSort(T arr[], int n){
//根據給定的數組大小n來計算對應遞增序列中的最大值
int h = 1;
while( h < n/3 )
h = h * 3 + 1;
/*
* 其實在這里我覺得應該添加這樣一段代碼:
* if(n == h)
* h /= 3;
* 因為當n等于h的話,進入下面的循環后 for( int i = h; i < n; i++ ) 會退出
* 不過知道就行了,實際上對性能沒什么影響
*/
// 計算 increment sequence: 1, 4, 13, 40, 121, 364, 1093...
while( h >= 1 ){
for( int i = h; i < n; i++ ){
// 對 arr[i], arr[i-h], arr[i-2*h], arr[i-3*h]... 使用插入排序
T e = arr[i];
int j;
for(j = i; j >= h && e < arr[j-h]; j -= h)
arr[j] = arr[j-h];
arr[j] = e;
}
h /= 3;
}
}
其他與前次代碼相同,測試結果為:
希爾排序非常高效.
希爾排序時間復雜度的分析是比較難的,我們選取不同的讓h遞減的序列,它的復雜度也是不同的.
increment sequence: 1, 4, 13, 40, 121, 364, 1093...使用這個序列 時間復雜度為O(n^3/2)
希爾排序的時間復雜度比O(n^2)要低,但比O(nlogn)要高一些,不過它的實現比較簡單.
不過對于排序算法來講它的最優時間復雜度是O(nlogn)這個級別的.