排序算法(二)希尔排序算法
1.基本概念
希尔排序(Shell's-Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因D.L.Shell于1959年提出而得名。
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
2.算法思路
1.设数据的个数数量为n,取k=n/2,将下标差值为k的书分为一组,通过插入排序算法构成有序序列。
2.再取k=k/2,将下标差值为k的数分为一组再通过插入排序算法构成有序序列。
3.重复第二步,直到k=1时,执行简单插入排序。
3.举例
假设有这样一组长度 16 的数 {13, 14, 94, 33, 82, 25, 59, 94, 65, 23, 45, 27, 73, 25, 39, 10},如果我们以 K=8 开始进行排序:
13 14 94 33 82 25 59 94
65 23 45 27 73 25 39 10
然后我们对每列进行排序:
13 14 45 27 73 25 39 10
65 23 94 33 82 25 59 94
将上述四行数字,依序接在一起时我们得到:{13, 14, 45, 27, 73, 25, 39, 10, 65, 23, 94, 33, 82, 25, 59, 94},然后再以 k=4 再次排序:
13 14 45 29
73 25 39 10
65 23 94 33
82 25 59 94
然后我们对每列进行排序:
13 14 39 10
65 23 45 29
73 25 59 33
82 25 94 94
一次类推 k=2、k=1,当k=1时则是执行简单插入排序。
4.动图示例
5.代码实现
int[] numbers = {5, 97, 32, 54, 66, 77, 21, 33, 32, 25, 45, 89, 68, 67, 61, 12, 18, 19};
int d = numbers.length; // 先求出数组长度
while (d != 0) {
d /= 2; // 将数组折半
for (int i = 0; i < d; i++) { // 折半后相当于有 d=numbers.length/2 个竖列
for (int j = i + d; j < numbers.length; j += d) { // 为每个竖列排序
// 接下来则是插入排序
int k = j - d;
int temp = numbers[j];
while (k >= 0 && temp > numbers[k]) {
// 注意这里每次交换的位置差值是 d
numbers[k + d] = numbers[k];
k -= d;
}
numbers[k + d] = temp;
}
}
}
6.总结(参考百度百科)
不需要大量的辅助空间,和归并排序一样容易实现。希尔排序是基于插入排序的一种算法, 在此算法基础之上增加了一个新的特性,提高了效率。希尔排序的时间复杂度与增量序列的选取有关,例如希尔增量时间复杂度为O(n²),而Hibbard增量的希尔排序的时间复杂度为O(