希尔排序

作者: 云飞扬1 | 来源:发表于2020-08-06 10:14 被阅读0次

在这篇文章里专门讲过插入排序算法https://www.jianshu.com/p/5d071ca9a039,我们再回顾一下其排序过程:

插入排序.png

可以看到图中,第4轮插入时数组为 [3, 4, 5, 6, 0],需要将 0 插入到前面的有序数组中,你会发现0是最小的数据,最后要经过 4 轮比较才能将其插入到数组的第一个位置。我们可以得出一个规律:假设某种极端情况下,每轮插入时,待插入的数据与前面排好序的数据相比都是最小的,那么每轮都要比较完所有的数据,但反之,待插入数据与其前面有序数据相比都是最大的,则只需要比较一次。这都是极端情况,但是如果数组后面的数据都比较小,则要比较的次数肯定多,要经过很多次数据挪移操作,那么我们有没什么方法,尽可能快地将数组后面的小数据搬移到数组前面呢?这样就能减少数据比较搬移操作,以提升效率。

答案是肯定的,它就是希尔排序,希尔排序是直接插入排序的一种优化方案。假设数组有 n 条数据,并且第 n 条数据是数组里最小的。要将第 n 条数据交换到最前面,必然要比较 n -1 次,但是如果我们最先开始隔 n/2 个数据进行比较呢,那么第 n 个数据要搬移到最前面,只需要 1 或者 2 次比较就能被搬移到数组比较靠前的位置了。

我们定义这个间隔数叫 gap,每次我们对数组中的 [0+a, gap+a, 2*gap+a, 3 * gap+a...](a < gap, a取值范围[0, gap)) 进行插入排序,保持数组中这些位置的元素是相对有序的。gap 最开始是一个比较大的值,做完一轮之后,再缩小 gap 的值重复执行,当 gap 缩小到 1 时,就退化成前面我们讲的选择排序了,但是这个时候我们已经将数组后面相对较小的数搬移到前面了,最后一轮插入排序时要进行比较以及数据挪移的次数会越来越少了。

看如下算法示意图(注意这并不是实际执行顺序,而是一个最终的效果示意):

希尔排序.png

在这里会进行多次插入排序,但每次排序的数据量是不一样的,gap 越大数据量越小,比较小的数据能尽快交换到数组前面。随着 gap 的递减,排序的数据量越大,但是这个时候需要比较的次数也会越来越少了。

最后上代码如下:

fun shellSort(array: IntArray?) {
    array ?: return
    if (array.isEmpty())
        return
    var gap = array.size / 2
    while (gap > 0) {
        for (i in gap until array.size) {
            var target = array[i]
            var j = i - gap
            while (j >= 0 && array[j] > target) {
                array[j + gap] = array[j]
                j -= gap
            }
            array[j + gap] = target
        }
        gap /= 2
    }
}

空间复杂度:O(1)
时间复杂度:O(n²)
希尔排序是不稳定的,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以希尔排序是不稳定的。

最后,关于 gap 值的选择,这里很粗暴的选择了 n/2 这样每次递减,但实际上这样并不是高效的,关于这个话题不在这里做讨论,网上有更详细的文章说明,这里只是了解这个算法的核心思想。

相关文章

  • 排序算法(二)之希尔排序

    图解排序算法(二)之希尔排序 希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法。希尔排序也...

  • 07-希尔排序(Shell Sort)

    希尔排序(Shell Sort) 希尔排序是唐纳德·希尔(Donald Shell)在0959年提出的。希尔排序与...

  • 排序-希尔排序(分治)

    希尔排序 希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。 希尔排序...

  • swift经典算法-希尔排序

    希尔排序 希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。 希尔排序...

  • 排序算法④——希尔排序

    希尔排序 希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。 希尔排序...

  • 排序算法-希尔排序(Java实现)

    希尔排序 希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是...

  • 说说算法那些事-希尔排序

    希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法。希尔排序也是一种插入排序,希尔排序法又称...

  • 希尔排序学习

    希尔排序希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。希尔排序是基...

  • 排序算法(四) 希尔排序(插入排序的进化)

    参考Java排序算法(四):希尔排序常见排序算法 - 希尔排序 (Shell Sort) 希尔排序算法是按其设计者...

  • 编程马拉松 Day04 希尔排序、归并排序、快速排序

    本文将介绍三个高级排序算法 希尔排序 归并排序 快速排序 希尔排序 希尔排序(Shell's Sort)的名称源于...

网友评论

    本文标题:希尔排序

    本文链接:https://www.haomeiwen.com/subject/vdkbrktx.html