当前位置:   article > 正文

【归并排序,小和问题,利用C++实现】_c++小和问题

c++小和问题

1 归并排序(升序或降序只需在左右侧比较时修改即可)

  求数组左侧有序和右侧有序,然后合并左侧和右侧完成排序。

  对于数组a={1,4,2,5,3},mid=0+(4-0)/2=2,

第一步:从a的下标i=2处将a分为:左侧{1,4,2}右侧{5,3};

第二步:计算左侧的mid,将左侧{1,4,2}分为:左侧{1,4}右侧{2};

第三步:计算左侧的mid,将左侧{1,4}分为:左侧{1}右侧{4};

第四步:当不能进行分割时开始比较当前的左侧和右侧值进行排序,倒着执行到第一步完成数组a左侧的排序{1,2,4};

第五步:对数组a的右侧进行上述步骤,完成右侧排序{3,5};

最后:合并左侧{1,2,4}右侧{3,5},合并时若左侧a[i]<右侧a[j],先拷贝a[i],此为升序,若为降序则相反。 7-99999999999999

如图:

 

2 完整代码如下:

  1. #include<iostream>
  2. using namespace std;
  3. //1.归并排序,利用递归,先将两侧排好序,再进行合并
  4. //比较相邻序列
  5. void merge(int arr[], int temp[], int start,int mid, int end)
  6. {
  7. cout << "(start,mid,end)=" << "(" << start << "," << mid << "," << end << ")" << endl;
  8. int i = start, j = mid + 1, k = start;
  9. //将较小值放入temp
  10. while (i != mid+1 && j != end+1)
  11. {
  12. if (arr[i] <arr[j])
  13. {
  14. temp[k++] = arr[i++];
  15. }
  16. else
  17. {
  18. temp[k++] = arr[j++];
  19. }
  20. }
  21. //将多的数放到temp末尾
  22. while (i!= mid + 1)
  23. {
  24. temp[k++] = arr[i++];
  25. }
  26. while (j != end + 1)
  27. {
  28. temp[k++] = arr[j++];
  29. }
  30. //更新序列
  31. for (int i = start; i <= end; i++)
  32. {
  33. arr[i] = temp[i];
  34. cout << arr[i] << " ";
  35. }
  36. cout << endl;
  37. }
  38. //排序
  39. void merge_sort(int arr[], int temp[], int start, int end)
  40. {
  41. int mid = 0;
  42. if (start < end)
  43. {
  44. mid = start + (end - start) / 2;
  45. //递归调用
  46. merge_sort(arr, temp, start, mid);
  47. merge_sort(arr, temp, mid + 1, end);
  48. merge(arr, temp, start, mid, end);
  49. }
  50. }
  51. int main()
  52. {
  53. int a[5] = {1,4,2,5,3};
  54. int t[5];
  55. merge_sort(a, t, 0, 4);
  56. for (int i = 0; i < 5; i++)
  57. {
  58. cout << a[i] << " ";
  59. }
  60. cout << endl;
  61. system("pause");
  62. system("cls");
  63. return 0;
  64. }

3 小和问题 

 问题描述:在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和

以上述中a={1,4,2,5,3}为例:记小和为:res=0

(1)1左边比1小的数为0(1左边没有数字),res=0+0;

(2)4左边比4小的数为1,                                 res=0+1

(3)2左边比2小的数为1,                                  res=0+1+1

(4)5左边比5小的数为1,4,2,                            res=0+1+1+1+4+2

(5)3左边比3小的数为1,2,                               res=0+1+1+1+4+2+1+2=12

从上述可以得出比1的右侧比1大的个数为4,比4大的个数为1,比2大的数的个数为2,比5大的数的个数为0,比3大的数的个数为0

  小和  res=1*4 + 4*1 + 2*2 + 5*0 + 3*0=12

因此小和问题只需在归并排序过程中记录比当前数a[i]大的数的个数 num    res+=a[i]*num

注意:当左侧数等于右侧数,即:a[i]==a[j] 时应先拷贝右侧数,即 :temp=a[j],否则统计不出比当前数字大的数的个数.

4 小和详细代码:

  1. #include<iostream>
  2. using namespace std;
  3. /*
  4. 小和问题描述:
  5. 在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和
  6. */
  7. //分段排序
  8. int merge(int arr[], int temp[], int start, int mid, int end)
  9. {
  10. cout << "(start,mid,end)=" << "(" << start << "," << mid << "," << end << ")" << endl;
  11. int i = start, j = mid+1, k = start;
  12. int res = 0;
  13. while(i != mid + 1 && j != end + 1)
  14. {
  15. //若左侧等于右侧先拷贝右侧,否则算不出比当前数大的数的个数
  16. if (arr[i] == arr[j])
  17. {
  18. temp[k++] = arr[j++];
  19. }
  20. else if (arr[i] < arr[j]) //注意此处不要写为arr[i++]<arr[j++]
  21. {
  22. res += (end - j + 1) * arr[i]; //num=end-j+1为比当前数a[i]大的数的个数
  23. temp[k++] = arr[i++];
  24. }
  25. else
  26. {
  27. temp[k++] = arr[j++];
  28. }
  29. }
  30. //将多余的数放到temp末尾
  31. while (i != mid + 1)
  32. {
  33. temp[k++] = arr[i++];
  34. }
  35. while (j != end + 1)
  36. {
  37. temp[k++] = arr[j++];
  38. }
  39. //更新a[]
  40. for (int i=start;i<= end;i++)
  41. {
  42. arr[i] = temp[i];
  43. cout << arr[i] << " ";
  44. }
  45. cout << endl;
  46. return res;
  47. }
  48. //递归排序
  49. int merge_sort(int arr[], int temp[], int start, int end)
  50. {
  51. int mid = 0;
  52. if (start == end) //此时不记录小和
  53. {
  54. return 0;
  55. }
  56. mid = start + (end - start) / 2;
  57. //递归调用
  58. return merge_sort(arr,temp,start,mid)
  59. +merge_sort(arr, temp, mid + 1, end)
  60. +merge(arr, temp, start, mid, end);
  61. }
  62. int main()
  63. {
  64. //准备数组{ 2, 3, 4, 1, 2, 3, 8, 9, 0 };小和=5*2+3*3+2*4+4*1+3*2+2*3+1*8=
  65. int a[5] = { 1,4,2,5,3 };
  66. int t[5];
  67. int Sum = 1 * 4 + 4 * 1 + 2 * 2 + 5 * 0 + 3 * 0;
  68. int sum=merge_sort(a, t, 0, 4);
  69. cout << "a=";
  70. for (int i = 0; i < 5; i++)
  71. {
  72. cout << a[i] << ",";
  73. }
  74. cout << endl;
  75. cout << "验证Sum=" << Sum << endl;
  76. cout << "小和sum=" << sum << endl;
  77. return 0;
  78. }

结果: 

这是作者的学习笔记,在此分享,仅供参考。因为作者水平有限,如有疏漏之处,还望批评指正。 

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

闽ICP备14008679号