• c、c++排序的相关知识(归并排序、计数排序、稳定性等)


    排序,是对给定的一组数,按照某种逻辑关系,进行位置上的移动。由于排序至少需要将所有数过一遍(正常情况下,非特殊数组),因此排序的时间复杂度一定不能小于O(N)。

    归并排序:通过将一个大数据组分割成一个个小数据组,对小数据组排序,排好序后再整体排序。

    时间复杂度为O(NlogN),空间复杂度为O(N),其算法最好、最坏情况下时间复杂度均为O(NlogN),是一种十分高效的排序算法,本质上是一种以空间换时间的算法。

    1. void _merge(int* a, int* tmp, int left1, int right1, int left2, int right2)
    2. {
    3. int left = left1;
    4. int right = right2;
    5. int cur = left1;
    6. while (left1 <= right1 && left2 <= right2)
    7. {
    8. if (a[left1] < a[left2])
    9. {
    10. tmp[cur++] = a[left1++];
    11. }
    12. else
    13. {
    14. tmp[cur++] = a[left2++];
    15. }
    16. }
    17. while (left1 <= right1)
    18. {
    19. tmp[cur++] = a[left1++];
    20. }
    21. while (left2 <= right2)
    22. {
    23. tmp[cur++] = a[left2++];
    24. }
    25. while (left<= right)
    26. {
    27. a[left] = tmp[left];
    28. left++;
    29. }
    30. }
    31. void merge(int* a, int* tmp, int left, int right)
    32. {
    33. if (left >= right)
    34. {
    35. return;
    36. }
    37. int mid=(left+right)/2;
    38. merge(a, tmp, left, mid);
    39. merge(a, tmp, mid + 1, right);
    40. _merge(a, tmp, left,mid,mid+1, right);
    41. }
    42. // 归并排序递归实现
    43. void MergeSort(int* a, int n)
    44. {
    45. int* tmp = (int*)malloc(sizeof(int) * n);
    46. if (tmp == NULL)
    47. {
    48. perror("malloc");
    49. exit(-1);
    50. }
    51. merge(a, tmp, 0, n-1);
    52. free(tmp);
    53. }
    54. // 归并排序非递归实现
    55. void MergeSortNonR(int* a, int n)
    56. {
    57. int* tmp = (int*)malloc(sizeof(int) * n);
    58. if (tmp == NULL)
    59. {
    60. perror("malloc");
    61. exit(-1);
    62. }
    63. int gap = 1;
    64. while (gap < n)
    65. {
    66. for (int i = 0; i < n; i += 2*gap)
    67. {
    68. int left1 = i;
    69. int right1 = i + gap - 1;
    70. int left2 = i + gap;
    71. int right2 = i + 2 * gap - 1;
    72. if (right1 >= n-1)
    73. {
    74. break;
    75. }
    76. if (right2 >= n)
    77. {
    78. right2 = n - 1;
    79. }
    80. _merge(a, tmp, left1, right1, left2, right2);
    81. }
    82. gap *= 2;
    83. }
    84. free(tmp);
    85. }

    对于递归的算法,就是单纯的不断分割直到只有一个数无法再分割,然后在往回不断归并,结构上类似二叉树的后序遍历。

    对于非递归的算法,由于其在逻辑上需要不断进行归并、不断扩大每次归并的数据个数,因此很难通过栈的方式模拟实现,而是选择了用gap当做当前每次归并时一组数的个数,而这里最需要注意的就是数组越界问题,即除了begin1之外的数都有可能会越界,因此需要判断。当begin2>=n的时候,即第二个数不存在,因此不需要归并。当end2>=n的时候,即第二个存在,但大小无法到gap个,此时缩小end2的大小,使得第二组的数据个数为end2-begin2+1个,再与第一组数进行归并。

    稳定性:

    所谓稳定性,就是指原本相同的数据的相对位置关系,在排序后不发生变化。

    常见的排序有冒泡排序、直接插入排序、希尔排序、堆排序、快速排序、归并排序、选择排序。

    其中稳定的有冒泡排序、直接插入排序、归并排序

    不稳定:

    1.希尔排序:原因是在预排序的时候可能同样的数据在不同的组进行排序,导致相对位置变化

    2.堆排序:原因是堆排序时要把根节点的元素与最后一个元素互换,导致数据之间的相对位置变化。

    3:选择排序:原因是找到最大、最小的元素,将当前最左、最右测的元素与其互换的时候可能会使得位置发生改变。

    4:快速排序:每次将最左侧的元素放到最终位置时,可能会导致相对位置改变。

  • 相关阅读:
    邦芒宝典:工作中如何自我定位
    Angular核心-路由和导航
    深入学习MYSQL-使用触发器
    位图的详细介绍及模拟实现
    pgpool-II 4.3 中文手册-前言
    halcon算子1、dev_open_window
    python中的常用函数介绍
    你需要知道的13个有用的Python片段
    MySQL进阶 —— 超详细操作演示!!!(中)
    Hive学习笔记(1)
  • 原文地址:https://blog.csdn.net/yyssas/article/details/133352135