在原作者基础上加入注释

原作者:https://www.cnblogs.com/agui521/p/6918229.html

归并排序:归并排序(英语:Merge sort,或mergesort),是创建在归并操作上的一种有效的排序算法,效率为O(n log n)。1945年由约翰·冯·诺伊曼首次提出。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。

归并排序的核心思想是将两个有序的数列合并成一个大的有序的序列。通过递归,层层合并,即为归并。

如图,从下到上,每一步都需要将两个已经有序的子数组合并成一个大的有序数组,如下是实现合并的具体代码,请读者细细体会

 
  1. void merge(int arr[],int l,int mid,int r)
  2. {
  3. int aux[r-l+1];//开辟一个新的数组,将原数组映射进去
  4. for(int m=l;m<=r;m++)
  5. {
  6. aux[m-l]=arr[m];
  7. }
  8.  
  9. int i=l,j=mid+1;//i和j分别指向两个子数组开头部分
  10.  
  11. for(int k=l;k<=r;k++)
  12. {           
  13.   //分四种情况判断:
  14.   //i>mid 把大于mid的数据并入;j>r 把i-mid的数据并入;
  15. //aux[i-l]<aux[j-l],把小的数据即aux[i-l]并入,同理aux[i-l]>=aux[j-l]
  16. if(i>mid)
  17. {
  18. arr[k]=aux[j-l];
  19. j++;
  20. }
  21. else if(j>r)
  22. {
  23. arr[k]=aux[i-l];
  24. i++;
  25. }
  26. else if(aux[i-l]<aux[j-l])
  27. {
  28. arr[k]=aux[i-l];
  29. i++;
  30. }
  31. else
  32. {
  33. arr[k]=aux[j-l];
  34. j++;
  35. }
  36. }
  37. }

  

 

上图代码已经完成了归并中的“并”这一部分,归并归并,有并必有归,如下实现“归”的部分

  1. 1 void merge_sort(int arr[],int l,int r)
  2. 2 {
  3. 3 if(l >=r)
  4. 4 return ;
  5. 5 int mid=(l+r)/2;
  6. 6 merge_sort(arr,l,mid);  //这个函数的递归为了获取 l和mid 的值
  7. 7 merge_sort(arr,mid+1,r); //这两个递归主要为了获取 r 的值 为下面的 merge函数提供实参
  8. 8 merge(arr,l,mid,r);    
  9. 9 }

由于上图中的l,r不方便使用者调用,于是我们创建一个方便自己调用的my_merge_sort函数

  1. 1 void my_merge_sort(int arr[],int n)
  2. 2 {
  3. 3 merge_sort(arr,0,n-1);
  4. 4 }

以上我们便实现了归并排序中的归和并,归并排序是利用二分法实现的排序算法,时间复杂度为nlogn,是一种比较快速的排序算法。如下是笔者自己写的归并排序的全部代码,

  1. 1 #include <iostream>
  2. 2 using namespace std;
  3. 3
  4. 4
  5. 5 void merge(int arr[],int l,int mid,int r)
  6. 6 {
  7. 7 int aux[r-l+1];//开辟一个新的数组,将原数组映射进去
  8. 8 for(int m=l;m<=r;m++)
  9. 9 {
  10. 10 aux[m-l]=arr[m];
  11. 11 }
  12. 12
  13. 13 int i=l,j=mid+1;//i和j分别指向两个子数组开头部分
  14. 14
  15. 15 for(int k=l;k<=r;k++)
  16. 16 {
  17. 17 if(i>mid)
  18. 18 {
  19. 19 arr[k]=aux[j-l];
  20. 20 j++;
  21. 21 }
  22. 22 else if(j>r)
  23. 23 {
  24. 24 arr[k]=aux[i-l];
  25. 25 i++;
  26. 26 }
  27. 27 else if(aux[i-l]<aux[j-l])
  28. 28 {
  29. 29 arr[k]=aux[i-l];
  30. 30 i++;
  31. 31 }
  32. 32 else
  33. 33 {
  34. 34 arr[k]=aux[j-l];
  35. 35 j++;
  36. 36 }
  37. 37 }
  38. 38 }
  39. 39 //递归的使用归并排序,对arr[l....r]排序
  40. 40 void merge_sort(int arr[],int l,int r)
  41. 41 {
  42. 42 if(l >=r)
  43. 43 return ;
  44. 44 int mid=(l+r)/2;
  45. 45 merge_sort(arr,l,mid);
  46. 46 merge_sort(arr,mid+1,r);
  47. 47 merge(arr,l,mid,r);
  48. 48 }
  49. 49
  50. 50 void my_merge_sort(int arr[],int n)
  51. 51 {
  52. 52 merge_sort(arr,0,n-1);
  53. 53 }
  54. 54
  55. 55 int main()
  56. 56 {
  57. 57 int a[6];
  58. 58 for(int i=0;i<6;i++)
  59. 59 {
  60. 60 cin>>a[i];
  61. 61 }
  62. 62 my_merge_sort(a,6);
  63. 63 for(int i=0;i<6;i++)
  64. 64 {
  65. 65 cout<<a[i]<<" ";
  66. 66 }
  67. 67 return 0;
  68. 68 }

