• 【数据结构】直接插入排序 & 希尔排序(一)


    目录

    一,排序的概念

    二,直接插入排序

    1,基本思想

    2,基本思路

    3,思路实现

    三,希尔排序

    1,希尔排序的特性总结:

    2,思路实现:


    一,排序的概念

    排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作;

    稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。

    内部排序:数据元素全部放在内存中的排序。

    外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。

    二,直接插入排序

    1,基本思想

    直接插入排序是一种简单的插入排序法,其基本思想是:

    把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 ;

     实际中我们玩扑克牌时,就用了插入排序的思想

    2,基本思路

    当插入第i(i>=1)个元素时,前面的 array[0],array[1],…,array[i-1] 已经排好序,此时用array[i]的排序码与 array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移;

    直接插入排序的特性总结:

    1, 元素集合越接近有序,直接插入排序算法的时间效率越高

    2.,时间复杂度:O(N^2)

    3, 空间复杂度:O(1),它是一种稳定的排序算法

    4, 稳定性:稳定

    3,思路实现

    刚开始数组前一个数 arr [ 0 ] 是有序的然后让第二个数 arr [ 1 ] 当做插入数使得前两个数有序

    然后再让第三个数 arr [ 2 ] 当做插入数使得前三个数有序

    以此类推直至数组全部有序

    我们现在写一个升序的直接插入排序

    1. //交换
    2. void Swap(int* a, int* b)
    3. {
    4. int tmp = *a;
    5. *a = *b;
    6. *b = tmp;
    7. }
    8. //插入排序
    9. void InsertSort(int* arr, int n)
    10. {
    11. int i = 0;
    12. for (i = 0; i < n-1; i++)
    13. {
    14. int end = i;
    15. int tmp = arr[end + 1];
    16. while (end >= 0)
    17. {
    18. if (arr[end] >= tmp)
    19. {
    20. //交换
    21. Swap(&arr[end], &arr[end+1]);
    22. end--;
    23. }
    24. else
    25. {
    26. break;
    27. }
    28. }
    29. arr[end + 1] = tmp;
    30. }
    31. }

    我们测试一下;

    1. //打印
    2. void PrintSort(int* arr, int n)
    3. {
    4. int i = 0;
    5. for (i = 0; i < n; i++)
    6. {
    7. printf("%d ", arr[i]);
    8. }
    9. }
    10. int main()
    11. {
    12. int arr[] = { 9,1,2,5,7,4,8,6,3,5 };
    13. //插入排序
    14. InsertSort(arr, sizeof(arr) / sizeof(arr[0]));
    15. PrintSort(arr, sizeof(arr) / sizeof(arr[0]));
    16. return 0;
    17. }

    可以看到是有序的,直接插入排序就 OK 了;

    三,希尔排序

    希尔排序法又称缩小增量法

    希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成 gap 组,所有距离为的 gap 的数组分在同一组,并对每一组内的数据进行排序。然后重复上述分组和排序的工作。当 gap=1时,所有数组在统一组内排好序;

    图示:

    1,希尔排序的特性总结

    1, 希尔排序是对直接插入排序的优化;

    2, 当 gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果;

    3, 希尔排序的时间复杂度不好计算,因为 gap 的取值方法很多,导致很难去计算,因此在好些数据中给出的希尔排序的时间复杂度都不固定

    因为我们的 gap 是按照 Knuth 提出的方式取值的,而且 Knuth 进行了大量的试验统计,我们暂时就按照:O(n^1.25) 到O(1,6*n^1.25) 来算,其实平均也就是 O(n*1.3)

    4.,稳定性:不稳定

    2,思路实现:

    我们先让 gap 的值取总数据的一半也就是 n/2 ,然后每下次循环都缩减一半直至 gap=1 ,出循环程序结束;

    1. //希尔排序
    2. void HillSort(int* arr, int n)
    3. {
    4. int gap = n;
    5. int i = 0;
    6. while (gap > 1)
    7. {
    8. gap = gap / 2;
    9. for (i = 0; i < n-gap; i++)
    10. {
    11. int end = i;
    12. int tmp = arr[end + gap];
    13. while (end >= 0)
    14. {
    15. if (arr[end] >= tmp)
    16. {
    17. //交换
    18. Swap(&arr[end], &arr[end + gap]);
    19. end -= gap;
    20. }
    21. else
    22. {
    23. break;
    24. }
    25. }
    26. arr[end + gap] = tmp;
    27. }
    28. }
    29. }

    还是上面那组数据:

    这就 OK 了,其实就是换汤不换药,学会了直接插入排序,希尔排序直接秒杀!

    第一阶段就到这里了,带大家秒杀秒杀两个排序热热身;

    后面博主会陆续更新;

    如有不足之处欢迎来补充交流!

    完结。。

  • 相关阅读:
    数据结构知识点总结-特殊矩阵-矩阵的压缩存储
    第十四届蓝桥杯模拟题第三期
    智慧寝室管理系统
    LeetCode:689. 三个无重叠子数组的最大和(dp C++)
    7.缓存击穿、缓存穿透、缓存
    代码随想录算法训练营 day46|139.单词拆分
    云原生面试
    【rust】rsut基础:模块的使用一、mod 关键字、mod.rs 文件的含义等
    大数据技术之Zookeeper案例总结
    uniapp webview实现双向通信
  • 原文地址:https://blog.csdn.net/m0_71676870/article/details/133278801