[图解算法] 归并排序MergeSort——<递归与分治策略>
#include"iostream.h"
void Merge(int c[],int d[],int l,int m,int r){
int i=l,j=m+,k=l;
while((i<=m)&&(j<=r)){//循环两组中较小者先放入d[]暂存
if(c[i]<=c[j]) d[k++]=c[i++];
else d[k++]=c[j++];
}
if(i>m) for(int q=j;q<=r;q++) d[k++]=c[q];
else for(int q=i;q<=m;q++) d[k++]=c[q];
} void MergePass(int x[],int y[],int s,int n){
int i=;
while(i<=n-*s){
Merge(x,y,i,i+s-,i+*s-);
i=i+*s;
}
if(i+s<n) Merge(x,y,i,i+s-,n-);
else for(int j=i;j<=n-;j++) y[j]=x[j];
} void MergeSort(int a[],int n){
int* b=new int[n];
int s=;
while(s<n){
MergePass(a,b,s,n);
s+=s;
MergePass(b,a,s,n);
s+=s;
}
} void main(){
int a[] = {,,,,,,,,,};
int size = sizeof(a)/sizeof(int);
MergeSort(a,size+);
for(int i=;i<size;++i)
cout<<a[i]<<",";
cout<<endl;
}
注:文末有GIF动图解析。以上代码复制放入VC6可使用。
[图解+例子]
一、建立数组
(共10个随机乱序数)
二、设置拆分规模
MergeSort(int a[],int n)
把数组a[]及其长度n传入,并设置规模s为1(其实就是设置多少个数放一起排序啦,没那么高大上),即从一个和一个元素比较开始,每调用一次MergePass(),s翻倍。
三、拆分数组
MergePass(int x[],int y[],int s,int n)
遍历数组直到i比n-2*s大
(为什么是n-2s不是n?答:留个“尾巴”单独处理,比如四个数四个数合并,总共有10个数,剩下两个需要单独处理)
【对s的解释:规模s为上一次的规模,即构成新组的,如两个组合并,每个组1个元素,产生2个数的新组,此时规模s为1】

第一步1个1个合并成一个含2个元素的有序组s=1;
第二步2个2个合并成一个含4个元素的有序组s=2;
第三步4个4个合并成一个含8个元素的有序组s=4,
此时情况出现特殊,既然是合并成8个,意味着只要符合每8个有序就可以了,所以剩下两个是属于后8个,但是实际上剩余6个空位(见第四步图)
于是有了开头的判断“尾巴”的以下语句:
if (i+s<n) Merge(x,y,i,i+s-1,n-1); //如果多出来的尾巴比s要长(n-i>s)证明上一次规模的排序不足以把“尾巴”全部排有序
else for(int j=i;j<=n-1;j++) y[j]=x[j]; //如果多出来的尾巴比s要短或等于(n-i<=s)证明上一次规模的排序已经排好了尾巴
显然我们剩下两个元素刚好等于上一次规模s=2,所以属于第二种情况,已经排好了尾巴直接把它存入数组。
所以现在是8+8的有序数组,期中后面的8只有两个元素,也就引出了第四步。
第四步8个8个合并成一个含16个元素的有序组s=8,
显然,此时规模s为8,符合判断“尾巴”的第一种情况,尾巴比8长,所以调用merge()处理两组数据(如下图)。
有人可能会问,尾巴不是2吗?
不
尾巴此时为10。
因为规模为8的时候,需要两对8个数,才可以算一组,所以s=8时的尾巴应该是n%16,不是n%8

当然,总的个数就10个,后面红圈只是方便理解添加的。
第五步16个16个合并成一个含32个元素的有序组s=16,
s1=2 s2=4;
s3=8 s4=16;
为了保证数组传回a,s应当成对存在,所以第五步实际并没合并,只是把数组b传回数组a了
不断的拆->结合
递归->合并
分治问题->解决问题
。。。
四、解决子问题
Merge(int c[],int d[],int l,int m,int r)
此函数即为归并中并的操作,也是整个归并里的最基本的函数,用来处理各组的合并。
举个栗子:
a[0:3] : 2 3 19 27与a[4:7] 2 8 8 12合并
a[0]和a[4]比较,2=2放a[0]进暂存数组b,
a[1]和a[4]比较,3>2放a[4]进暂存数组b,
a[2]和a[4]比较,3<8放a[2]进暂存数组b,
。。。一直放完一方,再把剩下的全加入数组b尾部
得到递增数组b[]。
由于较为简单,此处不再深入解析。其实是困了要睡觉了。。。。。。。。写到半夜。。。
[GIF解析](图源网络,不是上面讲解所用数组)

