排序进阶——希尔排序(算法二)
Posted 可乐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序进阶——希尔排序(算法二)相关的知识,希望对你有一定的参考价值。
提升效率的本质在于少做事。
一. 序
之前介绍的入门排序方法,复杂度都是O(n²)。以这种复杂度去对大量数据排序显然是不可行的。即便是应付面试,也不太可能用冒泡排序、选择排序以及插入排序蒙混过关。
我们知道,插入排序的优点是针对比较有序的数据进行排序是相当高效的,缺点则是每次只移动一个数据。接下来,我们就针对插入排序的缺点,对其进行优化。
二. 插入排序回顾
首先看一下插入排序的实现,以数据7、8、3、5为例:
取第一个数7,肯定是有序的,不需要处理,得到7、8、3、5
取第二个数8,比7大放在7后面,得到7、8、3、5
取第三个数字3,分别与8、7比较,得到3、7、8、5
最后取5,分别与8、7、3相比,得到3、5、7、8
不难发现,几乎每个数字之间都做了比较。效率本身除了做事的速度,还取决于做事的量。想要更快的完成排序,计算机的速度可以看成是常量,可以优化的在于我们如何指导计算机少做事。
插入排序的优点是对基本有序的数据排序效率高,这给我们的启发便是想办法让一个比较无序的数组先变得比较有序。插入排序的缺点是一次只移动一个数据,优化的方向显然就是一次移动多个数据。
三. 希尔排序
由此,插入排序的进阶版本,希尔排序(Shell sort)被发明了出来。还是外国人的老套路,该算法以设计者希尔(Donald Shell)的名字命名,于1959年公布。
希尔排序首先把一串数据按照一定的间隔(Gap)分开,比如7、8、3、5按照间隔2分开,就变成了两个数组7、3和8、5,这样可以分别对这两个小的数组进行排序,变成3、7和5、8。放在原来的数组中看就变成了3、5、7、8。最后以1的间隔扫描一遍数据,不需要再移动任何数据。
一次搞定,牛叉不牛叉,哇塞不哇塞。
到此可以看出,希尔排序通过把数据按照一定的间隔分组,然后以小组为单位,在小组内使用插入排序,然后逐步缩小分组间隔,对于100个数据A1~A100,可以先按照50为间隔分成:
A1、A51
A2、A52
……
A50、A100
等50组,每组先进行插入排序。然后再以25为间隔,把数据分成25组,每组4个数据进行插入排序。以此类推,直到最后以1为间隔分成1个组,再做一次插入排序。
要注意的是,分组间隔里面间隔1是必选项,由它保证整个数据最后肯定是有序的。其余间隔如何选择是个很复杂的数学问题,简单的实现可以用待排序数据的个数不停除以2,直到最后间隔为1停止。
老规矩,算法一般来说与编程语言无关,因此这里依然用通俗易懂的伪码(Pseudocode):
[701, 301, 132, 57, 23, 10, 4, 1] =
foreach (gap in gaps)
{
gap; i < n; i += 1) =
{
a[i] =
i; j >= gap and a[j - gap] > temp; j -= gap) =
{
a[j - gap] =
}
temp =
}
}
四. 复杂度
希尔排序的时间复杂度是多少呢?不知道,我是认真的,确实不知道。希尔排序使用的分组间隔如果很小,分出来的组就少,每个组内需要比较的元素就很多;反之,如果间隔很大,每个组内需要比较的元素大幅减少,但是需要比较的组却大幅增加。很容易想到,分组间隔需要找到一个均衡。目前Sedgewick提出的(1, 5, 19, 41, 109,...)被认为是最好的分组间隔。该序列的项来自:
使用此序列,在小数组中比快速排序和堆排序还快,但是在涉及大量数据时希尔排序还是比快速排序慢。目前一般认为希尔排序的时间复杂度在O(n^(1.3~2))之间。由于希尔排序的复杂度与排序分组间隔的选择直接相关,目前还是个未解决问题(Open problem)。
说到排序,一般还会提到排序的稳定性。什么是稳定性呢?简单的讲,就是相同数据之间的相对位置是否会多次变动,如果会多次变动,就是不稳定的,否则就是稳定的。不难看出,希尔排序会使用不同的间隔多次排序,很可能多次移动同一数据,因此是不稳定的。
简单看一下插入排序和希尔排序的效率,以10000个随机数排序耗时为例:
耗时差了近200倍,这就是算法的魅力。有兴趣后台回复『希尔排序』获取源码。
五. 小结分析
希尔排序虽然不是速度最快的排序算法,但是希尔排序的应用极其广泛。原因主要有如下几点:
排序速度比较快,比插入排序等O(n²)的算法要好。
代码实现极其简单,且空间复杂度为O(1),排序过程仅需一个辅助存储变量。
虽然大部分情况下没有快速排序速度快,但是希尔排序在程序实现上不需要开栈操作,使用的空间极少,而快速排序则需要开辟大量的栈空间。
PS:加了底部广告,就不开赞赏了。
推荐:
推荐阅读:
后台回复『希尔排序』获取排序源码。
喜欢就『关注』或者『分享』吧。
以上是关于排序进阶——希尔排序(算法二)的主要内容,如果未能解决你的问题,请参考以下文章