排序算法:希尔排序

icy2003 程序 2020-05-17 17:45:39 824 0条

希尔排序算法是按其设计者希尔(Donald Shell)的名字命名,该算法由1959年公布,是插入排序的一种更高效的改进版本。它的作法不是每次一个元素挨一个元素的比较。而是初期选用大跨步(增量较大)间隔比较,使记录跳跃式接近它的排序位置;然后增量缩小;最后增量为 1 ,这样记录移动次数大大减少,提高了排序效率

4.gif

希尔排序是基于插入排序的以下两点性质而提出改进方法的:

  1. 插入排序在对几乎已经排好序的数据操作时, 效率高, 即可以达到线性排序的效率。
  2. 但插入排序一般来说是低效的, 因为插入排序每次只能将数据移动一位。

算法评价

  • 平均时间复杂度:O(nlogn)
  • 最好情况:O(nlog^2 n)
  • 最坏情况:O(nlog^2 n)
  • 空间复杂度:O(1)
  • 稳定性:不稳定

算法思想

  1. 先取一个正整数 d1(d1 1 个组,所有距离为 d1 的倍数的记录看成一组,然后在各组内进行插入排序。
  2. 然后取 d2(d2 1)。
  3. 重复上述分组和排序操作;直到取 di = 1(i >= 1) 位置,即所有记录成为一个组,最后对这个组进行插入排序。一般选 d1 约为 n/2,d2 为 d1 /2, d3 为 d2/2 ,…, di = 1。

实例分析

假设有数组 array = [80, 93, 60, 12, 42, 30, 68, 85, 10],首先取 d1 = 4,将数组分为 4 组,如下图中相同颜色代表一组:

94511-9eccdfjo1st.png

然后分别对 4 个小组进行插入排序,排序后的结果为:

64442-dp8mx5p2mjv.png

然后,取 d2 = 2,将原数组分为 2 小组,如下图:

19580-rqu0qqhkby.png

然后分别对 2 个小组进行插入排序,排序后的结果为:

86979-8csci4k3cvr.png

最后,取 d3 = 1,进行插入排序后得到最终结果:

20435-zp51mp4z2n.png

代码示例

Javascript

function shellSort(array) {

    function swap(array, i, k) {
        var temp = array[i];
        array[i] = array[k];
        array[k] = temp;
    }

    var length = array.length,
        gap = Math.floor(length / 2);

    while (gap > 0) {
        for (var i = gap; i < length; i++) {
            for (var j = i; 0 < j; j -= gap) {
                if (array[j - gap] > array[j]) {
                    swap(array, j - gap, j);
                } else {
                    break;
                }
            }
        }

        gap = Math.floor(gap / 2);
    }

    return array;
}
标签: 算法

非特殊说明,本博所有文章均为博主原创。