# 归并排序

#### 一.两个有序数组的排顺

``````public void merge(int[] a, int[] b, int[] c){
int i=0,j=0,k=0;
while (i<a.length && j<b.length){
if (a[i]<=b[j]){
c[k++]=a[i++];
} else{
c[k++]=b[j++];
}
}
while (i<a.length){
c[k++]=a[i++];
}
while (j<b.length){
c[k++]=b[j++];
}
``````

我们用一组测试用例来测试上述算法，并加上log使之更加清晰：

``````public class TwoListSort {
public static void main(String args[]){
int[] a = {2,6,11 };        //声明数组
int[] b = {8,9,9,15};
int[] c = new int[7];
merge(a,b,c);
}

public static void merge(int[] a, int[] b, int[] c){
int i=0,j=0,k=0;
while (i<a.length && j<b.length){
if (a[i]<=b[j]){
c[k++]=a[i++];
test(c,i,j,k);
} else{
c[k++]=b[j++];
test(c,i,j,k);
}
}
while (i<a.length){
c[k++]=a[i++];
test(c,i,j,k);
}
while (j<b.length){
c[k++]=b[j++];
test(c,i,j,k);
}
}

public static void test(int[] c, int i, int j, int k){
for(int h = 0; h < c.length ; h++) {
System.out.print( c[h] + "," );
}
System.out.print( "        "+ " i = "+i +", "+" j = "+j +", "+" k = "+k );
System.out.println("");
}
}
``````

log输出为：

``````2,0,0,0,0,0,0,         i = 1,  j = 0,  k = 1
2,6,0,0,0,0,0,         i = 2,  j = 0,  k = 2
2,6,8,0,0,0,0,         i = 2,  j = 1,  k = 3
2,6,8,9,0,0,0,         i = 2,  j = 2,  k = 4
2,6,8,9,9,0,0,         i = 2,  j = 3,  k = 5
2,6,8,9,9,11,0,         i = 3,  j = 3,  k = 6
2,6,8,9,9,11,15,         i = 3,  j = 4,  k = 7
``````

``````初始：i=0，j=0,k=0;
a[0]<b[0]
c[0] = a[0] = 2;
c = 2,0,0,0,0,0,0,         i = 1,  j = 0,  k = 1
a[1]<b[0]
c[1] = a[1] = 6;
c = 2,6,0,0,0,0,0,         i = 2,  j = 0,  k = 2
a[2]>b[0]
c[2] = b[0] = 8;
c = 2,6,8,0,0,0,0,         i = 2,  j = 1,  k = 3
a[2]>b[1]
c[3] = b[1] = 9;
c = 2,6,8,9,0,0,0,         i = 2,  j = 2,  k = 4
a[2]>b[2]
c[4] = b[2] = 9;
c = 2,6,8,9,9,0,0,         i = 2,  j = 3,  k = 5
a[2]<b[3]
c[5] = a[2] = 11;
c = 2,6,8,9,9,11,0,         i = 3,  j = 3,  k = 6

while (j<b.length){
c[k++]=b[j++];
test(c,i,j,k);
}
c[6] = b[3] = 15
c = 2,6,8,9,9,11,15,         i = 3,  j = 4,  k = 7
``````

#### 二.无序数组的排序

现在有一个无序数组需要排序，并且他是完全无序的，不能划分为任何有序数组，这个时候需要怎么排序呢？这个问题可以转换为，上一种情况中，A和B两个子数组也是无序的，那么我们可以继续将A和B两个数组拆分下去，拆成更小的子数组：a1,a2和b1,b2...如此下去，我们一直将子数组拆分到最小元素，即一个子数组只有一个元素（也就是拆分成一个个元素，每个元素视为长度为1的数组），那么这一个个长度为1的数组，就可以视为有序数组了(毕竟他只有一个元素)。
那么此时我们可以两个元素，视为“一.两个有序数组的排顺”情况中的A.B两个数组，然后两两合并，知道合并为最初长度的数组，可以看到，这实际上是一个递归的过程。

``````public class MergeSort {
public static void main(String args[]){
int[] nums = {27, 8, 57, 9, 23, 41, 65, 19, 0, 1, 2 };      //声明数组
mergeSort(nums);
}
//归并排序
public static void mergeSort(int[] arr){
int[] temp =new int[arr.length] ;
internalMergeSort(arr, temp, 0, arr.length-1);
}
private static void internalMergeSort(int[] a, int[] b, int left, int right){
if (left<right){    //当left==right的时，已经不需要再划分了
int middle = (left+right)/2;
internalMergeSort(a, b, left, middle);          //左子数组
internalMergeSort(a, b, middle+1, right);       //右子数组
mergeSortedArray(a, b, left, middle, right);    //合并两个子数组
}
}
// 合并两个有序子序列 arr[left, ..., middle] 和 arr[middle+1, ..., right]。temp是辅助数组。
private static void mergeSortedArray(int arr[], int temp[], int left, int middle, int right){
int i=left;
int j=middle+1;
int k=0;

while ( i<=middle && j<=right){     // 逐个归并
if (arr[i] <=arr[j]){
temp[k++] = arr[i++];
} else{
temp[k++] = arr[j++];
}
}
while (i <=middle){      // 将左边剩余的归并
temp[k++] = arr[i++];
}
while ( j<=right){           // 将右边剩余的归并
temp[k++] = arr[j++];
}
for (i=0; i<k; ++i){         //把数据复制回原数组
arr[left+i] = temp[i];
}
}
}
``````

``````   private static void internalMergeSort(int[] a, int[] b, int left, int right){
//当left==right的时，已经不需要再划分了
if (left<right){
int middle = (left+right)/2;

System.out.println("");
System.out.println(  "(left左 , middle左，right左) = " + " (" + left + "," + middle + "," + right + ") "  );
for(int i = left; i < right +1;  i++) {
System.out.print(a[i] + ",");
}
internalMergeSort(a, b, left, middle);          //左子数组

System.out.println("");

System.out.println(  "(left右 , middle右，right右) = " + " (" + left + "," + (middle+1) + "," + right + ") "  );
for(int i = middle+1; i < right +1;  i++) {
System.out.print(a[i] + ",");
}
internalMergeSort(a, b, middle+1, right);       //右子数组

mergeSortedArray(a, b, left, middle, right);    //合并两个子数组
}
}
``````
`````` private static void mergeSortedArray(int arr[], int temp[], int left, int middle, int right){
System.out.println("");
System.out.println(  "(left合并 , middle合并，right合并) = " + " (" + left + "," + middle + "," + right + ") "  );
System.out.print("排序前：");
for(int h = left; h < right +1; h++) {
System.out.print( arr[h] + ",");
}

int i=left;
int j=middle+1;
int k=0;

while ( i<=middle && j<=right){     // 逐个归并
if (arr[i] <=arr[j]){
temp[k++] = arr[i++];
} else{
temp[k++] = arr[j++];
}
}

while (i <=middle){      // 将左边剩余的归并
temp[k++] = arr[i++];
}

while ( j<=right){           // 将右边剩余的归并
temp[k++] = arr[j++];
}

for (i=0; i<k; ++i){         //把数据复制回原数组
arr[left+i] = temp[i];
}

System.out.println("");
System.out.print("排序后：");
for(int h = left; h < right +1; h++) {
System.out.print( arr[h] + ",");
}
}
``````

``````(left左 , middle左，right左) =  (0,5,10)
27,8,57,9,23,41,65,19,0,1,2,
(left左 , middle左，right左) =  (0,2,5)
27,8,57,9,23,41,
(left左 , middle左，right左) =  (0,1,2)
27,8,57,
(left左 , middle左，right左) =  (0,0,1)
27,8,
(left右 , middle右，right右) =  (0,1,1)
8,
(left合并 , middle合并，right合并) =  (0,0,1)

``````

``````(left右 , middle右，right右) =  (0,2,2)
57,
(left合并 , middle合并，right合并) =  (0,1,2)

``````

``````(left右 , middle右，right右) =  (0,3,5)
9,23,41,
(left左 , middle左，right左) =  (3,4,5)
9,23,41,
(left左 , middle左，right左) =  (3,3,4)
9,23,
(left右 , middle右，right右) =  (3,4,4)
23,
(left合并 , middle合并，right合并) =  (3,3,4)

(left右 , middle右，right右) =  (3,5,5)
41,
(left合并 , middle合并，right合并) =  (3,4,5)

``````
``````(left合并 , middle合并，right合并) =  (0,2,5)

``````

``````(left右 , middle右，right右) =  (0,6,10)
65,19,0,1,2,
(left左 , middle左，right左) =  (6,8,10)
65,19,0,1,2,
(left左 , middle左，right左) =  (6,7,8)
65,19,0,
(left左 , middle左，right左) =  (6,6,7)
65,19,
(left右 , middle右，right右) =  (6,7,7)
19,
(left合并 , middle合并，right合并) =  (6,6,7)

(left右 , middle右，right右) =  (6,8,8)
0,
(left合并 , middle合并，right合并) =  (6,7,8)

(left右 , middle右，right右) =  (6,9,10)
1,2,
(left左 , middle左，right左) =  (9,9,10)
1,2,
(left右 , middle右，right右) =  (9,10,10)
2,
(left合并 , middle合并，right合并) =  (9,9,10)

(left合并 , middle合并，right合并) =  (6,8,10)

``````

``````(left合并 , middle合并，right合并) =  (0,5,10)

``````

• 序言：七十年代末，一起剥皮案震惊了整个滨河市，随后出现的几起案子，更是在滨河造成了极大的恐慌，老刑警刘岩，带你破解...
沈念sama阅读 117,643评论 1 238
• 序言：滨河连续发生了三起死亡事件，死亡现场离奇诡异，居然都是意外死亡，警方通过查阅死者的电脑和手机，发现死者居然都...
沈念sama阅读 51,126评论 1 200
• 文/潘晓璐 我一进店门，熙熙楼的掌柜王于贵愁眉苦脸地迎上来，“玉大人，你说我怎么就摊上这事。” “怎么了？”我有些...
开封第一讲书人阅读 72,773评论 0 167
• 文/不坏的土叔 我叫张陵，是天一观的道长。 经常有香客问我，道长，这世上最难降的妖魔是什么？ 我笑而不...
开封第一讲书人阅读 35,753评论 0 127
• 正文 为了忘掉前任，我火速办了婚礼，结果婚礼上，老公的妹妹穿的比我还像新娘。我一直安慰自己，他们只是感情好，可当我...
茶点故事阅读 42,544评论 1 204
• 文/花漫 我一把揭开白布。 她就那样静静地躺着，像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上，一...
开封第一讲书人阅读 35,328评论 1 124
• 那天，我揣着相机与录音，去河边找鬼。 笑死，一个胖子当着我的面吹牛，可吹牛的内容都是我干的。 我是一名探鬼主播，决...
沈念sama阅读 27,288评论 2 206
• 文/苍兰香墨 我猛地睁开眼，长吁一口气：“原来是场噩梦啊……” “哼！你这毒妇竟也来了？” 一声冷哼从身侧响起，我...
开封第一讲书人阅读 26,427评论 0 119
• 想象着我的养父在大火中拼命挣扎，窒息，最后皮肤化为焦炭。我心中就已经是抑制不住地欢快，这就叫做以其人之道，还治其人...
爱写小说的胖达阅读 25,389评论 5 170
• 序言：老挝万荣一对情侣失踪，失踪者是张志新（化名）和其女友刘颖，没想到半个月后，有当地人在树林里发现了一具尸体，经...
沈念sama阅读 29,446评论 0 177
• 正文 独居荒郊野岭守林人离奇死亡，尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
茶点故事阅读 26,700评论 1 167
• 正文 我和宋清朗相恋三年，在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
茶点故事阅读 27,938评论 1 176
• 白月光回国，霸总把我这个替身辞退。还一脸阴沉的警告我。[不要出现在思思面前， 不然我有一百种方法让你生不如死。]我...
爱写小说的胖达阅读 22,285评论 0 24
• 序言：一个原本活蹦乱跳的男人离奇死亡，死状恐怖，灵堂内的尸体忽然破棺而出，到底是诈尸还是另有隐情，我是刑警宁泽，带...
沈念sama阅读 24,871评论 2 163
• 正文 年R本政府宣布，位于F岛的核电站，受9级特大地震影响，放射性物质发生泄漏。R本人自食恶果不足惜，却给世界环境...
茶点故事阅读 28,716评论 3 172
• 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹，春花似锦、人声如沸。这庄子的主人今日做“春日...
开封第一讲书人阅读 23,692评论 0 4
• 文/苍兰香墨 我抬头看了看天上的太阳。三九已至，却和暖如春，着一层夹袄步出监牢的瞬间，已是汗流浃背。 一阵脚步声响...
开封第一讲书人阅读 23,785评论 0 113
• 我被黑心中介骗来泰国打工， 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留，地道东北人。 一个月前我还...
沈念sama阅读 29,903评论 2 187
• 正文 我出身青楼，却偏偏与公主长得像，于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子，可洞房花烛夜当晚...
茶点故事阅读 30,330评论 2 188

### 推荐阅读更多精彩内容

• 数据结构与算法--归并排序 归并排序 归并排序基于一种称为“归并”的简单操作。比如考试可能会分年级排名和班级排名，...
sunhaiyu阅读 815评论 0 6
• 归并排序 百度上的解释：归并排序：是建立在归并操作上的一种有效的排序算法,该算法是采用分治法（Divide ...
半月迎风阅读 575评论 0 4
• 序言 上一篇文章我们已经讲完了插入排序，也就是说我的On^2 的算法基本就写完了，当然还有别的On^2 的算法，但...
再见远洋阅读 1,579评论 0 3
• 归并排序 所谓归并，就是将两个或两个以上的有序表合并成一个新的有序表。如下图所示，有两个已经排好序的有序表A[1]...
JackChen1024阅读 2,305评论 0 4
• 1.插入排序—直接插入排序(Straight Insertion Sort) 基本思想: 将一个记录插入到已排序好...
依依玖玥阅读 1,122评论 0 2