自顶向下(递归)的归并排序和自底向上(循环)的归并排序——java实现

归并排序有两种实现方式,自顶向下和自底向上。前者的思想是分治法,现将数组逐级二分再二分,分到最小的两个元素后,逐级往上归并,故其核心在于归并。后者的思想相反,采用循环的方式将小问题不断的壮大,最后变成整个大问题。

归并需要有一个同等大小的辅助数组aux,现将需要归并的元素copy至辅助数组aux中,然后通过逐一比较aux中的元素,将其放至原数组中的合适位置。

归并排序的时间复杂度为nlogn,需要额外的空间n,排序元素稳定,即使在最坏的情况下归并排序的时间复杂度也是nlogn。

package 排序;
 
 import java.util.Arrays;
 
 import edu.princeton.cs.algs4.In;
 import edu.princeton.cs.algs4.StdOut;
 /**
  * @author evasean www.cnblogs.com/evasean/
  */
 @SuppressWarnings("rawtypes")
 public class Merge归并排序 {
     private static Comparable[] aux;
     private static int num=1;
     public static void merge(Comparable[] a, int lo, int mid, int hi){
         StdOut.println("merge lo="+lo+",mid="+mid+",hi="+hi);
         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[j],aux[i])) a[k] = aux[j++];//右半边当前元素小于左半边当前元素,取右半边元素
             else a[k] = aux[i++];//右半边当前元素大于或等于左半边当前元素,取左半边元素
         }
         StdOut.println("第"+num+"次归并结果:"+Arrays.toString(a));
         num++;
     }
     /**
      * 自顶向下的归并排序
      * @param a
      */
     public static void sort(Comparable[] a){
         aux = new Comparable[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);
         merge(a,lo,mid,hi);
     }
     /**
      * 自底向上的归并排序
      * @param a
      */
     public static void sortBU(Comparable[] a){
         
         int N = a.length;
         aux = new Comparable[N];
         for(int sz = 1; sz < N; sz=2*sz){
             for(int lo = 0; lo < N - sz; lo += 2*sz){
                 merge(a,lo,lo+sz-1,Math.min(lo+2*sz-1, N-1));
             }
         }
     }
 
     @SuppressWarnings("unchecked")
     private static boolean less(Comparable v, Comparable w) {
         return v.compareTo(w) < 0;
     }
 
     private static void show(Comparable[] a) {
         for (int i = 0; i < a.length; i++)
             StdOut.print(a[i] + " ");
         StdOut.println();
     }
 
     public static boolean isSorted(Comparable[] a) {
         for (int i = 1; i < a.length; i++) {
             if (less(a[i], a[i - 1]))
                 return false;
         }
         return true;
     }
 
     public static void main(String[] args) {
         String[] a = new In().readAllStrings();
         StdOut.println(Arrays.toString(a));
         sort(a);
         assert isSorted(a);
         show(a);
     }
 }

相关推荐