当前位置:   article > 正文

归并排序三种实现方法(递归、非递归和自然合并排序)_3、归并排序:用递归算法实现归并排序,在主函数中输入一些数据,并通过该递归函数进

3、归并排序:用递归算法实现归并排序,在主函数中输入一些数据,并通过该递归函数进

                

1.      递归实现归并排序

1)     基本思想:

将待排元素分成大小大致相同的2个子集,分别对2个子集合进行排序,最终将排好序的子集合合并 就会得到一个排好序的集合 即为所求

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

递归的终结条件:子区间长度为1(一个记录自然有序)。

2)     具体过程如下图所示:


3)     代码实现

 

  1. /*
  2. 数组a[]为待排序数组,数组b[]用来存放已排好序的数
  3. left、right分别为待排序数组最左端和最右端的下标
  4. mid为数组下标的中点
  5. */
  6. #include<iostream>
  7. #include<algorithm>
  8. using namespace std;
  9. #define maxn 100
  10. int num[maxn];
  11. // 将待排序集合一分为二,直至待排序集合只剩下一个元素为止,
  12. // 然后不断合并两个排好序的数组段
  13. template<class Type>
  14. void MergeSort(Type a[],int left,int right)
  15. {
  16. Type *b=new Type [maxn];
  17. if(left<right) //控制待排序数组中至少有两个元素,一个元素时为有序
  18. {
  19. int i=(left+right)/2; //取数组中点,将数组尽量均等划分
  20. MergeSort(a,left,i); //将左半段进行递归排序
  21. MergeSort(a,i+1,right); //将右半段进行递归排序
  22. Merge(a,b,left,i,right); //合并到数组b
  23. Copy(a,b,left,right); //复制到数组a
  24. }
  25. }
  26. // 将已排好序的数组合并到数组b[]中
  27. template<class Type>
  28. void Merge(Type a[],Type b[],int left,int mid,int right)
  29. {
  30. int i=left;
  31. int j=mid+1;
  32. int k=left;
  33. while(i<=mid && j<=right) //i的取值范围为 [left,m], j的取值范围为 [m+1,right]
  34. {
  35. if(a[i]<a[j]) //取左右两边数组中较小的元素放入数组b中,最后得到的数组b即为有序
  36. b[k++]=a[i++];
  37. else
  38. b[k++]=a[j++];
  39. }
  40. if(i>mid) //说明右边的数组的元素个数多
  41. for(int z=j;z<=right;z++)
  42. b[k++]=a[z];
  43. else
  44. for(int z=i;i<=mid;i++)
  45. b[k++]=a[z];
  46. }
  47. // 将数组b[]中的数复制到数组a[]中
  48. template<class Type>
  49. void Copy(Type a[],Type b[],int left,int right)
  50. {
  51. for(int i=left;i<=right;i++)
  52. a[i]=b[i];
  53. }
  54. int main()
  55. {
  56. int n;
  57. while(cin>>n)
  58. {
  59. for(int i=0;i<n;i++)
  60. cin>>num[i];
  61. MergeSort(num,0,n-1);
  62. for(int i=0;i<n;i++)
  63. cout<<num[i]<<endl;
  64. }
  65. system("pause");
  66. return 0;
  67. }
  68. /*
  69. 7
  70. 49 38 65 97 76 13 27
  71. */

2.      非递归实现归并排序

1)   基本思想:

将数组中的相邻元素两两配对。用Merge()函数将他们排序,构成n/2组长度为2的排序好的子数组段,然后再将他们合并成长度为4的子数组段,如此继续下去,直至整个数组排好序

2)   具体过程如下图所示:

例1:8   3   2   6   7   1   5   4

    

 

例2:49   38   65  97   76   13   27



 

  

例2:49   38   65  97   76   (如上图)