[特例]
有空更新。。。
[总结]
这样通过先递归的分解数列,再合并数列就完成了归并排序!
欢迎一起探讨,本人保留解析著作权。
算法引用自 王晓东. 计算机算法设计与分析[M]. 电子工业出版社, 2012.
[图解算法] 归并排序MergeSort——<递归与分治策略>的更多相关文章
- 递归与分治策略之循环赛日程表Java实现
递归与分治策略之循环赛日程表 一.问题描述 设有n=2^k个运动员要进行网球循环赛.现要设计一个满足以下要求的比赛日程表: (1)每个选手必须与其他n-1个选手各赛一次: (2)每个选手一天只能参赛一 ...
- 递归与分治策略之棋盘覆盖Java实现
递归与分治策略之棋盘覆盖 一.问题描述 二.过程详解 1.棋盘如下图,其中有一特殊方格:16*16 . 2.第一个分割结果:8*8 3.第二次分割结果:4*4 4.第三次分割结果:2*2 5.第四次分 ...
- [图解算法]线性时间选择Linear Select——<递归与分治策略>
#include <ctime> #include <iostream> using namespace std; template <class Type> vo ...
- [图解算法] 二分查找Binary-Search——<递归与分治策略>
#include"iostream.h" int BinarySearch(int a[],int left,int right,const int& x) { if(le ...
- 数据结构和算法(Golang实现)(23)排序算法-归并排序
归并排序 归并排序是一种分治策略的排序算法.它是一种比较特殊的排序算法,通过递归地先使每个子序列有序,再将两个有序的序列进行合并成一个有序的序列. 归并排序首先由著名的现代计算机之父John_von_ ...
- C#数据结构与算法系列(二十三):归并排序算法(MergeSort)
1.介绍 归并排序(MergeSort)是利用归并的思想实现的排序方法,该算法采用经典的分治策略(分治法将问题分(divide)成一些小的问题然后递归求解, 而治(conquer)的阶段则将分的阶段得 ...
- 【从零学习经典算法系列】分治策略实例——高速排序(QuickSort)
在前面的博文(http://blog.csdn.net/jasonding1354/article/details/37736555)中介绍了作为分治策略的经典实例,即归并排序.并给出了递归形式和循环 ...
- 【技术文档】《算法设计与分析导论》R.C.T.Lee等·第4章 分治策略
分治策略有一种“大事化小,小事化了”的境界,它的思想是将原问题分解成两个子问题,两个子问题的性质和原问题相同,因此这两个子问题可以再用分治策略求解,最终将两个子问题的解合并成原问题的解.有时,我们会有 ...
- 小旭讲解 LeetCode 53. Maximum Subarray 动态规划 分治策略
原题 Given an integer array nums, find the contiguous subarray (containing at least one number) which ...
随机推荐
- eniac世界第二台计算机
ENIAC,全称为Electronic Numerical Integrator And Computer,即电子数字积分计算机.ENIAC是世界上第一台通用计算机,也是继ABC(阿塔纳索夫-贝瑞计算 ...
- Jboss6内存修改
1.启动脚本:/home/jboss/jboss-eap-6.2/bin/standalone.sh -Djboss.bind.address.management=192.168.0.62 -Djb ...
- vue2.0中改变了数组值不能实时反映到页面
页面中点击事件checkContent,改变row数组中的row[99]的值,如果注释更改,那么页面是不能实时获取的,如图更改,则可以 具体原理:http://blog.csdn.net/websof ...
- springMVC笔记二
第十四章 springmvc快速入门(注解版本) 1)springmvc快速入门(传统版) 步一:创建springmvc-day02这么一个web应用 步二:导入springioc,springweb ...
- P4754 True Vegetable
题目描述 小A现在有 NN 道题,编号为 1,2,\cdots,N1,2,⋯,N .每道题的起始毒瘤程度为 00 或 11 .在每回合,小A可以将编号连续的 KK 道题的毒瘤程度+1.但小B因为本身比 ...
- 2017 Multi-University Training Contest - Team 4 phone call(树+lca+并查集)
题解: (并查集处理往上跳的时候,一定要先让u,v往上跳到并查集的祖先,不然会wa掉) 代码如下: #include <iostream> #include <algorithm&g ...
- [USACO06NOV]玉米田Corn Fields
题面描述 状压dp. 设\(f[i][sta]\)为第\(i\)层状态为\(sta\)的方案数. 然后每次可以枚举上一层的状态以及本层的状态,然后如果不冲突且满足地图的要求,则转移. 时间复杂度\(O ...
- [洛谷P1430]序列取数
题目大意:给定一个序列$s$,每个人每轮可以从两端(任选一端)取任意个数的整数,不能不取.在两个人都足够聪明的情况下,求先手的最大得分. 题解:设$f_{i,j}$表示剩下$[i,j]$,先手的最大得 ...
- SICAU-OJ: 第k小
第k小 题意: 给出一个长度不超过5000的字符串,然后让你找出第K小的字串(1<=K<=5).重复的串大小相等. 题解: 这里我们知道某些串的前缀是肯定小于等于其本身的. 那么长度为5的 ...
- [05] css优先级
1.优先级计算规则(特殊性) 在css中,有不同的方式编写css,如果想给同一个标签设置样式,选择器的写法有很多种,那么当多个样式都应用于同一个标签,标签优先选择哪个样式呢?按照以下规则: 现有 0, ...