归并排序

归并排序的基本思想是:利用递归和分而治之(Divide and Conquer)的方法将待排序的数组划分成越来越小的局部数组,再对局部数组排序,最后利用递归的方法将已经排序完毕的局部数组整合成越来越大的有序数组。归并排序包括两个步骤:
一、分割(Divide);
二、整合(Conquer):
首先来看一下归并排序中用到的下标:left 指局部数组开头的元素,right 指局部数组末尾+1 的元素,mid 是 left 和 right 相加除以2,对结果向下取整。

归并排序中用到的下标.png

接下来我们通过对数组 {9, 6, 7, 2, 5, 1, 8, 4, 2} 对归并排序进行说明:
归并排序.jpg

一、分割
向下的蓝色箭头代表分割,箭头边的数字表示处理顺序,分割由mergeSort负责,当局部数组只剩下一个元素时,mergeSort不做任何处理直接结束,如果不是,则计算数组的中央位置 mid, 将 left 到 mid (不包含mid)视作前半部分,mid 到 right (不包含right)视作后半部分,再分别套用mergeSort;具体步骤如下所示:
Step 1: left=0, right=9, 因此 mid=4, 调用mergeSort进行分割,将0~4(即9、6、7、2)视作前半部分,;
Step 2: left=0, right=4, 因此 mid=2, 调用mergeSort进行分割,将0~2(即9、6)视作前半部分;
Step 3: left=0, right=2, 因此 mid=1, 调用mergeSort进行分割,将0~1(即9)视作前半部分,此时局部数组只剩一个元素,mergeSort不做任何处理直接结束;
Step 4: left=1, right=2, 将1~2(即6)视作后半部分,此时局部数组只剩一个元素,mergeSort不做任何处理这节结束;
Step 5: 接下来对对 {6} 和 {9} 这这两个局部数组进行合并,因此就有了第二个步骤。
二、整合
向上的橘色箭头代表整合,箭头边的数字表示处理顺序,整合由merge负责。为了方便叙述,在这里将包含 n1 个元素的前半部分已排序数组称为 L,包含 n2 个元素的后半部分有序数组称为 R, 现在我们需要将 L 和 R 中的元素按照升序排列复制到数组 A 中,在这里我们可以利用已排序的性质进行合并,同样我们举个例子进行说明。
合并两个已排序的数组.jpg

Step 5: 调用merge对前半部分数组和后半部分数组进行合并,结果为6、9;
Step 6: left=0, right=4, 因此 mid=2, 调用mergeSort进行分割,将2~4(即7、2)视作后部分;
step 7: left=2, right=4, 因此 mid=3 调用mergeSort进行分割,将2~3(即7)视作前半部分,此时局部数组只剩一个元素,mergeSort不做任何处理这节结束;
Step 8: left=3, right=4, 将3~4(即2)视作后半部分,此时局部数组只剩一个元素,mergeSort不做任何处理这节结束;
Step 9: 接下来调用merge对 {7} 和 {2} 这两个局部数组进行合并,结果为 {2、7};
Step 10: 调用merge对 {6, 9} {2, 7}这两个局部数组进行合并,结果为 {2, 6, 7, 9};
Step ........: 以此类推。
Step 24: 最终得到排序的结果为 {1, 2, 2, 4, 5, 6, 7, 8, 9}。
接下来贴上代码:
<pre>
void merge(int A[], int n, int left, int mid, int right){
int n1 = mid - left;
int n2 = right - mid;
for (int i = 0; i < n1; i++) L[i] = A[left+i];
for (int i = 0; i < n2; i++) R[i] = A[mid + i];
L[n1] = R[n2] = SENTINEL;
int i = 0, j = 0;
for (int k = left; k < right; k++){
cnt++;
if (L[i] <= R[j]){
A[k] = L[i++];
}
else{
A[k] = R[j++];
}
}
}
//归并排序
void mergeSort(int A[], int n, int left, int right){
if (left + 1 < right){
int mid = (left + right) / 2;
mergeSort(A, n, left, mid);
mergeSort(A, n, mid, right);
merge(A, n, left, mid, right);
trace(A, n);
}
}
</pre>
运行结果:
运行结果.png

稳定性:归并排序包含不相邻元素间的比较,但并不会直接交换,在合并两个已排序数组的时候,如果遇到了相同元素,只要保证前半部分数组优先于后半部分数组,相同元素的顺序就不会颠倒,因此归并排序属于稳定的排序算法。
复杂度:在merge处理中,合并算法的复杂度为O(n1+n2),对于本例的输入{9, 6, 7, 2, 5, 1, 8, 4}包含9个元素,若想将其分割成仅包含一个元素的局部数组,需要经历9-5-3-2-1的4次分割,总共分为5层,如果是8个元素,则分为4层。一般来说n个数据大致分为log2(n)层。由于每层执行merge的复杂度为O(n), 因此归并排序的整体复杂度为O(nlogn)。
总结:归并排序算法虽然高效稳定,但是在处理过程中,除了用于保存输入数据的数组之外,还需要临时占用一部分内存空间。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • 数据结构与算法--归并排序 归并排序 归并排序基于一种称为“归并”的简单操作。比如考试可能会分年级排名和班级排名,...
    sunhaiyu阅读 873评论 0 6
  • 归并排序 所谓归并,就是将两个或两个以上的有序表合并成一个新的有序表。如下图所示,有两个已经排好序的有序表A[1]...
    JackChen1024阅读 2,358评论 0 4
  • 序言 上一篇文章我们已经讲完了插入排序,也就是说我的On^2 的算法基本就写完了,当然还有别的On^2 的算法,但...
    再见远洋阅读 1,652评论 0 3
  • 背景 Array.prototype.sort的实现,不同浏览器有不同的算法实现 chrome使用的快排 Fire...
    mengxr阅读 145评论 0 0
  • 为了完成搭建 MySQL 主从数据库的任务,在自己电脑上从头搭建环境。遇到的问题和解决方法在这里做一一记录。 问题...
    囿于昼夜阅读 897评论 0 2