希尔排序
初始 | 81 | 94 | 11 | 96 | 12 | 35 | 17 | 95 | 28 | 58 | 41 | 75 | 15 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
在5-排序后 | 35 | 17 | 11 | 28 | 12 | 41 | 75 | 15 | 96 | 58 | 81 | 94 | 95 |
在3-排序后 | 28 | 12 | 11 | 35 | 15 | 41 | 58 | 17 | 94 | 75 | 81 | 96 | 95 |
在1-排序后 | 11 | 12 | 15 | 17 | 28 | 35 | 41 | 58 | 75 | 81 | 94 | 95 | 96 |
void shellsort(int *a, int N)
{
int i, j, Increment;
int tmp;
for (Increment = N / 2; Increment > 0; Increment /= 2)
{
for (i = Increment; i < N; ++i)
{
tmp = a[i];
for (j = i; j >= Increment; j -= Increment)
{
if (tmp < a[j - Increment])
a[j] = a[j - Increment];
else
break;
}
a[j] = tmp;
}
}
}
1 希尔排序通过使用比较相距一定间隔的元素来工作,个趟比较的所用的距离随着算法的进行而减小,直到只比较相邻元素的最后一趟排序为止,因此,希尔排序有时也叫缩小增量排序(diminishing increment sort)。
2 希尔排序使用一个序列h1, h2, ..., ht,叫做增量序列(increment sequence),只要h1 = 1,任何增量序列都是可行的。
3 在使用增量hk的一趟排序后,对于每一个i有a[i] <= a[i + hk],所有相隔hk的元素都被排序,此时称文件是hk-排序的。
4 希尔排序的一个重要性质是,一个hk-排序的文件(此后将是h(k - 1)-排序的)保持它的hk-排序性,假如算法不是这样的话,算法将失去他的意义。
5 一趟hk-排序的作用就是对hk个独立的子数组执行一次插入排序。
6 增量序列有多种不同的选择,他们对算法的时间复杂度影响不同
- 增量序列的一种流行选择是使用shell建议的序列:ht为不大于 N / 2的最大整数,hk为不大于h(k + 1) / 2的最大整数,此时,算法的最坏运行时间为\(\Theta(n^2)\)
- Hibbard提出一个稍微不同的增量序列:1,3,7。。。,\(2^k\) - 1,关键的区别在于相邻的增量没有公因子,算法的最坏运行时间为\(\Theta(n^{3/2})\)
- Sedgewick提出了几种增量序列,其最坏运行时间(也是可以达到的)为\(\mathrm{O}(n^{4/3})\),平均运行时间猜测为\(\mathrm{O}(n^{7/6})\),其中最好的序列{1,5,19,41,109,。。。},序列中的项或者是9 x \(4^i\) - 9 x \(2^i\) + 1,或者是\(4^i\) - 3 x \(2^i\) + 1,通过将这些值放到一个数组中可以最容易的实现这个算法
7 希尔排序是算法非常简单且又具有极其复杂分析的一个好例子