• 归并排序和非比较排序


    归并排序还是比较难理解的,我们要掌握归并排序的递归和非递归的方式。

    下面先了解一下归并排序到底是什么:

    四个字----分而治之

     先从整体小的归并,然后到总的整体归并

     

     

     

    完整代码:

    void _MerGetSort(int* arr, int begin, int end, int* tmp)
    {
        if (begin >= end)
        {
            return;
        }

        //划分区域
        int mid = (begin + end) / 2;
        //递归
        _MerGetSort(arr, begin, mid, tmp);
        _MerGetSort(arr, mid + 1, end, tmp);
        
        //归并比较
        int begin1 = begin;
        int end1 = mid;
        int begin2 = mid + 1;
        int end2 = end;
        int i = begin1;
        while (begin1 <= end1 && begin2 <= end2)
        {
            if (arr[begin1] < arr[begin2])
            {
                tmp[i++] = arr[begin1++];
            }
            else
            {
                tmp[i++] = arr[begin2++];
            }
        }
        //肯定有一个已经走完了  将剩下的归并到tmp中
        while (begin1 <= end1)
        {
            tmp[i++] = arr[begin1++];
        }
        while (begin2 <= end2)
        {
            tmp[i++] = arr[begin2++];
        }

        //归并完了,将tmp拷贝回arr数组
        memcpy(arr + begin, tmp + begin, sizeof(int) * (end - begin + 1));
    }

    void MerGetSort(int* arr, int len)
    {
        //开辟一个数组
        int* tmp = (int *)malloc(sizeof(int) * len);
        _MerGetSort(arr, 0, len - 1, tmp);
        free(tmp);
    }
    void PrintSort(int* arr, int len)
    {
        for (int i = 0; i < len; i++)
        {
            printf("%d ", arr[i]);
        }
    }
    int main()
    {
        int arr[] = { 3,1,2,4,9,5,6};
        int len = sizeof(arr) / sizeof(arr[0]);
        MerGetSort(arr, len);
        
        PrintSort(arr, len);
    }
     

     

    下面介绍非递归写法:

     

    1. void MerGetSort(int* arr, int len)
    2. {
    3. //开辟一个新的数组
    4. int* tmp = (int*)malloc(sizeof(int) * len);
    5. if (tmp == NULL)//判断一下
    6. {
    7. printf("malloc fail\n");
    8. exit(-1);
    9. }
    10. int gap = 1;//确定gap
    11. while (gap < len)
    12. {
    13. printf("%d->", gap);
    14. for (int i = 0; i < len; i += 2 * gap)
    15. {
    16. //[i, i + gap - 1] [gap + i, i + 2 * gap - 1] 划分区域
    17. int begin1 = i, end1 = i + gap - 1;
    18. int begin2 = gap + i, end2 = i + 2 * gap - 1;
    19. printf("[%d][%d] [%d][%d]", begin1, end1, begin2, end2);
    20. //判断越界区域,然后修改
    21. //因为gap是多少begin1都会是最后一个,所以从end1开始修改
    22. if (end1 >= len)
    23. {
    24. end1 = len - 1;
    25. begin2 = len; //此时[begin2,end2]----[len,len-1]不合理,就不会执行
    26. end2 = len - 1;
    27. }
    28. else if (begin2 >= len)//无效区域 修改
    29. {
    30. begin2 = len;
    31. end2 = len - 1;
    32. }
    33. else if (end2 >= len)
    34. {
    35. end2 = len - 1;
    36. }
    37. int i = begin1;
    38. //然后归并比较
    39. while (begin1 <= end1 && begin2 <= end2)
    40. {
    41. if (arr[begin1] < arr[begin2])
    42. {
    43. tmp[i++] = arr[begin1++];
    44. }
    45. else
    46. {
    47. tmp[i++] = arr[begin2++];
    48. }
    49. }
    50. //走完之后,将剩下的数据放入tmp
    51. while (begin1 <= end1)
    52. {
    53. tmp[i++] = arr[begin1++];
    54. }
    55. while (begin2 <= end2)
    56. {
    57. tmp[i++] = arr[begin2++];
    58. }
    59. }
    60. printf("\n");
    61. memcpy(arr, tmp, sizeof(int) * len);//拷贝
    62. gap = gap * 2;
    63. }
    64. }
    65. void PrintSort(int* arr, int len)
    66. {
    67. for (int i = 0; i < len; i++)
    68. {
    69. printf("%d ", arr[i]);
    70. }
    71. }
    72. int main()
    73. {
    74. int arr[] = { 3,1,2,4,9,5,6};
    75. int len = sizeof(arr) / sizeof(arr[0]);
    76. MerGetSort(arr, len);
    77. PrintSort(arr, len);
    78. }

    至于无效区域是指:

    如果你不想修改边界的话,也可以直接跳过,修改如下:
    方法二:
     

     这么memcpy是一段一段拷贝的,不想方式一是全部一起拷贝,两种方式看个人喜好。

    接下来要介绍的是非比较排序

    我们接下来学的就是计数排序

    了解一下计数排序

    这种计数排序具有局限性:
    1、如果是浮点数,字符串就不能玩了

    2、如果数据范围很大,空间复杂度就会很高,也不能玩

    3、一般这些数据都是相差的幅度比较小

    当遇到100、1000以上这些数据,又相差不大的话,运用相对映射的话就非常实用了。

    //计数排序
    void CountSort(int* arr, int len)
    {
        int min = arr[0], max = arr[0];//最小最大的都是第一位  往后面去找
        for (int i = 1; i < len; i++)
        {
            if (arr[i] < min)
            {
                min = arr[i];
            }
            if (arr[i] > max)
            {
                max = arr[i];
            }
        }
        //最大最小已经找好了 开辟空间
        int range = max - min + 1;
        int* count = (int *)malloc(sizeof(int) * range);
        if (count == NULL)
        {
            printf("malloc fail\n");
            exit(-1);
        }
        memset(count, 0, sizeof(int) * range);//全部初始化成0

        //统计出现次数
        for (int i = 0; i < len; i++)
        {
            count[arr[i] - min]++;
        }

        //回写排序
        int j = 0;
        for (int i = 0; i < range; i++)
        {
            while (count[i]--)
            {
                arr[j++] = i + min;
            }
        }
    }
    void PrintSort(int* arr, int len)
    {
        for (int i = 0; i < len; i++)
        {
            printf("%d ", arr[i]);
        }
    }
    int main()
    {
        int arr[] = { 1003,1001,1002,1004,1009,1005,1006};
        int len = sizeof(arr) / sizeof(arr[0]);
        CountSort(arr, len);
        
        PrintSort(arr, len);
    }

     

     

     

    这里对前面几种排序作归类,和有缺点评估

     希望小伙伴们都能学会这些排序,你们的支持才是我前进的动力呀!

    如有错误,多多指教!

     

  • 相关阅读:
    02 使用jenkins实现K8s持续集成
    五、数据库连接池解析与编写 —— TinyWebServer
    Postman接口测试之Mock快速入门
    springboot 事务注解
    C++中带默认值的函数参数
    快速上手Linux核心命令(十一):Linux用户相关命令
    Python 全栈系列244 nginx upstream 负载均衡 踩坑日记
    SQL注入类型判断
    算法与数据结构【30天】集训营——线性表的定义及特点-顺序表的表示与实现及操作(03)
    QT 如何防止 QTextEdit 自动滚动到最下方
  • 原文地址:https://blog.csdn.net/qq_61342044/article/details/125620206