当前位置:   article > 正文

归并排序-分治递归_设递归函数max对数组的处理区间是[low, high],以中间位置mid将原问题分解为两个子

设递归函数max对数组的处理区间是[low, high],以中间位置mid将原问题分解为两个子

目录

1、归并排序-分治递归原理

根据线性表分类

链表归并

顺序表归并

1、归并排序-分治递归原理

        将待排原始链表分成大小大致相同的2个新链表,分别对2个子链表进行排序,同理将以上2个链表继续拆分,最终将排好序的子集合合并就会得到一个排好序的集合 即为所求。(参考二叉树后序递归遍历)


2、根据线性表分类

        设归并排序的当前区间是R[low..high],分治法的三个步骤是:
         ① 分解操作:将当前区间一分为二,即求分裂点 
        ② 求解递归:递归地对两个子区间R[low..mid]和R[mid+1..high] 进行归并排序;
        ③ 归并组合:将已排序的两个子区间R[low..mid]和R[mid+1..high] 归并为一个有序的区间                R[low..high]。

       顺序表归并

        通过数组上下限来确定中间位置mid。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. void Merge(int A[],int low,int mid,int high){
  4. //表A的两段A[low...mid]和A [mid+l...high]各自有序,将它们合并成一个有序表
  5. int *B= (int*)malloc((high-low+1) *sizeof (int) ) ;
  6. int i,j,k;
  7. for(k=low;k<=high;k++)
  8. B[k]=A[k]; //将A中所有元素复制到B中
  9. for (i=low,j=mid+1,k=i; i<=mid&&j<=high; k++)
  10. {
  11. if(B[i]<=B[j]) //〃比较B的左右两段中的元素
  12. A[k]=B[i++]; //将较小值复制到A中
  13. else
  14. A[k]=B[j++];
  15. }
  16. while (i<=mid) A[k++] =B [i++]; //〃若第一个表未检测完,复制
  17. while (j<=high) A[k++]=B[j++]; //若第二个表未检测完,复制
  18. }
  19. void MergeSort (int A[], int low, int high) {
  20. int mid;
  21. if(low<high){
  22. mid=(low+high)/2; //从中间划分两个子序列
  23. MergeSort (A, low, mid) ; //对左侧子序列进行递归排序
  24. MergeSort (A, mid+1, high) ; //对右侧子序列进行递归排序
  25. Merge (A,low,mid, high) ; //归并
  26. } //if *
  27. }
  28. int main()
  29. {
  30. int a[5]={5,6,9,8,7};
  31. int i;
  32. for(i=0;i<5;i++)
  33. printf("%d",a[i]);
  34. printf("\n");
  35. MergeSort(a,0,4);
  36. for(i=0;i<5;i++)
  37. printf("%d",a[i]);
  38. printf("\n");
  39. }

        链表归并

通过快慢指针fast、slow来确定中间结点位置。

slow = slow->next;
fast = fast->next->next;

遍历完成后,right=slow->next;生成右边新链表的头结点。slow->next=NULL来拆分成两个新链表

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. struct ListNode {
  4. int val;
  5. struct ListNode *next;
  6. };
  7. void see(struct ListNode*head);
  8. //对递归分开后的链表两两相治
  9. struct ListNode* mergeSort(struct ListNode* left, struct ListNode* right) {
  10. struct ListNode* res = (struct ListNode*)malloc(sizeof(struct ListNode));
  11. res->val = 0;
  12. res->next = NULL;
  13. struct ListNode* head = res;
  14. //归并中的 "合"
  15. while (left && right) {
  16. if (left->val < right->val) {
  17. //左边小
  18. head->next = left;
  19. head = head->next;
  20. left = left->next;
  21. } else {
  22. //右边小
  23. head->next = right;
  24. head = head->next;
  25. right = right->next;
  26. }
  27. }
  28. //剩下的左边
  29. while (left) {
  30. head->next = left;
  31. head = head->next;
  32. left = left->next;
  33. }
  34. //剩下的右边
  35. while (right) {
  36. head->next = right;
  37. head = head->next;
  38. right = right->next;
  39. }
  40. return res->next;
  41. }
  42. struct ListNode* MSort(struct ListNode* head)//对初始链表进行递归分开
  43. {
  44. if (head == NULL || head->next == NULL) {
  45. return head;
  46. }
  47. struct ListNode* slow = head;
  48. struct ListNode* fast = head->next;
  49. // 使用快慢指针划分链表
  50. while (fast != NULL && fast->next != NULL) {
  51. slow = slow->next;
  52. fast = fast->next->next;
  53. }
  54. struct ListNode* right = slow->next;
  55. slow->next = NULL;
  56. // 递归地对链表的两个部分进行归并排序
  57. struct ListNode* sortedLeft = MSort(head);
  58. struct ListNode* sortedRight = MSort(right);
  59. // 合并已排序的两个部分
  60. return mergeSort(sortedLeft, sortedRight);
  61. }
  62. //固定添加一组用力来测试 ,生成一个链表 ,头插法建立
  63. struct ListNode* Add()
  64. {
  65. struct ListNode* newhead=(struct ListNode*)malloc(sizeof(struct ListNode));
  66. newhead->next=NULL;
  67. int a[5]={1,6,2,3,4};// 4 3 2 6 1
  68. int i;
  69. for(i=0;i<5;i++)
  70. {
  71. struct ListNode* s=(struct ListNode*)malloc(sizeof(struct ListNode));
  72. s->val=a[i];
  73. s->next=newhead->next;
  74. newhead->next=s;
  75. }
  76. return newhead->next;
  77. }
  78. //输出链表数据
  79. void see(struct ListNode*head)
  80. {
  81. while(head!=NULL)
  82. {
  83. printf("%d",head->val);
  84. head=head->next;
  85. }
  86. printf("\n");
  87. }
  88. int main()
  89. {
  90. struct ListNode* head;
  91. head=Add();
  92. see(head);
  93. head=MSort(head);
  94. see(head);
  95. }

此时MSort()算法中,参数head是不带头结点的链表。欲对带头结点的链表进行归并排序,则MSort()做如下更改:

  1. struct ListNode* MSortD(struct ListNode* head) {
  2. if (head == NULL || head->next == NULL || head->next->next == NULL) {
  3. return head;
  4. }
  5. struct ListNode* slow = head->next;
  6. struct ListNode* fast = head->next->next;
  7. // 使用快慢指针划分链表
  8. while (fast != NULL && fast->next != NULL) {
  9. slow = slow->next;
  10. fast = fast->next->next;
  11. }
  12. struct ListNode* right = slow->next;
  13. slow->next = NULL;
  14. // 递归地对链表的两个部分进行归并排序
  15. struct ListNode* sortedLeft = MSort(head->next);//重新将头结点取消
  16. struct ListNode* sortedRight = MSort(right); //拆开的右边的新链表也是不带头结点
  17. // 合并已排序的两个部分
  18. return mergeSort(sortedLeft, sortedRight);
  19. }

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

闽ICP备14008679号