都在注释里了:
import java.util.Arrays;
public class MergeSort {
public static void main(String[] args) {
int[] a = {2,1,13,10,5,3,8,8,4,9,4};
mergeSort(a); //非递归就用这句
//recuSort(a,0,a.length-1); //递归就用这句
System.out.println(Arrays.toString(a));
}
public static void mergeSort(int []a) { //非递归,复杂些
int length = a.length;
int len = 1; //len 表示左边len个,右边len个做归并。起始为1,即两两归并
while(len < length) {
for(int i = 0;i + len < length;i = i + (len << 1)) { //对于每个归并单位,从0开始,直到开始归并的下标+归并单位的值超过最大下标
int low = i; //每次归并的开始总是i
int mid = i + len - 1; //一定要在这里计算mid,不能用high和low算,因为个数为奇数时high是截取的
int high = low + (len << 1) - 1; //计算high
if(high > length-1) //如果数组元素个数是奇数,那high最后一次就会超出下标,这时置为最大下标
high = length-1;
merge(a,low,high,mid); //开始归并,以mid为界,将low--high的元素归并为有序
}
len = len << 1; //第一次两两归并,第二次就四四归并,第三次就八八归并,以此类推
}
}
public static void recuSort(int[] a,int low,int high) { //递归的方法,比较简单
if(low >= high)
return;
int mid = low + (high-low)/2;
recuSort(a,low,mid);
recuSort(a,low + 1,high);
merge(a,low,high,mid);
}
public static void merge(int[] a,int low,int high,int mid) { //low-mid是左边,mid+1-high是右边
int[] temp = new int[a.length];
int index = low;
int left = low;
int right = mid+1;
while(left <= mid && right <=high) { //将两边的元素比较,从而有序的逐个加入一个临时数组
if(a[left] < a[right])
temp[index++] = a[left++];
else
temp[index++] = a[right++];
}
while(left <= mid) //上一步是逐个加入,左右两边肯定有一边先到终点,需要将另一边的元素全部加入临时数组
temp[index++] = a[left++];
while(right <= high)
temp[index++] = a[right++];
while(low <= high) //将临时数组的有序元素复制到源数组
a[low] = temp[low++];
}
}