# 希尔排序
- 时间复杂度 由增量序列决定 介于
O(n) ~ O(n²) - 空间复杂度
O(1) - 不稳定
本质上是对插入排序的一种优化,基本思想是:
- 将待排序数组按照一定的间隔分为多个子数组,每组分别进行插入排序。这里按照间隔分组指的不是取连续的一段数组,而是每跳跃一定间隔取一个值组成一组。
- 逐渐缩小间隔进行下一轮排序
- 最后一轮时,取间隔为 1,也就相当于直接使用插入排序。但这时经过前面的“宏观调控”,数组已经基本有序了,所以此时的插入排序只需进行少量交换便可完成。
其中,每一遍排序的间隔在希尔排序中被称为增量,增量组成的序列称为增量序列,增量依次递减,最后一个增量必须为 1,所以希尔排序又被称为缩小增量排序。
增量序列的选择会极大影响排序的效率,这里我们选择初始增量是长度的一半,每遍增量减半:
function shellSort(arr) {
for (let gap = arr.length >> 1; gap > 0; gap >>= 1) {
// 分组
for (let groupStartIndex = 0; groupStartIndex < gap; groupStartIndex++) {
// 插入排序
for (
let curIndex = groupStartIndex + gap;
curIndex < arr.length;
curIndex += gap
) {
let cur = arr[curIndex];
let preIndex = curIndex - gap;
while (preIndex >= groupStartIndex && cur < arr[preIndex]) {
arr[preIndex + gap] = arr[preIndex];
preIndex -= gap;
}
arr[preIndex + gap] = cur;
}
}
}
}
// 优化
function shellSort(arr) {
for (let gap = arr.length >> 1; gap > 0; gap >>= 1) {
// 分组
for (let i = gap; i < arr.length; ++i) {
let cur = arr[i];
let preIndex = i - gap;
while (preIndex >= 0 && cur < arr[preIndex]) {
arr[preIndex + gap] = arr[preIndex];
preIndex -= gap;
}
arr[preIndex + gap] = cur;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
增量元素不互质,则小增量可能根本不起作用