前言
- 希尔算法是针对插入算法的优化升级版。在进行插入算法之前先执行预排序,可以让数组内的元素按照等比间隔进行分组,然后对组内元素进行比较和交换,然后再按照一定的间隔再进行分组,然后再进行比较和交换,最后就以1为间隔在进行比较和交换,相当于对全部元素进行插入算法。在最后一步进行交换时,因为数组内元素已经经过预排序处理,所以就会减少很多插入算法的工作量。
代码实现
public static void main(String[] args) {
Integer[] param = {4, 3, 5, 2, 6, 1, 7, 10, 9, 8, 11, 12, 13};
int d = param.length;
while (d > 1) {
// 取数组长度一半为间隔增量跨度;
d = d / 2;
// 遍历间隔跨度的数据
for (int i = 0; i < d; i++) {
// 根据跨度数据在加上间隔值
for (int k = i + d; k < param.length; k = k + d) {
// 获取后续间隔值元素
int ik = param[k];
int j;
// 用间隔值元素和左面的元素进行大小比较,如果间隔值小于左面的值,则替换掉
for (j = k - d; j >= 0 && ik < param[j]; j = j - d) {
param[j + d] = param[j];
}
// 最后把之前保存的初始间隔值赋值到中间比较的空缺位
param[j + d] = ik;
}
}
}
System.out.println(Arrays.toString(param));
}
----------------------------------------
结果:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
最后
- 希尔算法的时间复杂度平均要小于插入算法,但是在希尔算法最坏的情况下可能比插入算法的时间复杂度更加耗时,因为如果当希尔算法前面的几个预排序分组步骤都没有改动数组内元素的顺序,然后再执行插入排序,相当于前面的几组预排序就白耗时了。
- 所以人们就提出了几种对希尔算法预排序中间隔增量的算法,其中Hibbard增量算法和sedgewick增量算法具有代表性:
- Hibbard算法:1,3,7,15 . . .;公式:2 ^ n-1; 最坏时间复杂度O(n^(2/3));
- sedgwick算法:1,5,19,41,109 . . .;公式: 94^k - 92^k + 1 或者 4^k - 3*2^k + 1;最后时间复杂度o(n^(3/4));
参考 小灰算法之希尔排序