插入排序--希尔排序

基本思想

先将整个待排序的记录序列分割成若干个子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
即把记录按步长gap分组,对每组记录采用直接插入排序方法进行排序。
随着步长逐渐减小,所分成的组包含的记录越来越多,当步长的值减小为1时,整个数据合成为一组,构成一组有序记录,则完成排序。

示意图

插入排序--希尔排序_第1张图片
image.png

初始时,有一个大小为10的无序序列
在第一趟排序中,我们不妨设gap1=N/2 = 5,即相隔为5个元素组成一组,可以分成5组。
接下来,按照直接插入排序的方法对每个组进行排序。
在第二趟排序中,我们把上次的gap缩小一半,即gap2 = gap1/2 = 2。这样每相隔距离为2的元素组成一组,可以分成2组,按照直接插入排序的方法对每个组进行排序。
在第三趟排序中,再次把gap缩小一半,即gap3=gap2/2=1。这样相隔距离为1的元素组成一组,即只有一组,按照直接插入排序的方法对每个组进行排序。此时,排序已经结束。
需要注意的是,图中有两个相等数值的元素5,可以清楚看到,在排序过程中,两个元素位置交换了,所以,希尔排序是不稳定的算法。

java代码

public static void shellSort(int[] list) {
        if (null == list || list.length <= 1) {
            return;
        }

        int gap = list.length / 2;
        while (gap >= 1) {
            for (int i = gap; i < list.length; i++) {
                int j;
                int temp = list[i];

                for (j = i - gap; j >= 0 && temp < list[j]; j -= gap) {
                    list[j + gap] = list[j];
                }
                list[j + gap] = temp;

            }
            gap = gap / 2;
        }
    }

时间复杂度

步长的选择是希尔排序的重要部分,只要最终步长为1任何步长序列都可以工作。
算法最开始以一定的步长进行排序。然后会继续以一定步长进行排序,最终算法以步长为1进行排序。当步长为1,算法变为插入排序,这就保证了数据一定会被排序。
步长N/2的k次方,最坏情况下复杂度O(N*N)

你可能感兴趣的