动画:一篇文章快速学会希尔排序

内容介绍

希尔排序简介

冒泡排序在1956年就已经被研究。但是排序速度是比较慢的,冒泡排序的时间复杂度是O(n2),然而在后面的很长的时间里,尽管人们发明各种排序算法(比如前面选择排序和插入排序),但时间复杂度都是0(n2),时间复杂度似乎没法超越0(n2)。此时,计算机学术界充斥着“排序算法不可能突破O(n2)的声音”。终于有一天,当一位科学家发布超越了0(n2)新排序算法后,紧接着就出现了好几种可以超越0(n2)的排序算法,并把内排序算法的时间复杂度提升到了0(nlogn)。 “不可能超越0(n^2)”彻底成为了历史。

希尔排序按其设计者希尔(Donald Shell)的名字命名,该算法由1959年公布。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序,在这之前排序算法的时间复杂度基本都是0(n^2)的,希尔排序算法是突破这个时间复杂度的第一批算法之一。

前面讲的插入排序,它的效率在数据近乎有序时候是很高的,只需要少量的插入操作,就可以完成整个排序工作,此时直接插入很高效。还有就是数据比较少时,直接插入的优势也比较明显。可问题在于,两个条件本身就过于苛刻,实际开发中数据少或者基本有序都属于特殊情况。

不过别急,条件不存在,我们创造条件也是可以去做的。希尔排序(Shell’sSort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。该方法因D.L.Shell于1959年提出而得名。虽然插入排序是O(n^2)的排序复杂度,但是如果已经是有序的,则可以提前结束,可以提高效率我们知道插入排序在近乎有序的数组中效率很高, 如何让待排序的记录数量少并且近乎有序呢?很容易想到的就是将原本有大量记录数的记录进行分组。分割成若干个子序列,此时每个子序列待排序的记录个数就比较少了,然后在这些子序列内分别进行直接插入排序,当整个序列都基本有序时,注意只是基本有序时,再对全体记录进行一次直接插入排序。

有同学会疑惑。这不对呀,比如我们现在有个序列是{9, 1, 5, 8, 3, 7, 4, 6, 2},现在将它分成三组:{9, 1, 5},{8, 3, 7},{4, 6, 2},哪怕将它们各自排序排好了,变成{1, 5, 9},{3, 7, 8},{2,4,6}再合并它们成{1, 5, 9, 3, 7, 8, 2, 4, 6},此时,这个序列还是杂乱无序,谈不上基本有序,要排序还是重来一遍直接插入有序,这样做没有用。需要强调一下,所谓的基本有序,就是小的关键字基本在前面,大的基本在后面,不大不小的基本在中间,像{2, 1, 3, 6, 4, 7, 5, 8, 9}这样 可以称为基本有序了。但像{1, 5, 9, 3, 7, 8, 2, 4, 6} 这样的9在第三位,2在倒数第三位就谈不上基本有序。问题其实也就在这里,我们分割待排序记录的目的是减少待排序记录的个数,并使整个序列向基本有序发展。而像上面这样分完组后就各自排序的方法达不到我们的要求。因此,我们需要采取跳跃分割的策略:将相距某个“增量” 的记录组成一一个子序列,这样才能保证在子序列内分别进行直接插入排序后得到的结果是基本有序而不是局部有序。

希尔排序的思想

希尔排序,通过增量(gap)将元素两两分组,对每组使用直接插入排序算法排序;增量(gap)逐渐减少,当增量(gap)减至1时,整个数据恰被分成一组,最后进行一次插入排序,整个数组就有序了。

希尔排序动画演示

一般没有特殊要求排序算法都是升序排序,小的在前,大的在后。
数组由{7, 3, 1, 9, 5, 4, 2, 8, 6} 这9个无序元素组成。

第一次:gap = 9/2 = 4 动画:

第二次:gap = 4/2 = 2 动画:

第三次:gap = 2/2 = 1 动画:

希尔排序分析

希尔排序,通过增量(gap)将元素分成n组,对每组使用直接插入排序算法排序。增量(gap)逐渐减少,当增量(gap)减至1时,整个数据恰被分成一组,最后进行一次插入排序。

第一次:gap = 9/2 = 4,每个元素和后面的元素之间间隔4,元素被分成4组。其中元素7, 5, 6分成一组,元素3,4分成一组,元素1, 2分成一组,元素9,8分成一组,效果如下图:

第二次:gap = 4/2 = 2,每个元素和后面的元素之间间隔2,元素被分成2组。

第三次:gap = 2/2 = 1,每个元素和后面的元素之间间隔1,元素被分成1组。

希尔排序代码编写

回顾一下刚才的分析,当我们有9个元素时,gap分别取值4, 2, 1。

元素数量不同gap取值也不同,需要一个循环控制gap的取值。当取好gap后需要使用插入排序对每组进行排序,需要使用嵌套循环。
在进行小范围插入排序时,要注意从哪个位置开始。我们先回顾一下之前学习的插入排序,第一个元素6不需要动,从第二元素5开始才需要进行比较和插入。

希尔排序拆分成多个小组后,每个小组使用插入排序,也是从每个小组的第二个数据开始比较插入,如下图所示:

从上图中可以看出,第一组从索引4开始比

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值