手写希尔排序算法

举报
实力程序员 发表于 2021/07/20 14:10:56 2021/07/20
【摘要】 昨天给大家介绍了插入排序算法,今天介绍的希尔排序算法,其实是插入排序算法的更高效改进版。该算法因D.L.Shell于1959年提出而得名。希尔排序是基于插入排序的以下两点性质而提出改进方法的:插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位;希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列...

昨天给大家介绍了插入排序算法,今天介绍的希尔排序算法,其实是插入排序算法的更高效改进版。该算法因D.L.Shell于1959年提出而得名。


希尔排序是基于插入排序的以下两点性质而提出改进方法的:

  • 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;
  • 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位;


希尔排序的基本思想是:
先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序。


希尔排序算法的原理,我们用图来解说。


一个未排序的数组,10个元素,如下:

2021-07-20_01.jpg

我们先用N/2 =5作为步长,将数据分为5组:

2021-07-20_02.jpg

对每组数据进行直接插入排序:

2021-07-20_03.jpg

然后再将步长/2, 作为新的步长,进行数据分组:

2021-07-20_04.jpg

对每组数据进行直接插入排序:

2021-07-20_05.jpg

然后再将步长/2, 作为新的步长,进行数据分组(此时step等于1,是最后一次了):

2021-07-20_06.jpg

最后再应用一次直接插入排序,整个数组就排好序了:

2021-07-20_07.jpg

以上,就是希尔排序算法的图解​说明。


用程序实现时,对每个数据分组进行直接插入排序时,我们可以把多个分组​排序合并在一起,用一次循环就把多个分组都排好序。​具体思路为:
从下标等于step的元素开始,一直到整个数组的最后一个元素,对每个元素,从后向数组头部方向进行查找,用直接插入法将其插入到所在数据分组的​合适位置。同一个分组的元素,是与其距离为-step、-2*step​、-3*step...的元素。


希尔排序算法的​C语言实现代码,如下:

void shell_sort(int* parr, int count) {
    for (int step = count >> 1; step > 0; step >>= 1) { // 遍历每个元素,将其插入至所在分组的前面数据序列中
        for (int i = step; i < count; i++) {
            int val = parr[i];   // 待插入元素
            int k = i;
            while ((k - step >= 0) && (parr[k - step] > val)) { // 从后向前遍历所在分组, 比val大的元素向后移动一个位置
                parr[k] = parr[k - step];
                k -= step;
            }
            parr[k] = val;  // 插入至分组的相应位置
        }
    }
}


​我的微信号是 实力程序员,欢迎大家转发至朋友圈,分享给更多的朋友。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。