希爾排序(shell sort)也是一種插入排序演算法,希爾排序是d.l.shell於2023年提出的。
希爾排序採用的是分組插入的思想:
1. 設現在有乙個序列:,先取定乙個小於n的整數di作為乙個增量,把序列中的全部記錄分組成di個子序列,所有間隔為di的記錄放在同乙個子串行,然後在每個子串行內進行直接插入排序。
2. 然後取第二個增量d2(<d1),重複上述的分組和排序,直至所取的增量dt = 1 (d1>d2> … >dt-1>dt),即所有記錄放在同一組中進行直接插入排序為止。
也就是說,希爾排序的思想是將乙個記錄了大量資料的序列進行分組,分成多個子串行,然後再對這多個子串行內進行直接插入排序。這裡提到了希爾排序會將乙個序列分成多個子串行,那麼是怎麼分組呢?接下來我們通過乙個示例來說明希爾排序的原理。
希爾排序的過程:
圖1如圖1所示,現在有這樣乙個待排序列,根據希爾排序的思想,首先要做的就是將這個序列分組成多個子串行。
這裡我們對增量di取值為5,並將序列中所有間隔為5的元素放在同乙個子串行中
,比如,對於子串行來說,序列中16這個元素的間隔為5的元素是11,因此把11放在和16同乙個子串行中,下乙個跟16間隔為5的元素是31,那麼把31放在這個子串行中,最後形成了子串行。
從圖1來看,總共有分成5個子序列,不同的子串行用了不同的顏色來進行區分,同時我們還可以看出同乙個子串行中的每個元素之間的間隔都是5,例如子串行來說,25和23之間的間隔就是5,其他子串行也是如此。
圖2前面我們還說過,希爾排序對序列分組成多個子串行後,還需要對每個子串行進行直接插入排序。比如,對於子串行來說,排序前是乙個無序的子串行
,當排序完成後變成了乙個有序的子串行
了。
其他子串行也是如此:
排序前為,排序後為從圖2來看,當所有的子串行排序完畢後,都變成有序的了,但是從整個序列來看,還不是有序的,因此還要繼續排序。排序前為,排序後為
排序前為,排序後為
排序前為,排序後為
圖3重複上步驟,第二次增量di取值為2,分組完成後進行排序,然後第三次增量di取值為1,子串行已經組合成乙個序列,幾乎是有序的了,當排序完畢時,整個序列就變成完全有序的序列了。
通過希爾排序的整個過程來看,當增量di取值為2時,整個序列接近有序了,當增量di=1時,整個序列幾乎有序。隨著增量逐漸減少,每個序列中的記錄的元素也會越多,當增量為1時,所有的記錄分為乙個序列,排序結束後,就是乙個有序的序列。
需要注意的是:前面我們為了介紹希爾排序的原理,增量di
d
i的值是隨便取的,但是這並不代表增量di的值可以隨便取。也就是說,在定義增量di
d
i時,定義增量的序列為:dn
>dn
−1>..
.>d1
=1d
n>dn
−1>..
.>d1
=1,一般使用shell建議的序列:di
=n/2
d i=
n/2。
希爾排序演算法**如下:
#include
#include
#include
#define maxsize 8
typedef
int keytype; //定義關鍵字型別
typedef
int infotype;
typedef
struct
//記錄型別
rectype; //排序的記錄型別定義
/*希爾排序
引數說明:
arr:傳入要排序的陣列
n:陣列的大小
*/void shellsort(rectype r , int n)
r[j].key = temp.key;
}//增量每次取di=n/2
gap /= 2;
}}int main(void)
; int arr = ;
int i;
printf("--------排序前--------\n");
for(i = 0; i < maxsize; i++)
//希爾排序
shellsort(r, maxsize);
printf("--------排序後--------\n");
for(i = 0; i < maxsize; i++)
return
0;}
測試結果:
相信希爾排序的思想不難理解,但是希爾排序演算法的時間複雜度分析反而十分複雜,這裡我們只需直接記住結論即可,希爾排序的時間複雜度大約為:o(
n1.3
) o(n
1.3)
,而直接插入排序的時間複雜度是o(
n2) o(n2)。
那麼希爾排序演算法為什麼比直接插入排序好呢?假設現在要對10個元素進行排序。
如果使用直接插入排序,大約花費的時間為 =10
2=100 =102
=100
。如果使用希爾排序,當增量di = 5時,分為5組,時間為5×
22=20
5 ×2
2=20。當增量di = 2時,分為2組,時間為2×
52=50
2 ×5
2=50。當di = 1時,分為1組,此時幾乎是有序的,時間約為10,然後把每個分組的時間都加起來,總的時間約為20+
50+10=
80 20+50
+10=80
。希爾排序是一種不穩定的排序演算法,例如:
圖4把這個序列分為2組子串行,用不同顏色區分,然後對著兩組子串行進行直接插入排序,從排序完後的結果我們可以發現,這兩組子串行中的8的位置相對於原來的位置已經發生了改變,所以希爾排序是乙個不穩定排序
。
插入排序 希爾插入排序
本文借鑑於lsgo實驗室創始人馬老師 演算法 希爾插入排序 delta len nums 2 while delta 0 shell delta,nums delta delta 2return nums defshell delta,key for i in range delta,len key...
插入排序 希爾排序
我們知道當乙個序列基本有序時,直接插入會變得很高效。因為此時只需少量的移動元素,操作集中在元素的比較上。基於這種想法,我們就試圖把乙個序列在進行直接插入前調整得盡量有序。這就是希爾排序 shell sort 的核心思路。shell只是演算法發明者的名字,無特殊含義 那到底該怎麼做呢?希爾排序一反以前...
插入排序 希爾排序
希爾排序 先將整個待排序的記錄序列分割成為若干子串行分別進行直接插入排序,待整個序列中的記錄 基本有序 時,再對全體記錄進行依次直接插入排序。以n 10的乙個陣列49,38,65,97,26,13,27,49,55,4為例 第一次 gap 10 2 5 4938 6597 2613 2749554 ...