「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」
介绍
希尔排序是一种不稳定的排序算法,什么叫不稳定呢?也就是如果相同的两个数字,无法保证其相对位置不发生变化。
思想
希尔排序采用分组插入的方法,先将整个待排序记录分割成几组,从而减少参与插入排序的数据量,对每组分别进行直接插入排序,然后增加每组数据量,重新分组,经过几次后整个序列基本有序,再对全体记录进行一次直接插入排序。
分析
希尔排序的时间复杂度为 O(nlog n),空间复杂度为 O(1),他的特点主要有三点。
- 因为采用了记录跳跃式的移动导致排序方法不稳定
- 只能顺序结构,不能用于链式结构
- 记录总的比较次数和移动次数都比直接插入排序要小,n越大越明显,所以适合初始记录基本无序,n较大的情况
步骤
- 先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序。
- 缩小增量d1的值,重新记录分组,同样在组内进行直接插入排序
- 重复上述两个步骤,直到增量等于 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;
}