当前位置:   article > 正文

算法-希尔排序算法(四)_希尔排序算法假设第一次是四

希尔排序算法假设第一次是四

大家端午节安康,这两天都忙着玩了。没什么时间写技术博客。不过定好的计划一定要努力完成。
这次给大家介绍一下希尔排序算法,其实这是建立在插入排序之上的一种排序算法。当然,作为一个程序员,我们听到诸如:“建立在XX之上”,“是XXX的改进版”,“继XXX后,XXXX横空出世”这些句子,本能会思考旧东西的缺点,新东西的优点,新东西解决了旧东西什么问题。那么插入排序有什么问题呢?

插入排序之殇

如果仔细看过前面介绍插入排序算法的小伙伴,肯定知道插入排序是要移动元素的位置,将合适的元素插入至合适的位置。那么问题就来了,如果要对大量的数据排序,岂不是插入一次,要挪动大量的元素?插入排序在面对大量的数据时,效率十分慢。而希尔排序,就是插入排序的优化版,能在面对大量数据时也保持效率。

希尔排序定义

希尔排序(shell sort)这个排序方法又称为缩小增量排序,是1959年D·L·Shell提出来的。该方法的基本思想是:设待排序元素序列有n个元素,首先取一个整数increment(小于n)作为间隔将全部元素分为increment个子序列,所有距离为increment的元素放在同一个子序列中,在每一个子序列中分别实行直接插入排序。然后缩小间隔increment,重复上述子序列划分和排序工作。直到最后取increment=1,将所有元素放在同一个子序列中排序为止。
由于开始时,increment的取值较大,每个子序列中的元素较少,排序速度较快,到排序后期increment取值逐渐变小,子序列中元素个数逐渐增多,但由于前面工作的基础,大多数元素已经基本有序,所以排序速度仍然很快。

其实看图就比看文字更好理解:
假设我们有一个数组如下,我们第一次排序时,取间隔为4的数,那么数组便分成了下标为04,16,27,3的几组数,先对这几组分别排序。排好之后,我们再取间隔为2的数,那么数组分成了,0246与1357两组数,最后我们取间隔为1的数,这相当于一次插入排序。

在这里插入图片描述在这里插入图片描述在这里插入图片描述
注意,我们在一开始取间隔取得很大,目的就是做元素之间的快速移动,避免长距离的移动元素,随着后面间隔越来越小,但因为长距离间隔的元素已经是有序的了,所以不会存在下标第99999的需要插入到下标为2的元素位置上。

时间复杂度

灰常遗憾,希尔的时间复杂度至今仍然不确定,因为对应不通的间隔,时间复杂度是不一样的
希尔排序的复杂度和增量序列是相关的:

{1,2,4,8,…}这种序列并不是很好的增量序列,使用这个增量序列的时间复杂度(最坏情形)是O(n^2)

Hibbard提出了另一个增量序列{1,3,7,…,2^k-1},
这种序列的时间复杂度(最坏情形)为O(n^1.5)

Sedgewick提出了几种增量序列,其最坏情形运行时间为O(n^1.3),其中最好的一个序列是{1,5,19,41,109,…}

代码实现

    /**
     * 希尔排序 
     * @param arr 目标序列
     */
    public static void shellSort(int[] arr){
        int len = arr.length;
        for(int gap=len/2; gap>=1; gap=gap/2){  //拆分整个序列,元素间距为gap(也就是增量)
            //对子序列进行直接插入排序
            for(int i=gap+1; i<len; i++){
                for(int j=i-gap; j>=0&&arr[j]>arr[j+gap]; j=j-gap){        
                    swap(arr,j,j+gap);
                }
            }
        }
    }    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/886019
推荐阅读
相关标签
  

闽ICP备14008679号