• 常见排序算法之插入排序


    目录

    一、直接插入排序

    1.1 什么是插入排序

    1.2 代码思路

    1.3 C语言源码

    二、希尔排序

    2.0 插入排序的弊端

    2.1 什么是希尔排序?

    2.2 排序思路

    2.3 C语言源码


    一、直接插入排序

    1.1 什么是插入排序

    插入排序是一种简单直观的排序算法,它通过构建有序序列,对未排序数据逐个插入到合适的位置,从而达到排序的目的。

    具体操作为:将第一个元素视为已排序部分,然后依次将后面的元素插入到已排序部分,直到所有元素都插入完成为止。

    插入排序的时间复杂度为O(N^2),是一种稳定的排序算法。

    1.2 代码思路

    采取先部分后整体的思路进行讲解

    • 部分
    1. 假设前n个元素均为已排序好的元素,已排序好的最后一个元素的数组下标为end
    2. 将end+1下标对应的值与end对应的值进行比较
      如果大于前一个值,则在end+1的位置插入该值。
      如果小于前一个值,则在end-1的位置插入该值。
    3. 循环比较已经排序好的元素的值与end+1的值,重复插入操作。
      在比较有限次后若发现满足条件,则跳出循环。
      考虑最坏的情况,如果end-1为0时,也就是插入到了数组的第一个位置,则跳出循环。
    • 整体
    1. 从n=0开始循环,假设循环i次,那么每次已排序好的数组最后一个下标就是数组的大小-i
    2. 关键问题是要进行多少次循环?

    1.3 C语言源码

    1. void InsertSort(int* a, int n)
    2. {
    3. for (int i = 0; i < n-1; i++)
    4. {
    5. int end = i;
    6. int tmp = a[end + 1];
    7. while (end >= 0)
    8. {
    9. if (a[end] > tmp)
    10. {
    11. a[end + 1] = a[end];
    12. end--;
    13. }
    14. else
    15. {
    16. break;
    17. }
    18. a[end + 1] = tmp;
    19. }
    20. }
    21. }

    二、希尔排序

    2.0 插入排序的弊端

    插入排序的主要弊端在于其时间复杂度较高。在最坏情况下,插入排序的时间复杂度为O(n^2),因此对于大规模数据集合来说,插入排序的效率较低。尤其是当数组是升序排序时,想要转成降序排序,效率极低。

    由此衍生出希尔排序。通过引入增量序列,将整个数据集合分成多个子序列,并对每个子序列进行插入排序,逐渐减小增量,最终实现对整个数据集合的排序。这样做减少了数据的搬移次数,提高了排序的效率。希尔排序通过这种分组的方式,使得较小的元素可以更快地移动到合适的位置,从而减少了插入排序中的反复比较和移动操作,提高了排序效率。

    2.1 什么是希尔排序?

    希尔排序是一种基于插入排序的排序算法,也被称为“缩小增量排序”。它的基本思想是将待排序的元素分成若干个小组,对每个小组进行插入排序;然后逐渐减小每组的元素个数,继续进行插入排序,直到每组只有一个元素为止。通过这种分组和逐渐减小增量的方式,希尔排序可以在一定程度上减少插入排序的移动操作次数,从而提高排序效率。

    2.2 排序思路

    采取先部分后整体的思路进行讲解

    • 部分
    1. 设置分组的间隔 gap。
    2. 将每个组看作一个新的数组进行插入排序。
    3. 插入排序的数组下标以及循环结束的条件需要改变,见下图解
    • 整体
    1. 重新设置分组的间隔gap,缩小组数,重复插入排序操作。
    2. 直至gap为1,对整体进行一次插入排序,则最终完成了对数组的排序。
    3. 关于gap的取值选择,目前尚无定论。取gap = gap / 3+1为例
      摘自《数据结构-用面向对象方法与C++描述》-殷人昆
       

    2.3 C语言源码

    1. //常规思路版本
    2. void ShellSort(int* arr, int n)
    3. {
    4. int gap = n;
    5. //总排序
    6. while (gap > 1)
    7. {
    8. gap = gap / 3 + 1;
    9. //多组排序
    10. for (int j = 0; j < gap; j++)
    11. {
    12. //一组排序
    13. for (int i = j; i < n - gap; i+=gap)
    14. {
    15. int end = i;
    16. int tmp = arr[end + gap];
    17. while (end >= 0)
    18. {
    19. if (arr[end] > tmp)
    20. {
    21. arr[end + gap] = arr[end];
    22. end -= gap;
    23. }
    24. else
    25. {
    26. break;
    27. }
    28. arr[end + gap] = tmp;
    29. }
    30. }
    31. }
    32. }
    33. }
    34. //优化思路
    35. void ShellSort(int* arr, int n)
    36. {
    37. int gap = n;
    38. while (gap > 1)
    39. {
    40. gap = gap / 3 + 1;
    41. for (int i = 0; i < n - gap; i++)
    42. {
    43. int end = i;
    44. int tmp = arr[end + gap];
    45. while (end >= 0)
    46. {
    47. if (arr[end] > tmp)
    48. {
    49. arr[end + gap] = arr[end];
    50. end -= gap;
    51. }
    52. else
    53. {
    54. break;
    55. }
    56. arr[end + gap] = tmp;
    57. }
    58. }
    59. }
    60. }

  • 相关阅读:
    鸿蒙HarmonyOS实战-ArkUI组件(mediaquery)
    leetcode 刷题 log day 43
    计算机网络-网络层篇-IP协议
    java 基于springboot+vue的居民社区健康管理平台
    Csharp线程
    [Linux] 如何查看内核 Kernel 版本(查多个Kernel的方法)
    网络渗透测试:Wireshark抓取qq图片
    七甲川染料CY7标记海藻酸钠|CY7-海藻酸钠|alginate-peg-Cyanine7
    杭州和智高薪招聘云计算/存储/网络工程师!
    验算移位距离和与迭代次数的反比关系
  • 原文地址:https://blog.csdn.net/paradiso989/article/details/139270064