Java算法与数据结构--希尔排序

1.希尔排序的产生

希尔排序是基于插入排序的,插入排序步长为1的,而插入排序的步长是计算出来的。(学习希尔排序之前需要了解插入排序)。

2.插入排序的缺陷

步长为1的插入排序,必须得移动多次,举个栗子,假如一个很小的数据在考右侧的位置上,那么要讲该数据排序到正确的位置上,则所有中间数据都需要向右移动一次。

3.希尔排序的优点

希尔排序通过加大插入排序中元素之间的间隔(步长),并对这些间隔的元素进行排序,从而使得数据可以大幅度的移动,当完成该间隔的排序后,希尔排序会减少数据的间隔再进行排序,依次进行下去。

4.排序过程:

       待排序数组:48,  37  ,64,  96,  75,  12,  26,  48,  54,  03

       步骤一:选一个小于n(就是你的数组长度)的数字(比如选5),然后按照这个数来分组,即第一个和隔5个数之后的数字分为一组。在这个例子里:48和隔个5个数的12为一组,因为12后面不够5个数了,所以这个分组就到这了。

      分组情况:

              

       步骤二:将第一开始的分组的数字以直接插入的方式,按照从小到大的排序(也可以按照从大到小来)

                   12,26,45,54,03,48,37,64,98,75

     

   步骤三:由于第二部进行了排序,在这个基础上,再一次选一个小于 d1的数字,d2,以这个数字分组,这次以d2=3举例

       因此,第二次的分组情况如下:

         

     

步骤四:将刚刚分完组的数字,进行组内排序,还是以直接插入排序,所以排序之后结果是下面的情况:

     12,03,45,37,26,48,54,64,75

步骤五:这次还要选一个数字d3作为分组的标准,第一,二两次分别用的5,3,这次用d3=1。也就是说这次可以直接整体用直接插入排序了。

       

     

步骤六:直接插入排序结果为:03,12,26,37,45,48,54,64,75

5.步长的计算

步长h的初始值为1,通过公式:h=3*h+1来循环计算,知道该间隔大于数组的大小时停止。 
,h取值为(1,4,13,40…)

6.步长减少计算

通过公式:h=(h-1)/3

7.讲解代码

    public static void sort(long[] arr) {
        //初始化一个间隔
        int h = 1;
        //计算最大间隔
        while(h < arr.length / 3) {
            h = h * 3 + 1;
        }

        while(h > 0) {
            //进行插入排序
            long tmp = 0;
            for(int i = h; i < arr.length; i++) {
                tmp = arr[i];
                int j = i;
                while(j > h - 1 && arr[j - h] >= tmp) {
                    arr[j] = arr[j - h];
                    j -= h;
                }
                arr[j] = tmp;
            }
            //减小间隔
            h = (h - 1) / 3;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_30904985/article/details/82261140