C++版 归并排序
在原作者基础上加入注释
原作者:https://www.cnblogs.com/agui521/p/6918229.html
归并排序:归并排序(英语:Merge sort,或mergesort),是创建在归并操作上的一种有效的排序算法,效率为O(n log n)。1945年由约翰·冯·诺伊曼首次提出。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。
归并排序的核心思想是将两个有序的数列合并成一个大的有序的序列。通过递归,层层合并,即为归并。
如图,从下到上,每一步都需要将两个已经有序的子数组合并成一个大的有序数组,如下是实现合并的具体代码,请读者细细体会
void merge(int arr[],int l,int mid,int r)
{
int aux[r-l+1];//开辟一个新的数组,将原数组映射进去
for(int m=l;m<=r;m++)
{
aux[m-l]=arr[m];
} int i=l,j=mid+1;//i和j分别指向两个子数组开头部分 for(int k=l;k<=r;k++)
{
//分四种情况判断:
//i>mid 把大于mid的数据并入;j>r 把i-mid的数据并入;
//aux[i-l]<aux[j-l],把小的数据即aux[i-l]并入,同理aux[i-l]>=aux[j-l]
if(i>mid)
{
arr[k]=aux[j-l];
j++;
}
else if(j>r)
{
arr[k]=aux[i-l];
i++;
}
else if(aux[i-l]<aux[j-l])
{
arr[k]=aux[i-l];
i++;
}
else
{
arr[k]=aux[j-l];
j++;
}
}
}
上图代码已经完成了归并中的“并”这一部分,归并归并,有并必有归,如下实现“归”的部分

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

由于上图中的l,r不方便使用者调用,于是我们创建一个方便自己调用的my_merge_sort函数
1 void my_merge_sort(int arr[],int n)
2 {
3 merge_sort(arr,0,n-1);
4 }
以上我们便实现了归并排序中的归和并,归并排序是利用二分法实现的排序算法,时间复杂度为nlogn,是一种比较快速的排序算法。如下是笔者自己写的归并排序的全部代码,

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

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

