归并排序
思想:如果需要排序的数组分为两个部分,左边是有序的,右边也是有序的(都是升序或者都是降序),那么将两个区间合并为有序的只需要o(n)的复杂度就可以完成。那么如果这两个区域不是有序的呢,可以递归的调用归并排序,直到区间的元素只有一个元素,那么这个区间就是有序的,回到上一层调用,左右两个区间已经有序的情况下,把它们合并在一起,那么这一层就有序了。直到回到了第一层,那么整个数组就有序了。
public class MergeSort {
// [l,m] 区间升序, [m+1,r] 区间升序 ,通过 tmp[] 将它们合并仍然有序
private static void merge(int a[],int l,int m,int r,int tmp[]){
int i=l,j=m+1,k=0;
while (i<=m&&j<=r){
if(a[i]<a[j])
tmp[k++]=a[i++];
else
tmp[k++]=a[j++];
}
while (i<=m)
tmp[k++]=a[i++];
while (j<=r)
tmp[k++]=a[j++];
for(i=0;i<k;i++)
a[l+i]=tmp[i];
}
private static void mergeSortInner(int a[],int l,int r,int tmp[]){
if(l<r){
int m=(l+r)/2;
mergeSortInner(a,l,m,tmp);//先递归排序,使得左边升序
mergeSortInner(a,m+1,r,tmp);//递归排序,使得右边升序
merge(a,l,m,r,tmp);//合并两个升序的区间为有序
}
}
//一次性创建临时数组,避免每次合并时新建新的临时数组
private static void mergeSort(int a[],int n){
int tmp[]=new int[n];
mergeSortInner(a,0,n-1,tmp);
}
public static void main(String[]args){
int a[]=new int[100];
SortUtil.randomArray(a);
SortUtil.print(a);
mergeSort(a,100);
SortUtil.print(a);
}
}