• 排序2:希尔排序(缩小增量排序)


    上一期,我们介绍了直接插入排序

    这一期,我们来介绍希尔排序的底层逻辑和代码实现。


    目录

    希尔排序的基本思想

    单趟的实现

    整个排序的实现

    总结


    希尔排序的基本思想

    先选定一个整数gap,把待排序文件中所有记录分成gap个 组,所有距离为gap的记录分在同一组内,并对每一组内的记录进行排序。然后取重复上述分组和排序的工 作。当到达gap =1 时,所有记录在统一组内排好序
    光看概念十分抽象,我们看下面的图:

    当gap = 3时,我们可以把一组数据分为3组,每一组中,单独进行排序。通过这样,我们可以让数据大致趋向于有序。这就是单趟的底层原理了。
    分组排序后的结果:

     然后,逐渐缩小gap进行排序,数据就会越来越有序。

      

    单趟的实现

    从单趟实现起,逻辑可以分为下面几步:
            1、选定gap然后分组。
            2、每一组从后往前遍历排序。
            3、与后面一个间隔为gap的数比较。
            4、a:如果后面的数要小于前面的数,那么小的数插入到前面,然后被插入位置的后面的数字各往后移动gap格。
    代码如下:
    1. int gap = 3;
    2. for (int i = 0; i < n - gap; i += gap)
    3. {
    4. int end = i;
    5. int temp = a[end + gap];
    6. while (end >= 0)
    7. {
    8. if (a[end] > temp)
    9. {
    10. a[end + gap] = a[end];
    11. a[end] = temp;
    12. end -= gap;
    13. }
    14. else
    15. {
    16. break;
    17. }
    18. }
    19. }

    不难看出,这和直接插入排序的单趟是很相似的。

    整个排序的实现

    核心思想: 

            1、gap递减,缩小排序组数,最终到gap = 1的时候,就是一次直接插入排序了。

            2、齐头并进。

           

    代码如下:

    1. void ShellSort(int* a, int n)
    2. {
    3. int gap = n;
    4. while (gap > 1)
    5. {
    6. //间隔逐渐缩小,最后一次等于插入排序
    7. gap = gap / 3 + 1;
    8. //齐头并进
    9. for (int i = 0; i < n - gap; ++i)
    10. {
    11. int end = i;
    12. int temp = a[end + gap];
    13. while (end >= 0)
    14. {
    15. if (a[end] > temp)
    16. {
    17. a[end + gap] = a[end];
    18. a[end] = temp;
    19. end -= gap;
    20. }
    21. else
    22. {
    23. break;
    24. }
    25. }
    26. }
    27. }
    28. }

    i 的每次增加从gap变成了1,这样的目的是为了能够逐一的往后走下去,使得每组都能照顾到。

    gap赋值n,每次除以3。除以3后加上1的目的是为了能够最后数字变成1。

    我们来测试一下:

     结果:

     

    总结

    关与希尔排序的时间复杂度问题,是很难计算出来的。

    殷人昆老师的《数据结构-用面相对象方法与C++描述》一书中提到:

    在n在某个范围的内的时候,时间复杂度约为n^1.3 。当数据过多的时候,时间复杂度也会提高到

    n(logn)²。

    而希尔排序在排序中也是不稳定的(不稳定:即有可能因为某部分的有序破坏原先的已经变为有序的部分)。

  • 相关阅读:
    `英语` 2022/8/16
    Prometheus的部署
    基于Android的手机通讯录设计
    设置JVM的内存大小
    求HTML+CSS礼花特效
    LeetCode每日两题02:深搜/广搜 岛屿的最大面积 (均1200道)
    Ubuntu22.04安装PostgreSQL
    Java操作符
    LeetCode 10. 正则表达式匹配
    Spring Cloud Alibaba实现服务的无损下线功能
  • 原文地址:https://blog.csdn.net/qq_65139309/article/details/127089595