归并是一个简单的操作,即将两个有序的数组归并成一个更大的有序数组。人们根据这个操作发明了一种简单的归并算法:归并排序。
思想
要将一个数组排序,可先先将它分成两半分别排序(无限的分直至元素为一个),然后将结果归并起来。
它主要的有点是所需要的时间和NlogN成正比;它的主要缺点也很明显就是需要的额外空间和N成正比。
归并思路
一种是将两个数组归并到第三个数组中去,但是这会涉及到一个很大的问题,当我们需要多次归并时,每一次都要创建一个新数组来存储排序结果。
第二种,原地归并,在原数组中移动元素不需要额外的空间。
基于辅助数组我们设计了一个归并方法merge方法
public static void merge(Comparable[] aux,Comparable[] a, int lo, int mid,int hi){
// Comparable[] aux; 排序辅助类
int i = lo;
int j = mid+1;
for(int k = lo; k <= hi;k++){
aux[k] = a[k];
}
for(int k = lo; k<= hi; k++){
if(i > mid){
a[k] = aux[j++];
}else if(j > hi){
a[k] = aux[i++];
}else if (less(aux[i], aux[j])) {
a[k] = aux[i++];
}else{
a[k] = aux[j++];
}
}
}
该方法先将所有的元素复制到aux[]中,然后再归并到a[]中。再最后一个for循环中,有四个判断条件:右边的当前元素大于左边的当前元素;左边的当前元素大于右边的当前元素;左边用尽(取右边的元素);右边用尽(取左边的元素)。
注意先判断越界的情况即左边用尽(取右边的元素);右边用尽(取左边的元素)
算法实现
public class Merge {
private static Integer[] aux;
public static void main(String[] args) {
// TODO Auto-generated method stub
Integer[] a = new Integer[]{1,4,6,2,0,3,2,7,8,1,9};
sort(a);
SortUtil.show(a);
}
public static void sort(Comparable[] a){
aux = new Integer[a.length];
sort(a,0,a.length-1);
}
public static void sort(Comparable[] a,int lo,int hi){
if (hi <= lo) {
return;
}
int mid = lo + (hi - lo)/2;
sort(a,lo,mid);
sort(a,mid+1,hi);
SortUtil.merge(aux, a, lo, mid, hi);
}
}