MergeSorting.java
package com.zhanglei.mergesorting;
import java.util.Arrays;
public class MergeSorting {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr= new int[] {2,1,4,3,5,6,8,6,7,9,2};
int[] temp=new int[arr.length];
mergeSort(arr,0,arr.length-1,temp);
System.out.println("After mergeSorting:"+Arrays.toString(arr));
}
public static void mergeSort(int[] arr,int left,int right,int[] temp) {
if(left<right) {
int mid= (left+right)/2;
mergeSort(arr,left,mid,temp);
mergeSort(arr,mid+1,right,temp);
merge(arr,left,mid,right,temp);
}
}
public static void merge(int[] arr,int left,int mid,int right,int[] temp) {
int i=left;
int j=mid+1;
int t=0;//temp从索引0开始存储
while(i<=mid&&j<=right) {
if(arr[i]<=arr[j]) {
temp[t]=arr[i];
t++;
i++;
}else {
temp[t]=arr[j];
t++;
j++;
}
}
if(i>mid) {
while(j<=right) {
temp[t]=arr[j];
t++;
j++;
}
}
if(j>right) {
while(i<=mid) {
temp[t]=arr[i];
t++;
i++;
}
}
// for(int e=0;e<arr.length;e++) {//错误的写法
// arr[e]=temp[e];
// }
t=0;
for(int e=left;e<=right;e++) {//temp从0开始,但是arr是从left开始
arr[e]=temp[t];
t++;
}
}
}
输出结果:
After mergeSorting:[1, 2, 2, 3, 4, 5, 6, 6, 7, 8, 9]
备注1:
- 归并排序的原理:将原数组从中间分开为两个子数组,接着对两个子数组也进行相同的操作,直到只剩一个为止,然后再依次将同一层的两个主体(注意每个主体都是有序的)排序为一个有序的主体,比如最后一次排序就是第一次分开的两个子数组各自已经有序了,再将这两个有序的子数组合并为一个有序的大数组。
- 合并的实现方法:比如现在有两个有序的小主体,我们要合并为一个有序的大主体。需要使用到一个temp数组,将两个小主体依次比较放入temp中,当某个小主体提前遍历结束时,将另一个小主体的剩余元素全部放入temp中,最后再将temp中的元素全部复制回原数组的指定区间(因为arr是数组引用,而归并排序用到也是首尾指针,以及中间指针,所以只要将temp中的元素复制到arr的指定指针之间就可以实现对原数组的修改)
- 下面我用一个例子来演示一下:
- 比如我们从ms(a,0,1,t)分支可以看出,当只有两个元素时,由于两个stop(即该子程序终止了)的存在,主程序会进行两个元素的合并(这是终止分离开始合并的合并),是整个归并排序的最小单元!!!
- 合并都是同一级的合并,即从树上看是在同一层(同一层是指分离的时候,而不是合并的时候)
备注2:
- 归并排序速度跟快速排序差不多,代码就此省略