vlambda博客
学习文章列表

希尔排序,shell排序,缩小增量排序

1959年D·L·Shell,提出的这个算法。

名称:shell排序,希尔排序,缩小增量排序。


       插入排序的升级写法,原则就是将整个数组进行几次大体排序,让各个元素处在其应该在的大致位置上,最后进行一次细致排序,从而提升效率。

       大体排序的思路就是先把数据分成几个小组,让各小组各自进行插入排序。过程如下:不一定3个一组,8个也行,我这里以3个一组举例子。


第一次:3个一组(最后一组有可能不满3个,这个没有影响),将每一组的第一个数组作为一组数据,对他们进行插入排序。如下图:

10个数,每三个一组,就是分成4组,最后一组1个数。

先将每组的第一个数拿出来,也就是3 6 2 7进行插入排序,得到2 3 6 7。

然后将每组的第二个数拿出来,也就是4 9 6进行插入排序,得到4 6 9。

然后将每组的第三个数拿出来,也就是8 5 1进行插入排序,得到1 5 8。

最后三次小组排序后得到新数列2 4 1 3 6 5 6 9 8 7。


第二次2个数一组。第一次-1。执行第一次同样的逻辑,也就是一样的代码。过程如下图:

在上一次运行的结果基础上,再次以2个一组进行排序。

第一次拿出每组第一个。即2 1 6 6 8,排序后为1 2  6 6 8.

第二次拿出每组第二个。即4 3 5 9 7,排序后为3 4 5 7 9.

进行完结果为:1 3 2 4 6 5 6 7 8 9


最后再1个1组,1个一组就是挨个插入排序了。

这最后一次,从头到尾进行插入排序,我们发现仅需要进行;两次移动就成序了。


经过对比:

最原始的插入排序排好这串数需要22次移动元素。

shell排序排好这串数仅需要14次移动元素。

根据数据的大小位置不同,换一组数据,排序移动的次数也不同,也就是算法不稳定,比如换10个数,可能需要18次排序,也可能5次就排好。


#include  <stdio.h>


void sort(int* p, int len)

    for (int i = 3; i >= 1; i--)    //分组 3个1组,2个1组,1个1组

    {

        for (int j = 0; j < len - i; j += i)   //遍历组,一组遍历1个

        {

            int k = j + i;                         //插入排序核心算法,这段都是

            int temp = p[k];

            while (k >= i && temp < p[k - i])  //找位置

            {

                p[k] = p[k - i];

                k -= i;

            }

            p[k] = temp;

        }

    }

}


int main(void)

{

    int a[10] = { 3,4,8,6,9,5,2,6,1,7 };

    sort(a, 10);

    return 0;

}