希爾排序是1959 年由D.L.Shell 提出來的,相對直接排序有較大的改進。希爾排序又叫縮小增量排序
基本思想:
先将整個待排序的記錄序列分割成為若幹子序列分别進行直接插入排序,待整個序列中的記錄“基本有序”時,再對全體記錄進行依次直接插入排序。
操作方法:
- 選擇一個增量序列t1,t2,…,tk,其中ti>tj,tk=1;
- 按增量序列個數k,對序列進行k 趟排序;
- 每趟排序,根據對應的增量ti,将待排序列分割成若幹長度為m 的子序列,分别對各子表進行直接插入排序。僅增量因子為1 時,整個序列作為一個表來處理,表長度即為整個序列的長度。
希爾排序的示例:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZlBnauAzNklzMldzNwcDZjRDNjFjYkBTNhRmZ2kDZkRDMlJzMfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.jpeg)
算法實作:
01.void print(int a[], int n ,int i){
02. cout<<i <<":";
03. for(int j= 0; j<8; j++){
04. cout<<a[j] <<" ";
05. }
06. cout<<endl;
07.}
08./**
09. * 直接插入排序的一般形式
10. *
11. * @param int dk 縮小增量,如果是直接插入排序,dk=1
12. *
13. */
14.
15.void ShellInsertSort(int a[], int n, int dk) //直接排序
16.{
17. for(int i= dk; i<n; ++i){
18. if(a[i] < a[i-dk]){ //若第i個元素大于i-1元素,直接插入。小于的話,移動有序表後插入
19. int j = i-dk;
20. int x = a[i]; //複制為哨兵,即存儲待排序元素
21. a[i] = a[i-dk]; //首先後移一個元素
22. while(x < a[j]){ //查找在有序表的插入位置
23. a[j+dk] = a[j];
24. j -= dk; //元素後移
25. }
26. a[j+dk] = x; //插入到正确位置
27. }
28. print(a, n,i );
29. }
30.
31.}
32.
33./**
34. * 先按增量d(n/2,n為要排序數的個數進行希爾排序
35. *
36. */
37.void shellSort(int a[], int n)//希爾排序
{
38.
39. int dk = n/2;
40. while( dk >= 1 ){
41. ShellInsertSort(a, n, dk);
42. dk = dk/2;
43. }
44.}
45.int main(){
46. int a[8] = {3,1,5,7,2,4,9,6};
47. //ShellInsertSort(a,8,1); //直接插入排序
48. shellSort(a,8); //希爾插入排序
49. print(a,8,8);
50.}
單處理增量序列:增量序列d = {n/2 ,n/4, n/8 .....1} n為要排序數的個數
即:先将要排序的一組記錄按某個增量d(n/2,n為要排序數的個數)分成若幹組子序列,每組中記錄的下标相差d.對每組中全部元素進行直接插入排序,然後再用一個較小的增量(d/2)對它進行分組,在每組中再進行直接插入排序。繼續不斷縮小增量直至為1,最後使用直接插入排序完成排序。