【每天学一点 - 算法篇 - 排序 - 希尔排序】

系列文章目录

【每天学一点 - 算法篇 - 排序 - 插入排序】



前言

小时候听蛋炒饭

嘿,蛋炒饭,最简单也最困难 ----《蛋炒饭》

长大学希尔排序

希尔排序是算法非常简单且又极其复杂的分析的一个好例子 ----《数据结构与算法分析》


一、什么是希尔排序

希尔排序是最常用的叫法,但其实光说希尔排序确实不太容易记住它到底是怎么排序的,
毕竟希尔只是个人名,这个时候就要祭出它的学名 – 缩减增量排序
那缩减增量又是怎么排序的呢,
先进一段前情提要
【每天学一点 - 算法篇 - 排序 - 插入排序】
昨天刚写完插入排序,而增量缩减排序就是插入排序plus

二、原理

1.思路

那么这个插入排序plus又是怎么提升性能的呢?
因为插入排序是连续比较的,较差情况下每一个数都要跟前面所有的数比较一遍,那这时候希尔就想,我要是先间隔着比较,相当于我先做预排序,然后再进行插入排序会不会快一点呢
就是假设一个比较大的增量,相隔增量长度的数先进行一次插入排序,
然后逐步缩小这个增量,再次进行插入排序,
直到增量变成1的时候,进行玩插入排序,
最后的结果那就一定是有序队列了
这就是所谓的缩减增量排序

2.示例

在这里插入图片描述

3.抽象

要理解这个插入排序plus,要找到一点“分而治之”的感觉(实际并没有用到分治)
就是把整体先分好多组,让每个组都单独成为有序队列,
然后逐步减少分组数量,最后是整体成为有序队列

三、代码

实现方法

   public int[] shellSort(int[] a) {
        for (int gap = a.length / 2; gap > 0; gap /= 2) {
            for (int i = gap; i < a.length; i++) {
                int check = a[i];
                int j;
                for (j = i; j >= gap && check < a[j - gap]; j -= gap) {
                    a[j] = a[j - gap];
                }
                a[j] = check;
            }
        }
        return a;
    }

测试方法

  @Test
    public void shellSort() {
        int[] a = new int[]{3, 9, 5, 4, 8, 7, 1, 6, 2};
        System.out.println(Arrays.toString(new Sort().shellSort(a)));
    }

四、复杂度

这时候就到了 又极其复杂的分析 的部分了
首先说,仅从上面的操作上看,好像希尔排序跟插入排序也不是很看得出来谁的优势更大,谁能更快,毕竟你后面排序快的前提是进行了预排序,较差场景下还是每个数都跟其他的数分别比对了一遍。
那这个时候就要提到之前一直没有具体讲的增量缩减排序中的增量了,
诚然,如果只是单纯的二分取增量,时间复杂度跟插入排序不相上下,
但是老黑(hibbard,名字确实不好记,就叫老黑吧)提出了一个观点
如果增量缩减过程中,有三次的增量程线性关系,那就可以省出一次增量过程
比如三次的增量分别是3,5,13,
这时候3+2*5=13,那么13这次其实是可以省下来的,因为只用3和5排序就可以保证
第一个数<第四个数<第九个数<小于第十四个数,也就不需要13的那次排序了,
所以这个增量序列要没有公因子才行,老黑就提出了下面这个序列
1,3,7,,,,,2k-1
经证得时间复杂度为O(N3/2),证明过程等我学明白了再回来填坑
时光荏苒,岁月如梭,转眼就到了2022年,经过不断的实验与测试,人们又发现了一个效率更高的序列

{1,5,19,41,109,…},该序列中的项或者是94i-92i+1的形式,或者是4i-3*2i+1的形式。

这个序列也只是使用中发现效率更高,并不能实际证明出具体复杂度
现在也没有人证明出了希尔排序中效率最高的增量缩减序列
只能说希尔排序真不愧是 又极其复杂的分析 的排序算法

总结

并没能证明出希尔排序的复杂度,给自己埋个坑吧,争取尽快回来填上

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

破晓星芒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值