4. 希尔排序

  希尔排序是插入排序的一种优化方案。

  希尔排序主要是利用了插入排序的一些特点:

  1. 小段的直接插入排序,效率很高;
  2. 当待排数据基本上是有序的时候,直接插入排序的效率也会很高;

  假设待排序元素序列有n个元素,首先取一个整数 gap(小于n)作为间隔,将全部元素分为若干个子序列,所有距离为 gap 的元素放在同一个子序列中,在每一个子序列中进行插入排序。然后缩小间隔 gap,重复上述子序列划分、排序以及缩小 gap 的工作。直到最后取 gap=1,将所有元素放在同一个子序列中进行插入排序为止。

  希尔排序非常好的利用了插入排序的特点。在刚开始时,gap 的取值较大,每个子序列中的元素较少,排序速度较快;到排序后期 gap 的取值逐渐变小,子序列中元素个数逐渐增多,但由于前面工作的基础,大多数元素已经基本有序,所以排序速度仍然很快。

  希尔排序需要定义一个 gap,我们一般会选择数组长度的一半作为第一次的 gap,之后每次都将 gap 缩小为当前 gap 的一半,这是希尔建议的增量,称为希尔增量。但要知道的是,其实这个增量序列不是最优的。

  希尔排序和插入排序的对比:

稳定性 空间复杂度 平均时间复杂度 最好时间复杂度 最坏时间复杂度
插入排序 稳定 O(1) O(n2) O(n2) O(n)
希尔排序 不稳定 O(1) O(n1.3) O(n2) O(n)

在这里插入图片描述

public int[] bubbleSort(int[] arr){
    
    
	int len = arr.length;
	// gap 是增量,每次循环结束都会减半
    for (int gap = len >> 1; gap > 0; gap = gap >> 1) {
    
    
    	// i 起始值是组内无序区第一个元素
        for (int i = gap; i < len; i++) {
    
    
            int temp = arr[i];
            // j 起始值是组内有序区最后一个元素
            int j = i - gap;
            for (; j >= 0 && arr[j] > temp; j -= gap) {
    
    
                arr[j + gap] = arr[j];
            }
            arr[j + gap] = temp;
        }
    }
    return arr;
}

可以到 LeetCode 中验证代码正确性:912. 排序数组
希尔排序的提交结果:
在这里插入图片描述
  希尔排序时间复杂度的下界是n*log2n。希尔排序没有快速排序算法快。
  中等大小规模表现良好,对规模非常大的数据希尔排序不是最优选择。但是比O(n2 )复杂度的算法快得多。并且希尔排序非常容易实现,算法代码短而简单。 此外,希尔算法在最坏的情况下和平均情况下执行效率相差不是很多,与此同时快速排序在最坏的情况下执行的效率会非常差。
  几乎任何排序工作在开始时都可以用希尔排序,若在实际使用中证明它不够快,再改成快速排序这样更高级的排序算法.

猜你喜欢

转载自blog.csdn.net/qq_40395874/article/details/115096777