希尔排序(C语言实现)

目录

一、什么是希尔排序?

二、希尔排序的思想

三、步长

四、分组的实现以及排序过程

五、代码的实现


一、什么是希尔排序?

希尔排序(Shell Sort)是插入排序的一种。是针对直接插入排序算法的改进。该方法又称缩小增量排序,因DL.Shell于1959年提出而得名。
希尔排序基本思想:
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成(n除以d1)个组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2

二、希尔排序的思想

希尔排序的是插入排序的提升(建议先去了解一下插入排序)。它是通过将数据根据每一次的步长不断的将数据进行分组,并且进行处理,使得数值序列整体不会变得太过杂乱。使得在利用插入排序的过程中减少交换的次数,从而使整体得到优化。

三、步长

用专业一点的话来说,步长是:

要保证对步长为1的时候进行逻辑处理,比如10个数,步长每次缩小一半,
首次步长选择就应该是 d,且d*(2^x)+1<= 10;所以,x=1时候,d=4,x=2时,d=2;
所以对10个数,步长每次缩进一半,最佳就应该为 3:

总结:对长度为L的集合,假设步长的每次缩进为N,那么首次步长 d的大小必须满足,d*(N^x) + 1 <= L;
因为初始步长,越大越好,因为跨度越大,越保证对于最小数出现在最大位置时候的比较交换次数处理越少,所以,x值我们可以设置为1
所以,d*N + 1 <= L;且 N>1
————————————————
版权声明:本文为CSDN博主「weixin_42506330」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42506330/article/details/114807411

但是这些专业的话语对于我们新手编程小白来说是有一定理解难度的(作者我的确没看懂)。既然专业的话语我们理解不了,那我们就站在新手小白的角度去进行理解:

步长(step)是怎样计算的呢?

首先先要确定数组中的元素个数,然后进行每次取整除2的处理,直到最后step=1时,停止计算:

例如:一个数组为{9,8,1,3,6,5,2,7},有数组我们可知这个数组中的元素个数为8个

那么,第一次步长:step = n(数组元素个数) / 2(这里/号为c语言中的取整符号) => 8/2=4;

第二次步长:step = step(这里的step为第一次的step的值)/2 => 4/2 = 2;

第三次步长:step = step(这个同上)/2 => 2/2 = 1;

这三次步长计算为这次排序的所利用到的步长数。

注意:在计算步长的过程中,只有第一次的步长计算利用到了数组的元素个数,后面的第二次以及第三次的步长计算都是由上一次的步长/2。

四、分组的实现以及排序过程

步长计算完成后,我们要对整体的数据进行分组处理。既然要进行分组处理,那么分组是怎样计算的呢?

很简单,每一次分组的个数其实都是由步长决定的。为什么这样说呢?

例如:

9,8,1,3,6,5,2,7

step = 8/2=4;由step可知分组的个数为4组:{9,6},{8,5},{1,2},{3,7},然后对每组数据进行排序,重点!!!排序过程一定要放在整体数据中进行,分组只是让排序更加方便理解!!!

最终第一次排序结果:{6,5,1,3,9,8,2,7}

6,5,1,3,9,8,2,7

step = 4/2=2;由step可知分组的个数为2组:{6,1,9,2},{5,3,8,7}

最终第二次的排序结果:{1,3,2,5,6,7,9,8}

1,3,2,5,6,7,9,8

step = 2/2=1;由step可知分组的个数为1组,也就是整体数据;

最终第三次排序结果为:{1,2,3,5,6,7,8,9}

因为这个数组总共就只有三次步长计算,所以第三次排序完成后整体数据排序也就完成(排序的次数=步长计算次数)

但是这样可能也会有人问如果数组元素的个数为奇数时怎么办,最后分组的时候会多一个元素出来,这很好解决,多出来的元素放入到第一个分组中去进行排序。

五、代码的实现

#include 

void arr_out(int a[8])
{
    int i = 0;
    for(i = 0;i < 8;i++)
    {
        printf("%d ",a[i]);
    }
    printf("\n");
}

void arr_sort(int *p,int n)
{
    int step = 0;//步长
    int temp = 0;//用来保存第二段数据
    int i,j;

    for(step = n / 2;step > 0;step /= 2)
    {
        for(i = step;i < n;i++)
        {
            temp = p[i];
            for(j = i - step;j >= 0 && p[j] > temp;j -= step)
            {
                p[j + step] = p[j];
                //当满足条件时第一次j+step = i;后面的j+step = 上一次j的值
            }
            p[j + step] = temp;
        }
    }
}

int main()
{
    int a[8] = {0};
    int i = 0;
    for(i = 0;i < 8;i++)
    {
        scanf("%d",&a[i]);
    }

    arr_sort(a,8);//排序函数
    arr_out(a);//输出函数

    return 0;
}

你可能感兴趣的:(c语言)