1 #include <iostream>
2 #include <math.h>
3 using namespace std;
4
5 void merge(int arr[],int l,int mid,int r)
6 {
7 int aux[r-l+1];//开辟一个新的数组,将原数组映射进去
8 for(int m=l;m<=r;m++)
9 {
10 aux[m-l]=arr[m];
11 }
12
13 int i=l,j=mid+1;//i和j分别指向两个子数组开头部分
14
15 for(int k=l;k<=r;k++)
16 {
17 if(i>mid)
18 {
19 arr[k]=aux[j-l];
20 j++;
21 }
22 else if(j>r)
23 {
24 arr[k]=aux[i-l];
25 i++;
26 }
27 else if(aux[i-l]<aux[j-l])
28 {
29 arr[k]=aux[i-l];
30 i++;
31 }
32 else
33 {
34 arr[k]=aux[j-l];
35 j++;
36 }
37 }
38 }
39
40 void mergesort(int arr[],int n)
41 {
42 for(int sz=1;sz<=n;sz+=sz)
43 {
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 {//对arr[i...sz-1]和arr[i+sz.....i+2*sz-1]进行排序
46 merge(arr,i,i+sz-1,min(i+sz+sz-1,n-1)); //min函数防止越界
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++版 归并排序的更多相关文章
- javascript实现非递归--归并排序
另一道面试题是实现归并排序,当然,本人很不喜欢递归法,因为递归一般都是没有迭代法好.所以首选都是用迭代法,但是迭代法确实是难做啊,至底而上的思想不好把握. 这是我的实现代码 /* * * 非递归版归并 ...
- 算法与数据结构(十五) 归并排序(Swift 3.0版)
上篇博客我们主要聊了堆排序的相关内容,本篇博客,我们就来聊一下归并排序的相关内容.归并排序主要用了分治法的思想,在归并排序中,将我们需要排序的数组进行拆分,将其拆分的足够小.当拆分的数组中只有一个元素 ...
- 算法导论(第三版)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 ...
- 归并排序—Java版
一开始做算法的时候,感觉递归算法很绕,所以我就在阅读别人代码的基础上,对代码每一步都添加自己的注解,方便我以后的学习. public class MergeSort { /** * 归并排序 * @p ...
- C#版 - LeetCode 148. Sort List 解题报告(归并排序小结)
leetcode 148. Sort List 提交网址: https://leetcode.com/problems/sort-list/ Total Accepted: 68702 Total ...
- 结合《剑指offer(第二版)》面试题51来谈谈归并排序
一.题目大意 给定一个数组A,对于数组A中的两个数字,如果排在前面的一个数字大于(必须大于,等于不算)后面的数字,则这两个数字组成一个逆序对.要求输出数组A中的逆序对的总数.例如,对于数组{7,5,6 ...
- 算法分析中最常用的几种排序算法(插入排序、希尔排序、冒泡排序、选择排序、快速排序,归并排序)C 语言版
每次开始动手写算法,都是先把插入排序,冒泡排序写一遍,十次有九次是重复的,所以这次下定决心,将所有常规的排序算法写了一遍,以便日后熟悉. 以下代码总用一个main函数和一个自定义的CommonFunc ...
- 数据结构之排序技术:快速排序、归并排序、堆排序(C++版)
快速排序 #include <iostream> using namespace std; void swap(int num[], int i, int j) { int temp = ...
- C++_归并排序(纯C版)
#include <iostream> #include <stdlib.h> using namespace std; int compared(const void *ke ...
随机推荐
- spark学习笔记之面试
spark常见面试 map与flatMap的区别 题:以下代码输出有什么不同 val books=List("Hadoop","Hive","HDFS ...
- laotech老师唠科mac 深入浅出MAC OS X
laotech老师唠科mac 深入浅出MAC OS X http://study.163.com/plan/planLearn.htm?id=1637004#/learn/resVideo?lesso ...
- Mysql备份恢复方案解析
1.全量备份和增量备份 1.1全量备份 就是对现有的数据进行全部备份,之前做的备份均可舍弃,以最新的全备为基点. a.全备所有数据库 Innodb引擎: [root@leader mysql]#mys ...
- HDU 4393 Throw nails(贪心加模拟,追及问题)
题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=115361#problem/D 题意大致是:给出最多50000个人,拥有最初速度 ...
- Spring基础环境搭建所需要的jar包
红色标明的jar包.是spring框架开发的基础jar包. 必要jar包. spring-core-4.1.6.RELEASE.jar 框架核心jar包. spring-beans-4.1.6.REL ...
- vs.net2017在编辑的wpf的xaml文件引用本程序集下的类提示“找不到”
local对应就是当前exe程序下的类,会提示“...命令空间...找不到...” 因为我调整过生成的,于是尝试调回来anyCPU 问题解决. 看了一下vs.net2017的所在目录"C:\ ...
- KVM——以桥接的方式搭建虚拟机网络配置
以桥接的方式搭建虚拟机网络,其优势是可以将网络中的虚拟机看作是与主机同等地位的服务器. 在原本的局域网中有两台主机,一台是win7(IP: 192.168.0.236),一台是CentOS7(IP: ...
- Python: 根据利润计算奖金
简述:企业发放的奖金根据利润提成.利润(I)低于或等于10万元时,奖金可提10%: 利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%: 20万到40 ...
- NIO单一长连接——dubbo通信模型实现
转: NIO单一长连接——dubbo通信模型实现 峡客 1.2 2018.07.15 19:04* 字数 2552 阅读 6001评论 30喜欢 17 前言 前一段时间看了下dubbo,原想将dubb ...
- CISCN 2019 writeup
划水做了两个pwn和两个逆向...... 二进制题目备份 Re easyGO Go语言,输入有Please字样,ida搜索sequence of bytes搜please的hex值找到字符串变量,交叉 ...