希尔排序

来源:互联网 发布:戴尔win10激活windows 编辑:程序博客网 时间:2024/05/17 06:33
希尔排序(Shell Sort)插入排序的一种。是针对直接插入排序算法的改进。该方法又称缩小增量排序,因DL.Shell于1959年提出而得名。先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止(即最后一趟为直接插入排序)。

希尔排序是基于插入排序的以下两点性质而提出改进方法的:
1.插入排序在对几乎已经排好序的数据操作时, 效率高, 即可以达到线性排序的效率

2.但插入排序一般来说是低效的, 因为插入排序每次只能将数据移动一位

算法分析
1.增量序列的选择

     Shell排序的执行时间依赖于增量序列。
     好的增量序列的共同特征:
  ① 最后一个增量必须为1;
  ② 应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况。
     有人通过大量的实验,给出了目前较好的结果:当n较大时,比较和移动的次数约在nl.25到1.6n1.25之间。
2.Shell排序的时间性能优于直接插入排序
     希尔排序的时间性能优于直接插入排序的原因:
  ①当文件初态基本有序时直接插入排序所需的比较和移动次数均较少。
  ②在希尔排序开始时增量较大,分组较多,每组的记录数目少,故各组内直接插入较快,后来增量di逐渐缩小,分组数逐渐减少,而各组的记录数目逐渐增多,但由于已经按di-1作为距离排过序,使文件较接近于有序状态,所以新的一趟排序过程也较快。
     因此,希尔排序在效率上较直接插人排序有较大的改进。
3.稳定性
     希尔排序是不稳定的。      


实现:

//ader为增量void ShellInsert(int arr[],int len,int ader){if(arr == NULL || len <= 0 || ader <= 0){return;}int i,j,temp;for(i = ader; i < len; i++){if(arr[i-ader] > arr[i]) {temp = arr[i];for(j = i-ader; j>=0 && temp < arr[j]; j-=ader){arr[j+ader] = arr[j];}arr[j+ader] = temp;}}}//dlta为增量序列,t为增量序列的长度void ShellSort(int arr[],int len,int dlta[],int t){for(int i = 0; i < t; i++){ShellInsert(arr,len,dlta[i]);//使用每个增量,进行直接插入排序}}

测试:

/****************************************希尔排序by Rowandjj2014/7/19****************************************/#include<iostream>using namespace std;//ader为增量void ShellInsert(int arr[],int len,int ader){if(arr == NULL || len <= 0 || ader <= 0){return;}int i,j,temp;for(i = ader; i < len; i++){if(arr[i-ader] > arr[i]) {temp = arr[i];for(j = i-ader; j>=0 && temp < arr[j]; j-=ader){arr[j+ader] = arr[j];}arr[j+ader] = temp;}}}//dlta为增量序列,t为增量序列的长度void ShellSort(int arr[],int len,int dlta[],int t){for(int i = 0; i < t; i++){ShellInsert(arr,len,dlta[i]);//使用每个增量,进行直接插入排序}}int main(){int i;int arr[] = {9,7,5,3,1,6,11,8,4};int dlta[] = {5,3,1};ShellSort(arr,9,dlta,3);for(i = 0; i < 9; i++){cout<<arr[i]<<" ";}cout<<endl;return 0;}

结果:




2 1
原创粉丝点击