经典(Java版)排序算法的分析及实现之二希尔排

插入排序—希尔排序

希尔排序是1959 年由D.L.Shell 提出来的,相对直接插入排序有较大的改进。希尔排序的实质就是分组插入排序,该方法又称缩小增量排序。

基本算法:

先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高。步长的选择是希尔排序的重要部分。只要最终步长为1任何步长序列都可以工作。

算法最开始以一定的步长进行排序,然后会继续以一定步长进行排序,最终算法以步长为1进行排序。当步长为1时,算法变为插入排序,这就保证了数据一定会被排序。Donald Shell 最初建议步长选择为\frac{n}{2}并且对步长取半直到步长达到 1。虽然这样取可以比\mathcal{O}(n^2)类的算法(插入排序)更好,但这样仍然有减少平均时间和最差时间的余地。

希尔排序示例:n=10的一个数组 58 27 32 93 65 87 58 46 9 65,步长为n/2。

第一次排序 步长为 10/2 = 5

58  27  32  93  65  87  58  46  9  65
    1A                  1B
        2A                    2B
            3A                    3B
                  4A                    4B
                      5A                  5B

 首先将待排序元素序列分组,以5为步长,(1A,1B),(2A,2B),(3A,3B)等为分组标记,大写字母表示是该组的第几个元素,数字相同的表示在同一组,这样就分成5组,即(58,87),(27,58),(32,46),(93,9),(65,65),然后分别对各分组进行直接插入排序,排序后5组为(58,87),(27,58),(32,46),(9,93),(65,65),分组排序只是变得各个分组内的下表,下同。

    第二次排序 步长为 5/2 = 2

58  27  32  9  65  87  58  46  93  65

1A      1B      1C      1D      1E

2A      2B      2C      2D        2E

第三次排序 步长为 2/2 = 1

32  9  58  27  58  46  65  65  93  87

  1A  1B  1C  1D  1E  1F  1G  1H  1I  1J

第四次排序 步长为 1/2 = 0 得到有序元素序列

9  27  32  46  58  58  65  65  87  93

按照希尔排序算法定义

/**
    * 按照希尔排序定义实现
    *
    * @param sortList
    */
    static void shellSort1(Integer[] sortList) {
        int i, j, step;
        int len = sortList.length;
        // 步长除以2
        for (step = len / 2; step > 0; step /= 2)
            /**
            *  分别对每个分组进行直接插入排序
            */
            for (i = 0; i < step; i++)
            {
                for (j = i + step; j < len; j += step)
                    if (sortList[j] < sortList[j - step]) {
                        int temp = sortList[j];
                        int k = j - step;
                        while (k >= 0 && sortList[k] > temp) {
                            sortList[k + step] = sortList[k];
                            k -= step;
                        }
                        sortList[k + step] = temp;
                    }
            }
    }

对上面的代码进行优化,按照从从第一个步长数据开始,依次对每个元素与自己组内的数据进行直接插入排序

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/d8b8e36f9bf07708de2544f763bc3a52.html