归并排序是利用分治策略来实现的一种排序方式,分治法是先将一个问题划分成多个小问题递归求解,然后在将每个小问题处理的结构整合在一起,这一步称为治,最终解决了这个问题。示意图如下所示:
图中是对数组arr={8,4,5,7,1,3,6,2}排序,先将数组分开,在对分开的数组合并。
代码如下:
package com.ma.sort;
import java.util.Arrays;
public class MergeSort {
static int count = 0;
public static void main(String[] args) {
int[] arr = {8,4,5,7,1,3,6,2};
int[] temp = new int[arr.length];
MergeSort sort = new MergeSort();
sort.mergeSort(arr,0,arr.length-1,temp);
System.out.println(Arrays.toString(arr));
}
private void mergeSort(int[] arr,int left,int right,int[] temp){
int mid = (left + right)/2;
if (left < right){
//向左递归
mergeSort(arr,left,mid,temp);
//向右递归
mergeSort(arr,mid+1,right,temp);
//合并
merge(arr,left,right,mid,temp);
}
}
private void merge(int[] arr,int left,int right,int mid,int[] temp){
count++;
System.out.println("第"+ count+"次合并");
System.out.print("left="+left+";right="+right);
System.out.println();
int i =left;//左边一半的第一个下标
int j = mid+1;//右边一半的第一个下标
int t = 0;//临时数组的指针
while (i <= mid && j<=right){
if (arr[i]<=arr[j]){
temp[t] = arr[i];
i++;
t++;
}else {
temp[t] = arr[j];
j++;
t++;
}
}
//出循环
while (i<=mid){
//右半边都放完了,把左半边的全都方进去
temp[t] = arr[i];
t++;
i++;
}
while (j<=right){
temp[t] = arr[j];
t++;
j++;
}
//复制,此时t已经走到后面了
//复制不是一次复制整个temp数组,而是复制temp数组中有效元素个
t = 0;
int tempLeft = left;
while (tempLeft <= right){
arr[tempLeft] = temp[t];
tempLeft++;
t++;
}
}
}
注意合并代码中复制数组时,并不是每次都是全部复制,而是复制数组中的有效元素。
附上实验结果帮助理解:
第1次合并
left=0;right=1
第2次合并
left=2;right=3
第3次合并
left=0;right=3
第4次合并
left=4;right=5
第5次合并
left=6;right=7
第6次合并
left=4;right=7
第7次合并
left=0;right=7
[1, 2, 3, 4, 5, 6, 7, 8]