排序——希尔排序(来自曾经被其伤害过的人)

简介

希尔排序,又称缩小增量法。
过程:
先取定一个整数d1<n,把全部结点分成d1个组,所有距离为d1倍数的记录放在一组中,在各组内进行直接插入排序;然后取d2<d1,重复上述分组和排序工作,直至取di=1,即所有记录放在一个组中排序为止。

嗯,好了,上面的看一下就得了,不然就和我一样了,当我看明白了这行字的时候,感觉自己被学校ppt演的死去活来。。
其实就是选择一串数组,比如531,只要第一个小于数组长度且最后一个为1就行了。
然后要做的,就是按照数字分组:

  • a[0] a[5] a[10] a[15]……
  • a[1] a[6] a[11] a[16]……
  • a[2] a[7] a[12] a[17]……
  • a[3] a[8] a[13] a[18]……
  • a[4] a[9] a[14] a[19]……

每一组都是相差五个,所以产生了五组。
接下来就是将这五组数据排序好(使用的是插入排序)
下一个数字是3,所以按照间隔为3再次分组,排序,然后是1,就是一个完全的插入排序了。

那么可能会问,这怎么能实现高效呢,中间那么多次的插入。
其实在每一次的排序中,都是一小块一小块处理的,这样在处理大块的时候由于基本有序,所以插入排序还是很快的(上一篇提过,插入排序在基本有序的情况下是非常快的)

增量选择

增量,顾名思义指的就是上文提到的数组,看到上面的思路应该就知道了这个东西的重要性,甚至说增量的选择和这个算法一样重要,目前学到的最快的增量序列是1,5,19,41,109……

增量和算法的时间复杂度息息相关,该算法的时间复杂度范围为n*log2n到n2之间,n在一定范围内,时间复杂度为n1.3在这里插入图片描述
图中是一些巨佬们提出的一些序列。

代码实现

有人看到这就会问了,博主博主,你上面说了这么多种,现在你要讲的是哪种啊。
这个东西啊,讲一种剩下的就可以自己来了,所以,我就讲最简单的那种吧(咳咳,懂的都懂)

这里采用的是 n/2 开始,然后每一次都除二直到为1。
其中数组a[0]项并没有存储数值。

void Shellsort(int* a,int n)//数组&多少个数
{
    for(int k = n/2; k >= 1; k /= 2)//增量大小为除半
    {
        for(int i = k+1; i <= n; i++)//往后推保证了插入的顺序,同时能够遍历 
        {
            int x = a[i];
            int j = i-k;
            while(j>0 && x<a[j])
            {
                a[j+k] = a[j];
                j -= k;
            }
            a[j+k] = x;//组内排序,将x直接插入到组内合适的位置
        }
    }
}

这里面和刚才说的还是有所出入,至少不是将所有的分组都拿出来排序然后塞回去,
而是利用遍历直接将所有的组同时排好序:

  • 从第一组的第二个出发(因为插入算法就是从第二个元素开始的),即a[k+1];
  • 当数组下标 j 为正的时候(因为没有监视哨,所以每一次都要看一下是否越界)并且需要后移,就将j+k的位置上放上j,其实说白了就是用增量k替换了原来的1;
  • 随后i++,同时j++,进入下一组;、
  • 当到达第一组第三个数据,一切同上。

这个函数看起来还是有一些不好理解,单纯靠这个很难反推原来的想法,所以还是先看懂上面的思路吧(没错我当时也踩了这个雷,原地起飞,还好最后CSDN大佬捞我一把)

分析

希尔排序的时间复杂度在上面说过了,一言难尽,也是不确定的,但是空间复杂度却很好判断,因为没有使用和n有关的空间(比如数组),所以仍为o(1)。

另外,希尔排序是不稳定的,因为在划分组的时候很容易将两个相同的数据交换位置导致不稳定。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值