插入類排序的基本思路是在一個已經排好序的子記錄上,每一步將下一個待排序的記錄插入到已經排好序的記錄子集中,直到將全部待排序記錄所有插入爲止。算法
直接插入排序是最基本的插入排序算法,它的一趟操做是將第i個記錄插入到前面i-1個已經排好序的記錄中,在查找記錄i的插入位置時,也在進行元素的移動。假設有一個待排序隊列r[1,length],則整個排序過程須要n-1次趟。直接插入算法的實現以下:shell
1 |
void insSort( int *r, int length) |
2 |
{ |
3 |
int i, j; |
4 |
5 |
printf ( "Sorting:\n" ); |
6 |
for ( i = 2; i <= length; i++) { |
7 |
r[0] = r[i]; |
8 |
j = i - 1; |
9 |
10 |
while (r[0] < r[j]) { |
11 |
r[j + 1] = r[j]; |
12 |
j--; |
13 |
} |
14 |
15 |
r[j + 1] = r[0]; |
16 |
17 |
output(r, length); |
18 |
} |
19 |
} |
具體實現時,用一維數組來存儲待排序的序列,其中0號元素備份待插入的記錄。數組
折半插入排序法與直接插入法相似,區別在於肯定元素i插入的位置時利用折半查找法。每一趟排序的過程是先用折半查找法肯定插入位置,再逐個進行元素的移動。code
1 |
void binSort( int *r, int length) |
2 |
{ |
3 |
int i, j; |
4 |
int low ,high, mid; |
5 |
6 |
printf ( "Sorting:\n" ); |
7 |
for ( i = 2; i <= length; i++) { |
8 |
r[0] = r[i]; |
9 |
low = 1; |
10 |
high = i - 1; |
11 |
12 |
while (low <= high) { |
13 |
mid = (low + high) / 2; |
14 |
if (r[0] < r[mid]) |
15 |
high = mid - 1; |
16 |
else |
17 |
low = mid + 1; |
18 |
} |
19 |
20 |
for (j = i - 1; j >= low; j--) |
21 |
r[j + 1] = r[j]; |
22 |
r[high + 1] = r[0]; |
23 |
output(r, length); |
24 |
25 |
} |
26 |
} |
與直接插入法相似,數組r中的0號元素也備份了待插入的元素i。當肯定了記錄i的位置時,此時存在low=high+1這樣的關係,接下來將low到i-1之間的元素都後移一位,最終記錄i恰好插入空出來的位置中。排序
整個希爾排序的過程由若干次希爾插入組成,具體次數由增量數組delta中的元素個數n肯定。在每一次的希爾插入算法中,將待排序的記錄序列分紅d 個稀疏子序列,每一個稀疏子序列中元素之間的間隔正好爲d。希爾插入算法就是將每個子序列都按照直接插入法排列成有序,從而使得整個序列基本有序。上述過 程會重複n次,就是希爾排序算法的整個過程。隊列
1 |
void shellSort( int *r, int length, int *delta, int n) |
2 |
{ |
3 |
int i; |
4 |
for ( i = 0; i < n; i++) { |
5 |
shellInsert(r, length, delta[i]); |
6 |
} |
7 |
} |
第i趟希爾排序中,每一個稀疏子序列中元素的間隔由delta[i]決定。但希爾算法的最後一趟排序,元素的間隔必需是1。由於最後一次希爾排序就至關於直接插入排序,可是此時整個記錄序列已經幾乎有序,所以移動的次數會大大減小。for循環
1 |
void shellInsert( int *r, int length, int d) |
2 |
{ |
3 |
int i, j; |
4 |
int k; |
5 |
|
6 |
for (i = 1 + d; i <= length; i++) { |
7 |
if (r[i] < r[i - d]) { |
8 |
r[0] = r[i]; |
9 |
|
10 |
for (j = i - d; j > 0 && r[0] < r[j]; j -= d) { |
11 |
r[j + d] = r[j]; |
12 |
} |
13 |
r[j + d] = r[0]; |
14 |
} |
15 |
} |
16 |
output(r, length); |
17 |
} |
雖然希爾插入算法中須要依次將d個子序列排成有序,可是實際的實現過程卻從第一個子序列的第二個記錄(d+1)開始依次遍歷整個序列,由於每一個序列 中的元素都是由間隔d控制的,所以就至關於每一個子序列各自排序。內部的for循環至關於對每一個子序列進行直接插入排序,從當前的記錄i(保存在r[0] 中)開始,依次掃描當前子序列以前的元素(每一個元素的間隔爲d,所以每次循環j都減小d)以確保插入什麼時候的位置。table