希尔排序算法的实现

168 阅读2分钟

「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战

介绍

希尔排序是一种不稳定的排序算法,什么叫不稳定呢?也就是如果相同的两个数字,无法保证其相对位置不发生变化。

思想

希尔排序采用分组插入的方法,先将整个待排序记录分割成几组,从而减少参与插入排序的数据量,对每组分别进行直接插入排序,然后增加每组数据量,重新分组,经过几次后整个序列基本有序,再对全体记录进行一次直接插入排序。

分析

希尔排序的时间复杂度为 O(nlog n),空间复杂度为 O(1),他的特点主要有三点。

  1. 因为采用了记录跳跃式的移动导致排序方法不稳定
  2. 只能顺序结构,不能用于链式结构
  3. 记录总的比较次数和移动次数都比直接插入排序要小,n越大越明显,所以适合初始记录基本无序,n较大的情况

步骤

  1. 先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序。
  2. 缩小增量d1的值,重新记录分组,同样在组内进行直接插入排序
  3. 重复上述两个步骤,直到增量等于 1 为止

比如有一个数组 [49, 97, 26, 13, 27, 65, 38, 49, 55, 7] 其长度n为 10,现在要进行希尔排序。
首先我们定义增量 gap = Math.floor(n/2) = 5 也就是把下标为 {0,5},{1,6},{2,7},{3,8},{4,9} 为一组也就是[49, 65]、[97, 38]、[26, 49]、[13, 55]、[27, 7]。在把各组分别进行直接插入排序。排序完后的值为
[49, 38, 26, 13, 7, 65,97, 49, 55, 27]

然后更新增量 gap = Math.floor(gap/2) = 2 也就是分成两组,每相隔2个位置为一组,即[49,26,7,97,55][38,13,65,49,27]在把各组分别进行直接插入排序。排序完后的值为
[7, 13, 26, 27, 49, 38, 55, 49, 97, 65]

最后再更新增量gap = Math.floor(gap/2) = 1 这时候只有一组了,再进行直接插入排序 [7, 13, 26, 27, 38, 49, 49, 55, 65, 97]。 到这里就完成了希尔排序。

代码

Javascript 版本

function shellSort(arr) {
    var len = arr.length,
        temp,
        gap = 1;
    gap = Math.floor(len / 2)
    for (gap; gap> 0; gap = Math.floor(gap/2)) {
        for (var i = gap; i < len; i++) {
            temp = arr[i];
            for (var j = i-gap; j >= 0 && arr[j]> temp; j-=gap) {
                arr[j+gap] = arr[j];
            }
            arr[j+gap] = temp;
        }
    }
    return arr;
}