上面实现的归并排序是自顶向下的,我们可以以另外一种方向来实现归并,改递归为迭代。如下实现

  1. 1 #include <iostream>
  2. 2 #include <math.h>
  3. 3 using namespace std;
  4. 4
  5. 5 void merge(int arr[],int l,int mid,int r)
  6. 6 {
  7. 7 int aux[r-l+1];//开辟一个新的数组,将原数组映射进去
  8. 8 for(int m=l;m<=r;m++)
  9. 9 {
  10. 10 aux[m-l]=arr[m];
  11. 11 }
  12. 12
  13. 13 int i=l,j=mid+1;//i和j分别指向两个子数组开头部分
  14. 14
  15. 15 for(int k=l;k<=r;k++)
  16. 16 {
  17. 17 if(i>mid)
  18. 18 {
  19. 19 arr[k]=aux[j-l];
  20. 20 j++;
  21. 21 }
  22. 22 else if(j>r)
  23. 23 {
  24. 24 arr[k]=aux[i-l];
  25. 25 i++;
  26. 26 }
  27. 27 else if(aux[i-l]<aux[j-l])
  28. 28 {
  29. 29 arr[k]=aux[i-l];
  30. 30 i++;
  31. 31 }
  32. 32 else
  33. 33 {
  34. 34 arr[k]=aux[j-l];
  35. 35 j++;
  36. 36 }
  37. 37 }
  38. 38 }
  39. 39
  40. 40 void mergesort(int arr[],int n)
  41. 41 {
  42. 42 for(int sz=1;sz<=n;sz+=sz)
  43. 43 {
  44. 44 for(int i=0;i+sz<n;i+=sz+sz)//i+sz防止越界 i+=sz+sz 相当于 i+=(sz+sz) 先2个2个排序,再4个4个排序,再8个8个排序
  45.  
  46. 45       {//对arr[i...sz-1]和arr[i+sz.....i+2*sz-1]进行排序
  1. 46       merge(arr,i,i+sz-1,min(i+sz+sz-1,n-1)); //min函数防止越界
  1. 47       }
    48   }
    49
    50 }
    51
    52 int main()
    53 {
    54 int a[5];
    55 for(int i=0;i<5;i++)
    56 {
    57 cin>>a[i];
    58 }
    59 mergesort(a,5);
    60 for(int i=0;i<5;i++)
    61 {
    62 cout<<a[i]<<" ";
    63 }
    64 return 0;
    65 }