3)   代码实现 

  1. #include<iostream>
  2. #include<algorithm>
  3. using namespace std;
  4. #define maxn 100
  5. int num[maxn];
  6. template<class Type>
  7. void MergeSort(Type c[],int n)
  8. {
  9. Type *d=new Type [n];
  10. int s=1;
  11. while(s<n)
  12. {
  13. MergePass(c,d,s,n); //合并到数组d
  14. s+=s;
  15. MergePass(d,c,s,n); //合并到数组c
  16. s+=s;
  17. }
  18. }
  19. // 合并大小为s的相邻子数组
  20. template<class Type>
  21. void MergePass(Type x[],Type y[],int s,int n)
  22. {
  23. int i=0;
  24. while(i+2*s-1<n)
  25. {
  26. Merge(x,y,i,i+s-1,i+2*s-1); //合并大小为s的相邻2段子数组
  27. i+=2*s;
  28. }
  29. if(i+s<n) //剩下的元素个数m满足:s<= m <2*s
  30. Merge(x,y,i,i+s-1,n-1);
  31. else //剩下的元素个数m满足:m<s
  32. for(int j=i;j<=n-1;j++)
  33. y[j]=x[j];
  34. }
  35. template<class Type>
  36. void Merge(Type a[],Type b[],int left,int mid,int right)
  37. {
  38. int i=left;
  39. int j=mid+1;
  40. int k=left;
  41. while(i<=mid && j<=right)
  42. {
  43. if(a[i]<a[j])
  44. b[k++]=a[i++];
  45. else
  46. b[k++]=a[j++];
  47. }
  48. if(i>mid)
  49. for(int z=j;z<=right;z++)
  50. b[k++]=a[z];
  51. else
  52. for(int z=i;z<=mid;z++)
  53. b[k++]=a[z];
  54. }
  55. int main()
  56. {
  57. int n;
  58. while(cin>>n)
  59. {
  60. for(int i=0;i<n;i++)
  61. cin>>num[i];
  62. MergeSort(num,n);
  63. for(int i=0;i<n;i++)
  64. cout<<num[i]<<endl;
  65. }
  66. system("pause");
  67. return 0;
  68. }
  69. /*
  70. 8
  71. 8 3 2 6 7 1 5 4
  72. 7
  73. 49 38 65 97 76 13 27
  74. 5
  75. 49 38 65 97 76
  76. */

                                                 

3.      自然合并排序

1)   基本思想:

对于初始给定的数组a,通常存在多个长度大于1的已排好序的子数组段。因此用一次对a的线性扫描就可以找出所有这些排好序的子数组段,然后将相邻的排好序的子数组段两两合并

2)   样例:

若数组a中元素为{4,8,3,7,1,5,6,2},则自然排好序的子数组段有{4,8},{3,7},{1,5,6},{2},经一次合并后得到2个合并后的子数组段{3,4,7,8}和{1,2,5,6},继续合并相邻排好序的子数组段,直至整个数组已排好序,最终结果{1,2,3,4,5,6,7,8}

3)   代码实现

  1. #include<iostream>
  2. #include<algorithm>
  3. #include<cstdio>
  4. #include<stdlib.h>
  5. using namespace std;
  6. #define maxn 100
  7. int num[maxn];
  8. int sl[maxn]; //记录每个有序子串的起始坐标
  9. template<class Type>
  10. void MergeSort(Type a[],int n)
  11. {
  12. Type *b=new Type [n];
  13. int sNum=MergePass(a,n); //sNum = 有序子串的个数 +1
  14. while(sNum!=2)
  15. {
  16. for(int i=0;i<sNum;i+=2)
  17. {
  18. Merge(a,b,sl[i],sl[i+1]-1,sl[i+2]-1); //对sNUm个子串进行两两合并
  19. }
  20. sNum=MergePass(a,n); //求出经上次合并后的数组中有序子串的个数
  21. }
  22. }
  23. // 得到每个有序子串的起始位置 将其放入数组sl中 函数返回值为有序子串的个数
  24. template<class Type>
  25. int MergePass(Type x[],int n)
  26. {
  27. int k=0;
  28. int begin=x[0];
  29. sl[k++]=0; //第一个有序子串的起始位置为 0
  30. for(int i=1;i<n;i++)
  31. {
  32. if(begin>x[i])
  33. sl[k++]=i;
  34. begin=x[i];
  35. }
  36. sl[k++]=n;
  37. return k;
  38. }
  39. // 对相邻的有序子串进行合并,并将合并后的结果保存在数组b中,然后再复制到数组a中
  40. template<class Type>
  41. void Merge(Type a[],Type b[],int left,int mid,int right)
  42. {
  43. int j=left;
  44. int k=mid+1;
  45. for(int i=left;i<=right;i++)
  46. {
  47. if(j>mid)
  48. b[i]=a[k++];
  49. else if(k>right)
  50. b[i]=a[j++];
  51. else if(a[j]>a[k])
  52. b[i]=a[k++];
  53. else
  54. b[i]=a[j++];
  55. }
  56. for(int i=left;i<=right;i++)
  57. a[i]=b[i];
  58. }
  59. int main()
  60. {
  61. int n;
  62. while(cin>>n)
  63. {
  64. memset(num,0,sizeof(num));
  65. memset(sl,0,sizeof(sl));
  66. for(int i=0;i<n;i++)
  67. cin>>num[i];
  68. MergeSort(num,n);
  69. for(int i=0;i<n;i++)
  70. cout<<num[i]<<endl;
  71. }
  72. system("pause");
  73. return 0;
  74. }
  75. /*
  76. 7
  77. 49 38 65 97 76 13 27
  78. 7
  79. 13 27 49 38 65 97 76
  80. */


 

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

闽ICP备14008679号