以下代码参考菜鸟教程(归并排序 | 菜鸟教程),我修改了它上面的错误。
public class MergeSort {
public static void main(String[] args) {
int[] arr={6,3,9,7,1,15,5,2,4,11};
int left=0;
int right=arr.length-1;
print(arr);
mergeSort(arr,left,right);
}
public static void mergeSort(int[] arr,int left,int right){
if(left>=right){
return;
}
int mid=(right+left)/2;
mergeSort(arr,left,mid);
mergeSort(arr,mid+1,right);
// 对于arr[mid] <= arr[mid+1]的情况,不进行merge
// 对于近乎有序的数组非常有效,但是对于一般情况,有一定的性能损失
if (arr[mid]>arr[mid+1]){
merge(arr,left,mid,right);
}
}
public static void merge(int[] arr,int left,int mid,int right){
int[] tem = Arrays.copyOfRange(arr, left,right+1);//arr中需要合并的子数组tem
int midtem=(tem.length-1)/2;
int l=0,r=midtem+1;//子数组tem左右部分的起始位置索引
for (int k=left;k<=right;k++){
if (l>midtem){//如果子数组tem左半部分元素已经全部处理完毕,而右半部分还有元素
arr[k]=tem[r];
r++;
}else if (r>=tem.length){//如果右半部分元素已经全部处理完毕,而左半部分还有元素
arr[k]=tem[l];
l++;
}else if(tem[l]<tem[r]){// 左半部分所指元素 < 右半部分所指元素
arr[k]=tem[l];
l++;
}else if(tem[l]>=tem[r]){// 左半部分所指元素 >=右半部分所指元素
arr[k]=tem[r];
r++;
}
}
print(arr);
}
private static void print(int[] arr) {
for (int i : arr) {
System.out.print(i+"\t");
}
System.out.println();
}
}
上图可以帮我们理解归并的过程:通过递归将数组层层分组,直到每个组只有一个元素,然后将每个只含一个元素的数组在上一层分组里比较大小并合并成一个两个元素的有序数组,然后层层向上合并直至将整个数组排序合并。可以在merge()方法中打印数组,直观清晰地看到合并的整个过程。
注意:菜鸟教程中的merge方法是错误的,正确的是上面代码中的写法。