希尔排序

希尔排序

希尔排序(Shell's Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的板本。希尔排序是非稳定排序算法。该方法因 D.L.Shell 于 1959 年提出而得名。

排序方法

  1. 取间距step,对所有数按照下标对step的剩余类进行分组,也就是间隔为step倍数的为一组。

  2. 在组内进行直接插入排序。

  3. 缩小step。

  4. 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;
}
posted @ 2022-02-22 20:57  cacu  阅读(73)  评论(0编辑  收藏  举报