希尔排序(shell)
2015-08-28 22:44
411 查看
希尔排序O(nlogn)
希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因DL.Shell于1959年提出而得名。
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
不需要大量的辅助空间,和归并排序一样容易实现。希尔排序是基于插入排序的一种算法,
在此算法基础之上增加了一个新的特性,提高了效率。希尔排序的时间复杂度与增量序列的选取有关,例如希尔增量时间复杂度为O(n²),而Hibbard增量的希尔排序的时间复杂度为O(
![](http://f.hiphotos.baidu.com/baike/s%3D19/sign=aa2de37b8882b90139adc73a728da776/11385343fbf2b211f6c24d12c88065380dd78efa.jpg)
),希尔排序时间复杂度的下界是n*log2n。希尔排序没有快速排序算法快 O(n(logn)),因此中等大小规模表现良好,对规模非常大的数据排序不是最优选择。但是比O(
![](http://d.hiphotos.baidu.com/baike/s%3D16/sign=01af9b540ed79123e4e09072ac34c0d3/b812c8fcc3cec3fd372c6c29d488d43f87942758.jpg)
)复杂度的算法快得多。并且希尔排序非常容易实现,算法代码短而简单。 此外,希尔算法在最坏的情况下和平均情况下执行效率相差不是很多,与此同时快速排序在最坏的情况下执行的效率会非常差。专家们提倡,几乎任何排序工作在开始时都可以用希尔排序,若在实际使用中证明它不够快,再改成快速排序这样更高级的排序算法.
本质上讲,希尔排序算法是直接插入排序算法的一种改进,减少了其复制的次数,速度要快很多。 原因是,当n值很大时数据项每一趟排序需要的个数很少,但数据项的距离很长。当n值减小时每一趟需要和动的数据增多,此时已经接近于它们排序后的最终位置。
正是这两种情况的结合才使希尔排序效率比插入排序高很多。Shell算法的性能与所选取的分组长度序列有很大关系。只对特定的待排序记录序列,可以准确地估算关键词的比较次数和对象移动次数。想要弄清关键词比较次数和记录移动次数与增量选择之间的关系,并给出完整的数学分析,至今仍然是数学难题。
1.增量序列的选择
Shell排序的执行时间依赖于增量序列。
好的增量序列的共同特征:
① 最后一个增量必须为1;
② 应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况。
有人通过大量的实验,给出了较好的结果:当n较大时,比较和移动的次数约在nl.25到1.6n1.25之间。
2.Shell排序的时间性能优于直接插入排序
希尔排序的时间性能优于直接插入排序的原因:
①当文件初态基本有序时直接插入排序所需的比较和移动次数均较少。
②当n值较小时,n和
![](http://d.hiphotos.baidu.com/baike/s%3D16/sign=01af9b540ed79123e4e09072ac34c0d3/b812c8fcc3cec3fd372c6c29d488d43f87942758.jpg)
的差别也较小,即直接插入排序的最好时间复杂度O(n)和最坏时间复杂度0(
![](http://d.hiphotos.baidu.com/baike/s%3D16/sign=01af9b540ed79123e4e09072ac34c0d3/b812c8fcc3cec3fd372c6c29d488d43f87942758.jpg)
)差别不大。
③在希尔排序开始时增量较大,分组较多,每组的记录数目少,故各组内直接插入较快,后来增量di逐渐缩小,分组数逐渐减少,而各组的记录数目逐渐增多,但由于已经按di-1作为距离排过序,使文件较接近于有序状态,所以新的一趟排序过程也较快。
因此,希尔排序在效率上较直接插入排序有较大的改进。
由于visualgo上没有希尔排序的视频,我只能在这里简单举个例子了。。。。。(为毛你没有希尔的)
arr[] = {5, 4, 3, 2, 1};
5 / 2 = 2;
5 4 3
2 1
1A 1A 1A
2A 2A
一样字母的是一组,归为一组后进行插入排序,
1 2 3
4 5
由于取的数字实在是很特殊经过一次希尔排序就成功了。
稍微改进一下
希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因DL.Shell于1959年提出而得名。
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
优劣:
不需要大量的辅助空间,和归并排序一样容易实现。希尔排序是基于插入排序的一种算法,在此算法基础之上增加了一个新的特性,提高了效率。希尔排序的时间复杂度与增量序列的选取有关,例如希尔增量时间复杂度为O(n²),而Hibbard增量的希尔排序的时间复杂度为O(
![](http://f.hiphotos.baidu.com/baike/s%3D19/sign=aa2de37b8882b90139adc73a728da776/11385343fbf2b211f6c24d12c88065380dd78efa.jpg)
),希尔排序时间复杂度的下界是n*log2n。希尔排序没有快速排序算法快 O(n(logn)),因此中等大小规模表现良好,对规模非常大的数据排序不是最优选择。但是比O(
![](http://d.hiphotos.baidu.com/baike/s%3D16/sign=01af9b540ed79123e4e09072ac34c0d3/b812c8fcc3cec3fd372c6c29d488d43f87942758.jpg)
)复杂度的算法快得多。并且希尔排序非常容易实现,算法代码短而简单。 此外,希尔算法在最坏的情况下和平均情况下执行效率相差不是很多,与此同时快速排序在最坏的情况下执行的效率会非常差。专家们提倡,几乎任何排序工作在开始时都可以用希尔排序,若在实际使用中证明它不够快,再改成快速排序这样更高级的排序算法.
本质上讲,希尔排序算法是直接插入排序算法的一种改进,减少了其复制的次数,速度要快很多。 原因是,当n值很大时数据项每一趟排序需要的个数很少,但数据项的距离很长。当n值减小时每一趟需要和动的数据增多,此时已经接近于它们排序后的最终位置。
正是这两种情况的结合才使希尔排序效率比插入排序高很多。Shell算法的性能与所选取的分组长度序列有很大关系。只对特定的待排序记录序列,可以准确地估算关键词的比较次数和对象移动次数。想要弄清关键词比较次数和记录移动次数与增量选择之间的关系,并给出完整的数学分析,至今仍然是数学难题。
时间性能
1.增量序列的选择Shell排序的执行时间依赖于增量序列。
好的增量序列的共同特征:
① 最后一个增量必须为1;
② 应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况。
有人通过大量的实验,给出了较好的结果:当n较大时,比较和移动的次数约在nl.25到1.6n1.25之间。
2.Shell排序的时间性能优于直接插入排序
希尔排序的时间性能优于直接插入排序的原因:
①当文件初态基本有序时直接插入排序所需的比较和移动次数均较少。
②当n值较小时,n和
![](http://d.hiphotos.baidu.com/baike/s%3D16/sign=01af9b540ed79123e4e09072ac34c0d3/b812c8fcc3cec3fd372c6c29d488d43f87942758.jpg)
的差别也较小,即直接插入排序的最好时间复杂度O(n)和最坏时间复杂度0(
![](http://d.hiphotos.baidu.com/baike/s%3D16/sign=01af9b540ed79123e4e09072ac34c0d3/b812c8fcc3cec3fd372c6c29d488d43f87942758.jpg)
)差别不大。
③在希尔排序开始时增量较大,分组较多,每组的记录数目少,故各组内直接插入较快,后来增量di逐渐缩小,分组数逐渐减少,而各组的记录数目逐渐增多,但由于已经按di-1作为距离排过序,使文件较接近于有序状态,所以新的一趟排序过程也较快。
因此,希尔排序在效率上较直接插入排序有较大的改进。
由于visualgo上没有希尔排序的视频,我只能在这里简单举个例子了。。。。。(为毛你没有希尔的)
arr[] = {5, 4, 3, 2, 1};
5 / 2 = 2;
5 4 3
2 1
1A 1A 1A
2A 2A
一样字母的是一组,归为一组后进行插入排序,
1 2 3
4 5
由于取的数字实在是很特殊经过一次希尔排序就成功了。
for (int gap = num/2;gap > 0;gap /= 2) { for (int i = 0;i < gap;i++) { for (int j = i+gap;j < num;j+=gap) { if (arr[j] < arr[j-gap]) { int temp = arr[j]; int k = j - gap; while (k >= 0 && arr[k] > temp) { arr[k + gap] = arr[k]; k -= gap; } arr[k + gap] = temp; } } } }
稍微改进一下
for (int gap = num / 2; gap > 0; gap /= 2) for (int j = gap; j < num; j++) if (arr[j] < arr[j - gap]){ int temp = arr[j]; int k = j - gap; while (k >= 0 && arr[k] > temp) { arr[k + gap] = arr[k]; k -= gap; } arr[k + gap] = temp; }
相关文章推荐
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法
- 基于C++实现的各种内部排序算法汇总
- C++线性时间的排序算法分析
- C++实现汉诺塔算法经典实例
- C++实现简单的希尔排序Shell Sort实例
- PHP实现克鲁斯卡尔算法实例解析