希尔排序——排序算法


前言

经历上周元旦三天假期,这周又是双休,元气终于恢复了,如果不打游戏可能更好,索性又又又一次把游戏卸载了,工作以后想放松一下,发现打游戏并不是一个好的选择,打游戏反而让我更加的劳累了,刷刷视频又有负罪感,而且刷视频时间过得太快了,一个空间微视,一个B站,我最常用的两个刷一下就一天没了,还是控制不住,虽然B站也是用来学习的,经不住首页推荐呀,自己自制力太差了,有空还是多看看掘金和CSDN吧,至少看看文章会有收获。这周继续更一篇排序算法吧。


一、什么是希尔排序?

1959年Shell发明,第一个突破O(n2)的排序算法,是简单插入排序的改进版。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。我个人的理解而言,觉得希尔排序是通过不断的分组排序,从一开始的两个组别不断的二分下去成为多个小组,最后分组为1的时候也就是最后一次排序(此时已是插入排序,但是数组有序所以速度会快很多)。插入排序按照特定方法(步长为1)去执行,希尔排序调整了步长,分组跨越式的排序,从而做到比插入排序更加快一点,简而言之,插入排序是步长为1的希尔排序,希尔排序是插入排序的改进,所以学习希尔排序之前要先了解插入排序。

二、算法描述

算法步骤:

  1. 选择一个增量序列grap1,grap2,…,grapk,其中grapi>grapj,grapk=1;(所谓序列,就是每次分组的长度,在我的demo里面使用二分法作为增量序列)
  2. 按增量序列个数k,对序列进行k 趟排序;
  3. 每趟排序,根据对应的增量grapi,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

算法复杂度:

  • 时间复杂度:
    • 最好:O(n) 如果序列是已经排好的序列,则一次循环即可。
    • 最坏:O(n2)
    • 平均: O(n3/2)
  • 空间复杂度:O(1)
  • 稳定性:不稳定

三、JS代码实现

老规矩,懂前端的同学打开控制台(浏览器按F12键,现在好像都是f12吧)复制下面代码粘贴到控制台回车就可以运行看到结果了。(๑′ᴗ‵๑)。

代码如下(示例):

function shellSort(ary) {
    var len = ary.length;
    for (var grap = Math.floor(len / 2); grap > 0; grap = Math.floor(grap / 2)) {
        for (var i = grap; i < len; i++) {
            var j = i;
            var cur = ary[i];
            while (j - grap >= 0 && cur < ary[j - grap]) {
                ary[j] = ary[j - grap];
                j -= grap;
            }
            ary[j] = cur;
        }
    }
    return ary;
}
let ary = [9, 8, 7, 1, 2, 3, 6, 5, 4, 0];
console.log(shellSort(ary));

运行结果图:
希尔排序调试图


总结

希尔排序感觉需要自己去阅读代码,结合别人的解释才能理解算法中的思想,我刚开始看代码也是没转过弯了,这里希尔排序中分组是同时进行的,在算法中是每个小组的排序,一组组的和之前的排序比较,所以单看代码理解起来可能有点绕。我个人理解而言就是,先将序列划分成若干个小组分别排序,从局部有序逐渐的转变为全局有序。

——2021-1-10 22:45 晚安了,打工人。

今日份励志名言:

业精于勤,荒于嬉;行成于思,毁于随。
——韩愈·《进学解》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ZERO丶X

托马斯回旋360°飞旋感谢!!

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

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

打赏作者

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

抵扣说明:

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

余额充值