废话不多说,直接上代码,注释在代码里面已经写好了,有不明白的可以私信。
public class MergeSort {
public static void main(String[] args) {
//int[]arr = {3,5,2,7,1,0,6,9};
int[]arr = {7,4,9,6};
process(arr, 0, arr.length-1);
for(int i = 0; i < arr.length;i++) {
System.out.println(arr[i]);
}
}
public static void process(int[] arr, int L, int R) { //让arr数组在L到R范围有序(递归实现)
System.out.println("Deal with [" + L + " , " + R + " ]"); //打印递归实现的详细调用
if(L == R) {
return;
}
int mid = L + ((R - L) >> 1); //取数组中间位置
process(arr, L, mid); //左侧L到mid位置有序
process(arr, mid + 1, R); //右侧mid+1到R位置有序
merge(arr, L, mid, R);
}
//合并两个有序数组区间
private static void merge(int[] arr, int L, int M, int R) {
// TODO Auto-generated method stub
int[] help = new int[R - L + 1]; //先开辟一个和原数组等大小数组
int i = 0; //新开辟数组的第一个下标
int p1 = L; //相当于数组左半部分的第一个位置
int p2 = M + 1; //相当于数组右半部分的第一个位置
while(p1 <= M && p2 <= R) { //P1没有超过M,P2没有超过R,则说明都没越界(M:数组左半部分最大下标;R:数组右半部分最大下标)
//如果arr数组P1位置的值小于等于P2位置的值,就把P1位置的值赋给help的i位置,否则将P2位置的值赋值给help的i位置
//注意,++是在赋值后才自增的
help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
}
/*如果是第一次执行merge方法,那么传进来的值应该是递归拆完后的最小的值(0和1位置的值),在第一个while循环中,第一次循环P1<=M和P2<=R两个条件
是必然满足的,而第二次循环的话由于自增,必然有一个条件是不满足的,所以无论是P1<=M还是P2<=M不满足条件,都要对剩下的那个值进行处理,所以下面又写
了两个判断进行处理,此时已分别将L和M+1位置的值按照从小到大的顺序存入了help里面*/
while(p1 <= M) {
help[i++] = arr[p1++];
}
while (p2 <= R) {
help[i++] = arr[p2++];
}
//循环help数组,现在已经有序,把值放到arr数组,实现arr数组的L到M位置有序
for(i = 0; i < help.length; i++) {
arr[L + i] = help[i];
}
}
}
自己debug的时候用小数据量比较容易清晰的看到运行流程,比较容易理解
中间用到了递归,没搞明白递归的可以参考我的另一篇文章递归运行流程简介_小橘是橘子的博客-CSDN博客