希尔排序

      首先,希尔排序是直接插入排序的升华,在了解直接插入排序的基础上,稍加改动就实现希尔排序。接下来讲述希尔排序的原理:

     (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;
}

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值