希尔排序是1959 年由D.L.Shell 提出来的,相对直接排序有较大的改进。希尔排序又叫缩小增量排序
基本思想:
先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
操作方法:
- 选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;
- 按增量序列个数k,对序列进行k 趟排序;
- 每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
希尔排序的示例:
算法实现:
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,最后使用直接插入排序完成排序。