当前位置:   article > 正文

归并排序的实现(排序算法c语言描述)_用数学语言描述归并排序

用数学语言描述归并排序
归并排序法是将两个(或两个以上)有序表合并成一个新的有序表,是建立在归并操作上的一种有效的排序算法,具体是把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。该算法是采用分治法的一个非常典型的应用。所以归并排序的核心在于先分解,再合并。
基本思路:
将数组分成二组A,B,如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。为了让这两组数据是有序的,可以继续将A,B组各自再分成二组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。这样就实现了先递归的分解数列,再合并数列就完成了归并排序。
具体操作:
1) 将n个元素分成各含n/2个元素的子序列
2)用归并排序法对这两个子序列递归地排序
3)合并这两个已经排序好的子序列得到排序结果

我们通过一个图像来形象的理解一下:

代码:
下面,我们先看看实现有序数组的合并:

  1. /*将有序数组array[start~middle]与array[middle+1~end]合并为一个数组
  2. void merge(int array[], int start, int middle, int end)
  3. {
  4. int tmp[MAX] = {0}; // 临时数组
  5. int i; //第一个数组索引
  6. int j; //第二个数组索引
  7. int k; //临时数组索引
  8. for (i = start, j = middle+1, k = 0; k <= end-start; k++) // 分别将 i, j, k 指向各自数组的首部。
  9. {
  10. //若 i 到达第一个数组的尾部,将第二个数组余下元素复制到 临时数组中
  11. if (i == middle+1)
  12. {
  13. tmp[k] = array[j++];
  14. continue;
  15. }
  16. //若 j 到达第二个数组的尾部,将第一个数组余下元素复制到 临时数组中
  17. if (j == end+1)
  18. {
  19. tmp[k] = array[i++];
  20. continue;
  21. }
  22. //如果第一个数组的当前元素 比 第二个数组的当前元素小,将 第一个数组的当前元素复制到 临时数组中
  23. if (array[i] < array[j])
  24. {
  25. tmp[k] = array[i++];
  26. }
  27. //如果第二个数组的当前元素 比 第一个数组的当前元素小,将 第二个数组的当前元素复制到 临时数组中
  28. else
  29. {
  30. tmp[k] = array[j++];
  31. }
  32. }
  33. //将有序的临时数组元素复制到array中,
  34. //i = start 被排序的数组array 的起始位置
  35. //j = 0, 临时数组的起始位置
  36. for (i = start, j = 0; i <= end; i++, j++)
  37. {
  38. array[i] = tmp[j];
  39. }
  40. }
我们继续看归并排序的实现:

  1. // 归并排序
  2. void mergesort(int array[], int start, int end)
  3. {
  4. if (start < end)
  5. {
  6. int middle;
  7. middle = (end + start) / 2;
  8. // 对前半部分进行排序
  9. mergesort(array, start, middle);
  10. // 对后半部分进行排序
  11. mergesort(array, middle + 1, end);
  12. // 合并前后两部分
  13. merge(array, start, middle, end);
  14. }
  15. }

测试程序:

  1. #include <stdio.h>
  2. #define MAX 10
  3. // 打印结果
  4. void show(int arr[], int n)
  5. {
  6. int i;
  7. for ( i=0; i<n; i++ )
  8. printf("%d ", arr[i]);
  9. printf("\n");
  10. }
  11. void merge(int array[], int start, int middle, int end)
  12. {
  13. int tmp[MAX] = {0}; // 临时数组
  14. int i; //第一个数组索引
  15. int j; //第二个数组索引
  16. int k; //临时数组索引
  17. for (i = start, j = middle+1, k = 0; k <= end-start; k++) // 分别将 i, j, k 指向各自数组的首部。
  18. {
  19. //若 i 到达第一个数组的尾部,将第二个数组余下元素复制到 临时数组中
  20. if (i == middle+1)
  21. {
  22. tmp[k] = array[j++];
  23. continue;
  24. }
  25. //若 j 到达第二个数组的尾部,将第一个数组余下元素复制到 临时数组中
  26. if (j == end+1)
  27. {
  28. tmp[k] = array[i++];
  29. continue;
  30. }
  31. //如果第一个数组的当前元素 比 第二个数组的当前元素小,将 第一个数组的当前元素复制到 临时数组中
  32. if (array[i] < array[j])
  33. {
  34. tmp[k] = array[i++];
  35. }
  36. //如果第二个数组的当前元素 比 第一个数组的当前元素小,将 第二个数组的当前元素复制到 临时数组中
  37. else
  38. {
  39. tmp[k] = array[j++];
  40. }
  41. }
  42. //将有序的临时数组元素复制到array中,
  43. //i = start 被排序的数组array 的起始位置
  44. //j = 0, 临时数组的起始位置
  45. for (i = start, j = 0; i <= end; i++, j++)
  46. {
  47. array[i] = tmp[j];
  48. }
  49. }
  50. //我们继续看归并排序的实现:
  51. // 归并排序
  52. void mergesort(int array[], int start, int end)
  53. {
  54. if (start < end)
  55. {
  56. int middle;
  57. middle = (end + start) / 2;
  58. // 对前半部分进行排序
  59. mergesort(array, start, middle);
  60. // 对后半部分进行排序
  61. mergesort(array, middle + 1, end);
  62. // 合并前后两部分
  63. merge(array, start, middle, end);
  64. }
  65. }
  66. int main()
  67. { //测试数据
  68. int arr_test[MAX] = { 8, 4, 2, 3, 5, 1, 6, 9, 0, 7 };
  69. //排序前数组序列
  70. show( arr_test, MAX );
  71. mergesort( arr_test, 0, MAX-1 );
  72. //排序后数组序列
  73. show( arr_test, MAX );
  74. return 0;
  75. }


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/寸_铁/article/detail/817397
推荐阅读
相关标签
  

闽ICP备14008679号