数据结构实验之排序六:希尔排序

来源:互联网 发布:演唱会抢票攻略 知乎 编辑:程序博客网 时间:2024/06/06 03:43

**数据结构实验之排序六:希尔排序
*数据结构实验之排序六:希尔排序
*
Time Limit: 1000MS Memory Limit: 65536KB
Submit Statistic
Problem Description

我们已经学习了各种排序方法,知道在不同的情况下要选择不同的排序算法,以期达到最好的排序效率;对于待排序数据来说,若数据基本有序且记录较少时, 直接插入排序的效率是非常好的,希尔排序就是针对一组基本有序的少量数据记录进行排序的高效算法。你的任务是对于给定的数据进行希尔排序,其中增量dk=n/(2^k)(k=1,2,3……)
Input

连续输入多组数据,每组输入数据的第一行给出一个正整数N(N <= 10000),随后连续给出N个整数表示待排序关键字,数字间以空格分隔。

Output

输出dk=n/2和dk=1时的结果。

Example Input

10
10 9 8 7 6 5 4 3 2 1
10
-5 9 7 -11 37 -22 99 288 33 66

Example Output

5 4 3 2 1 10 9 8 7 6
1 2 3 4 5 6 7 8 9 10
-22 9 7 -11 37 -5 99 288 33 66
-22 -11 -5 7 9 33 37 66 99 288

Hint

Author

xam

希尔排序(Shell sort)算法原理
希尔排序算法是按其设计者希尔(Donald Shell)的名字命名,该算法由1959年公布,是插入排序的一种更高效的改进版本。它的作法不是每次一个元素挨一个元素的比较。而是初期选用大跨步(增量较大)间隔比较,使记录跳跃式接近它的排序位置;然后增量缩小;最后增量为 1 ,这样记录移动次数大大减少,提高了排序效率。希尔排序对增量序列的选择没有严格规定。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
插入排序在对几乎已经排好序的数据操作时, 效率高, 即可以达到线性排序的效率
但插入排序一般来说是低效的, 因为插入排序每次只能将数据移动一位
算法思路:
先取一个正整数 d1(d1 < n),把全部记录分成 d1 个组,所有距离为 d1 的倍数的记录看成一组,然后在各组内进行插入排序
然后取 d2(d2 < d1)
重复上述分组和排序操作;直到取 di = 1(i >= 1) 位置,即所有记录成为一个组,最后对这个组进行插入排序。一般选 d1 约为 n/2,d2 为 d1 /2, d3 为 d2/2 ,…, di = 1。
图片来自维基百科
这里写图片描述
实例分析
假设有数组 array = [80, 93, 60, 12, 42, 30, 68, 85, 10],首先取 d1 = 4,将数组分为 4 组,如下图中相同颜色代表一组:
这里写图片描述

然后分别对 4 个小组进行插入排序,排序后的结果为:
这里写图片描述
然后,取 d2 = 2,将原数组分为 2 小组,如下图:
这里写图片描述
然后分别对 2 个小组进行插入排序,排序后的结果为:
这里写图片描述
最后,取 d3 = 1,进行插入排序后得到最终结果:
这里写图片描述

上题 AC Code :

#include <iostream>#include <cstdio>#include <cmath>int f[1010],n;int dk(int n,int k){    return n/(int)pow(2,k);}int main(){    while(scanf("%d",&n)!=EOF)    {        int i;        for(i=1;i<=n;i++)            scanf("%d",f+i);        int k,d;        for(k=1;d=dk(n,k),d>=1;k++)        {            for(i=d;i<=n;i++)            {                f[0]=f[i];                int j=i-d;                while(j>0&&f[j]>f[0])                {                    f[j+d]=f[j];                    j-=d;                }                f[j+d]=f[0];            }            if(d==1||d==n/2)            {                for(i=1;i<=n;i++)                    printf("%d%c",f[i],i==n?'\n':' ');            }        }    }    return 0;}