首先,希尔排序是直接插入排序的升华,在了解直接插入排序的基础上,稍加改动就实现希尔排序。接下来讲述希尔排序的原理:
(1)希尔排序(shell sort)这个排序方法又称为缩小增量排序,该方法的基本思想是:设待排序元素序列有n个元素,首先取一个整数d(小于n)作为间隔将全部元素分为d个子序列,所有距离为d的元素放在同一个子序列中,在每一个子序列中分别实行直接插入排序。然后缩小间隔d,重复上述子序列划分和排序工作。直到最后取d = 1,将所有元素放在同一个子序列中排序为止。
(2)由于开始时,d的取值较大,每个子序列中的元素较少,排序速度较快,到排序后期d取值逐渐变小,子序列中元素个数逐渐增多,但由于前面工作的基础,大多数元素已经基本有序,所以排序速度仍然很快。
(3) 方法思路:进行希尔排序,可以分为几个步骤,先将他们按照一定的间隔分为开,总共可以分为 n/d 组,也就是分成几个子序列,在这几个子序列中进行直接插入排序(查询到需要插入的位置,并且将从后向前遍历的一次往后移动,最后插入即可)。最后进行输出。
(4)希尔排序举例: 对于一组数:21 25 49 25 16 8
第一趟取d的方法是:n/3向下取整+1=3 将整个数据列划分为间隔为3的3个子序列,然后对每一个子序列执行直接插入排序,相当于对整个序列执行了部分排序调整。图解如下:
第二趟将间隔d= d/3向下取整+1=2,将整个元素序列划分为2个间隔为2的子序列,分别进行排序。图解如下:
第3趟把间隔缩小为 d= d/3向下取整+1=1,当增量为1的时候,实际上就是把整个数列作为一个子序列进行插入排序,图解如下:
数据结构实验之排序六:希尔排序
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
我们已经学习了各种排序方法,知道在不同的情况下要选择不同的排序算法,以期达到最好的排序效率;对于待排序数据来说,若数据基本有序且记录较少时, 直接插入排序的效率是非常好的,希尔排序就是针对一组基本有序的少量数据记录进行排序的高效算法。你的任务是对于给定的数据进行希尔排序,其中增量dk=n/(2^k)(k=1,2,3……)
Input
连续输入多组数据,每组输入数据的第一行给出一个正整数N(N <= 10000),随后连续给出N个整数表示待排序关键字,数字间以空格分隔。
Output
输出dk=n/2和dk=1时的结果。
Sample Input
10 10 9 8 7 6 5 4 3 2 1 10 -5 9 7 -11 37 -22 99 288 33 66
Sample 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
Source
xam
代码实现如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int a[1000010];
void shell(int n)
{
int i, j, t, k, d;
for(d = n/2; d > 0;d = d/2) //这是不断的减小增量
{
for(i = 0;i < d;i++) //一共分成了d组
{
for(j = i+d;j < n;j += d) //一下是直接插入排序的过程
{
if(a[j] < a[j - d])
{
k = a[j];
for(t = j-d;t >= 0&&a[t] >= k;t -= d)
{
a[t+d] = a[t]; //注意
}
a[t+d] = k; //找到位置后直接放到对应的位置即可
}
}
}
if(d == n/2||d == 1) //题目要求是输出增量是n/2 和 1时的
{
for(i = 0;i < n;i++)
{
if(i == n-1)
printf("%d\n",a[i]);
else printf("%d ",a[i]);
}
}
}
}
int main()
{
int n, i;
while(~scanf("%d",&n))
{
for(i = 0;i < n;i++)
{
scanf("%d",&a[i]);
}
shell(n);
}
return 0;
}