C++版 归并排序的更多相关文章

  1. javascript实现非递归--归并排序

    另一道面试题是实现归并排序,当然,本人很不喜欢递归法,因为递归一般都是没有迭代法好.所以首选都是用迭代法,但是迭代法确实是难做啊,至底而上的思想不好把握. 这是我的实现代码 /* * * 非递归版归并 ...

  2. 算法与数据结构(十五) 归并排序(Swift 3.0版)

    上篇博客我们主要聊了堆排序的相关内容,本篇博客,我们就来聊一下归并排序的相关内容.归并排序主要用了分治法的思想,在归并排序中,将我们需要排序的数组进行拆分,将其拆分的足够小.当拆分的数组中只有一个元素 ...

  3. 算法导论(第三版)Exercises2.3(归并排序、二分查找、计算集合中是否有和为X的2个元素)

    2.3-1: 3 9 26 38 41 49 52 59 3 26 41 52   9 38 49 57 3 41   52 26   38 57   9 49 3   41  52  26  38  ...

  4. 归并排序—Java版

    一开始做算法的时候,感觉递归算法很绕,所以我就在阅读别人代码的基础上,对代码每一步都添加自己的注解,方便我以后的学习. public class MergeSort { /** * 归并排序 * @p ...

  5. C#版 - LeetCode 148. Sort List 解题报告(归并排序小结)

    leetcode 148. Sort List 提交网址: https://leetcode.com/problems/sort-list/  Total Accepted: 68702 Total ...

  6. 结合《剑指offer(第二版)》面试题51来谈谈归并排序

    一.题目大意 给定一个数组A,对于数组A中的两个数字,如果排在前面的一个数字大于(必须大于,等于不算)后面的数字,则这两个数字组成一个逆序对.要求输出数组A中的逆序对的总数.例如,对于数组{7,5,6 ...

  7. 算法分析中最常用的几种排序算法(插入排序、希尔排序、冒泡排序、选择排序、快速排序,归并排序)C 语言版

    每次开始动手写算法,都是先把插入排序,冒泡排序写一遍,十次有九次是重复的,所以这次下定决心,将所有常规的排序算法写了一遍,以便日后熟悉. 以下代码总用一个main函数和一个自定义的CommonFunc ...

  8. 数据结构之排序技术:快速排序、归并排序、堆排序(C++版)

    快速排序 #include <iostream> using namespace std; void swap(int num[], int i, int j) { int temp = ...

  9. C++_归并排序(纯C版)

    #include <iostream> #include <stdlib.h> using namespace std; int compared(const void *ke ...

随机推荐

  1. 一图了解DLL和SYS的区别

    The following diagram shows the device node, kernel-mode device stack, and the user-mode device stac ...

  2. oc Learning Blog

    http://www.cnblogs.com/heyonggang/p/3351269.html M了个J :http://www.cnblogs.com/mjios/tag/objective-c/ ...

  3. 谈谈Java对象的强引用,软引用,弱引用,虚引用分别是什么

    整体结构 java提供了4中引用类型,在垃圾回收的时候,都有自己的各自特点. 为什么要区分这么多引用呢,其实这和Java的GC有密切关系. 强引用(默认支持模式) 把一个对象赋给一个引用变量,这个引用 ...

  4. 【spring源码分析】IOC容器初始化——查漏补缺(二)

    前言:在[spring源码分析]IOC容器初始化(八)中多次提到了前置处理与后置处理,本篇文章针对此问题进行分析.Spring对前置处理或后置处理主要通过BeanPostProcessor进行实现. ...

  5. Pro*C编程研究一:从.pc到.exe

    [第一步]在Windows下编辑一个.pc程序(Pro*C源程序,作者用到:C:\proctest\exam1.pc),其内容如下: #include <stdio.h> #include ...

  6. php学习之单例模式

    <?php class Dog { private function __construct() { } //静态属性保存单例对象 static private $instance; stati ...

  7. [转][C#].Net反编译利器

    来自:https://www.cnblogs.com/zsuxiong/p/5117465.html 有以下8款非常不错的.Net反编译利器: 1.Reflector Reflector是最为流行的. ...

  8. python核心模块方法

    ********************os模块: os.remove() 删除文件 os.unlink() 删除文件 os.rename() 重命名文件 os.listdir() 列出指定目录下所有 ...

  9. Qt编写安防视频监控系统9-自动隐藏光标

    一.前言 这个效果的灵感来自于大屏电子看板系统,在很多系统中尤其是上了大屏的时候,其实在用户不在操作的时候,是很不希望看到那个鼠标箭头指针的,只有当用户操作的时候才显示出来,这个就需要开个定时器定时计 ...

  10. eNSP V100R002C00B500 Setup模拟CE6800

    本人操作系统:Windows7  64 下载需要的安装包: eNSP V100R002C00B500    官网下载地址:点击这里 CE6800 官网下载地址:点击这里 USG6000V        ...