数据结构实验之排序六:希尔排序
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
希尔排序可以理解为设置了一个增量d的插入排序。
在看下列图解之前,需要知道 主要操作是对 a[j] a[j+d] 进行比较,如果从小到大排序 且 a[j] > a[j+d] 则进行交换: swap(a[j] ,a[j+d])
现考虑 由于 d的不同,则对一组数据处理的次数也不同,例如 在 n=10 的条件下
当 d=5 的时候 需要比较 (a0 ,a5)(a1 a6) ( a2 a7) ( a3 a8) (a4 a9) 5次
当d=2的 时候 需要比较 (a0 ,a2)(a1 a3) ( a2 a4) ( a3 a5) (a4 a6) (a5 ,a7)(a6 a8) ( a7 a9) 8次
总结上述规律如下:
当 增量d设为位置参数 的 时候 比较 最后一次一定是 (ak, an-1) 做比较只需要确定k的值就好了, 又因为 n-1-k = d 所以 k = n-1-d
即需要比较的数组下标从 a0 到 an-1-d 一共比较了 n-d 次。
对于上面希尔排序的图解,大家都应该熟悉了。
#include <iostream>
#include<cstring>
#include<cstdio>
#include <algorithm>
using namespace std;
void shell_sort(int a[], int n, int d)
{
for(int i=d; i>0; i/=2) //控制增量d从 n/2 变为 1
{
for(int j=0; j<n-i; j++) // 控制比较次数 n-增量
{
if(a[j] > a[j+i]) //比较过程且满足交换条件
{
swap(a[j], a[j+i]);
int k=j;
while(k-i>=0) // 为直接插入的相关内容 即 3 x 5 y 1 变成 1 x 3 y 5 不是 3 x 1 y 5,详情请理解插入排序
{
if(a[k]< a[k-i])
{
swap(a[k],a[k-i]);
k = k-i;
}
else
break;
}
}
}
//print
if(i==n/2|| i==1)
{
for(int z=0; z<n; z++)
{
printf("%d%c",a[z],z==n-1?'\n':' ');
}
}
}
}
int main ()
{
int a[10010];
int n;
while(~scanf("%d",&n) )
{
for(int i=0; i<n; i++)
{
scanf("%d",&a[i]);
}
shell_sort(a, n,n/2);
}
}