希爾排序(shell sort)是插入排序的一種。也稱縮小增量排序,是直接插入排序演算法的一種更高效的改進版本。希爾排序是非穩定排序演算法。該方法因dl.shell於2023年提出而得名。
先將整個待排序的記錄序列分割成為若干子串行分別進行直接插入排序,待整個序列中的記錄「基本有序」時,再對全體記錄進行依次直接插入排序。
選擇乙個增量序列t1,t2,…,tk,其中ti>tj,tk=1;
按增量序列個數k,對序列進行k 趟排序;
每趟排序,根據對應的增量ti,將待排序列分割成若干長度為m 的子串行,分別對各子表進行直接插入排序。僅增量因子為1 時,整個序列作為乙個表來處理,表長度即為整個序列的長度。
增量序列d = n為要排序數的個數
說明:先將要排序的一組記錄按某個增量d(n/2,n為要排序數的個數)分成若干組子串行,每組中記錄的下標相差d。對每組中全部元素進行直接插入排序,然後再用乙個較小的增量(d/2)對它進行分組,在每組中再進行直接插入排序。繼續不斷縮小增量直至為1,最後使用直接插入排序完成排序。
**
#include
#define n 9
int arr[n]=;
int step=0;
int nmove=0; /* 移動次數 */
int nfor=0; /* 迴圈次數 */
int ncompare=0; /* 比較次數 */
void print(int dk)
/* 增量序列t1,t2,…,tk,k趟排序 */
void stepsort(int dk)
arr[j]=tmp; /* 在位置j插入第i個元素 */
}ncompare++;
print(dk);
}}void sort()
}void main()
結果
before...
no.0 dk=0 9 1 5 7 6 3 2 8 4 nnfor: 0 move: 0 ncompare: 0
sorting...
no.1 dk=4 6 1 5 7 9 3 2 8 4 nnfor: 1 move: 1 ncompare: 1
no.1 dk=4 6 1 5 7 9 3 2 8 4 nnfor: 2 move: 1 ncompare: 2
no.1 dk=4 6 1 2 7 9 3 5 8 4 nnfor: 3 move: 2 ncompare: 3
no.1 dk=4 6 1 2 7 9 3 5 8 4 nnfor: 4 move: 2 ncompare: 4
no.1 dk=4 4 1 2 7 6 3 5 8 9 nnfor: 5 move: 4 ncompare: 6
no.2 dk=2 2 1 4 7 6 3 5 8 9 nnfor: 6 move: 5 ncompare: 7
no.2 dk=2 2 1 4 7 6 3 5 8 9 nnfor: 7 move: 5 ncompare: 8
no.2 dk=2 2 1 4 7 6 3 5 8 9 nnfor: 8 move: 5 ncompare: 9
no.2 dk=2 2 1 4 3 6 7 5 8 9 nnfor: 9 move: 6 ncompare:10
no.2 dk=2 2 1 4 3 5 7 6 8 9 nnfor:10 move: 7 ncompare:11
no.2 dk=2 2 1 4 3 5 7 6 8 9 nnfor:11 move: 7 ncompare:12
no.2 dk=2 2 1 4 3 5 7 6 8 9 nnfor:12 move: 7 ncompare:13
no.3 dk=1 1 2 4 3 5 7 6 8 9 nnfor:13 move: 8 ncompare:14
no.3 dk=1 1 2 4 3 5 7 6 8 9 nnfor:14 move: 8 ncompare:15
no.3 dk=1 1 2 3 4 5 7 6 8 9 nnfor:15 move: 9 ncompare:16
no.3 dk=1 1 2 3 4 5 7 6 8 9 nnfor:16 move: 9 ncompare:17
no.3 dk=1 1 2 3 4 5 7 6 8 9 nnfor:17 move: 9 ncompare:18
no.3 dk=1 1 2 3 4 5 6 7 8 9 nnfor:18 move:10 ncompare:19
no.3 dk=1 1 2 3 4 5 6 7 8 9 nnfor:19 move:10 ncompare:20
no.3 dk=1 1 2 3 4 5 6 7 8 9 nnfor:20 move:10 ncompare:21
sorted.
增量序列的選擇
shell排序的執行時間依賴於增量序列。好的增量序列的共同特徵:
a. 最後乙個增量必須為1;
b. 應該盡量避免序列中的值(尤其是相鄰的值)互為倍數的情況。有人通過大量的實驗,給出了較好的結果:當n較大時,比較和移動的次數約在nl.25到1.6n1.25之間。
shell排序的時間效能優於直接插入排序
希爾排序在效率上較直接插入排序有較大的改進,希爾排序的時間效能優於直接插入排序的原因:
a. 當檔案初態基本有序時直接插入排序所需的比較和移動次數均較少。
b. 當
n 值較小時,n和
n2的差別也較小,即直接插入排序的最好時間複雜度o(
n)和最壞時間複雜度0(
n2) 差別不大。
c. 在希爾排序開始時增量較大,分組較多,每組的記錄數目少,故各組內直接插入較快,後來增量di逐漸縮小,分組數逐漸減少,而各組的記錄數目逐漸增多,但由於已經按di-1作為距離排過序,使檔案較接近於有序狀態,所以新的一趟排序過程也較快。
希爾增量:ht
=n/2
,h[k
]=h[
k+1]
/2,即n/
2,(n
/2)/
2,..
.,1 ,其餘的增量序列還有hi
bbar
d:1,
3,..
.,2k
−1,se
dgew
ick:
1,5,
19,41,
109...
該序列中的項或者是9∗
4i−9
∗2i+
1 或者是4i
−3∗2
i+1 。希爾排序的時間複雜度與增量序列的選取有關,例如希爾增量時間複雜度為o(
n2) ,而hibbard增量的希爾排序的時間複雜度為o(
n3/2
) ,希爾排序時間複雜度的下界是
nlog2n
。希爾排序是按照不同步長對元素進行插入排序,當剛開始元素很無序的時候,步長最大,所以插入排序的元素個數很少,速度很快;當元素基本有序了,步長很小,插入排序對於有序的序列效率很高。所以,希爾排序的時間複雜度會比o(
n2) 好一些。希爾排序沒有快速排序演算法快 o(
n(logn))
,因此中等大小規模表現良好,對規模非常大的資料排序不是最優選擇。但是比o(
n2) 複雜度的演算法快得多。並且希爾排序非常容易實現,演算法**短而簡單。 此外,希爾演算法在最壞的情況下和平均情況下執行效率相差不是很多。
希爾排序方法是乙個不穩定的排序方法。
插入排序 希爾插入排序
本文借鑑於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 ...