希尔排序
希尔排序
希尔排序(Shell's Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的板本。希尔排序是非稳定排序算法。该方法因 D.L.Shell 于 1959 年提出而得名。
排序方法
-
取间距step,对所有数按照下标对step的剩余类进行分组,也就是间隔为step倍数的为一组。
-
在组内进行直接插入排序。
-
缩小step。
-
step为1结束。否则跳转2。
时间复杂度
与参数step相关。
时间复杂度的下界为O(\(nlog_2^2n\))。
基本上为O(\(n^{1.2-2}\))
合理性分析
实际上希尔排序在实际运用中已经很少会见到了。
我认为他的主要价值在于认识和证明希尔排序的合理性。
直观上来说,每次插入排序都能让数列看上去更有顺序一些,然后前面大间距的插入排序帮助后面小间距的插入排序降低复杂度。
但这个要证明的话很不简单。
其实是要证明间隔k排序之后再进行间隔h排序,h排序不会影响k排序。
意思就是隔k个数有序,再将隔h个数排序,新序列仍然隔k个数有序。
h-排序 不影响 k-排序
引理 两个序列{\({x_1, ……, x_{n+r}}\)}和{\(y_1,……,y_{m+r}\)}中满足
\[x_1 <= y_m,……,x_r <=y_{m+r}
\]
如果对x和y排序,则仍满足如上规则。
证明思路 先考虑两个r个数序列,然后不断加数。
以下证明:
对a进行k排序
\[a_1,……,a_{1+tk}
\]
\[a_2,……,a_{2+tk}
\]
这些都是有序的
再进行h排序
\[a_1,……,a_{1+ph}
\]
\[a_2,……,a_{2+ph}
\]
其中取一种情况
\[a_1,a_{1+h},……
\]
\[a_{1+k}, a_{1+h+k},……
\]
类比于引理中的x,y。易得结果。
实现代码
#include <bits/stdc++.h>
using namespace std;
int a[100010];
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; ++i)
cin >> a[i];
int step = n / 3;
while (step)
{
for (int i = step + 1; i <= n; ++i)
for (int j = i; j >= step && a[j] < a[j - step]; j -= step)
swap(a[j], a[j - step]);
step /= 3;
}
for (int i = 1; i <= n; ++i)
cout << a[i] << ' ';
return 0;
}