归并排序(algs4)

来源:互联网 发布:js获取flash对象 编辑:程序博客网 时间:2024/05/10 16:02

 

将两个有序的数组归并成一个更大的有序数组。要将一个数组排序,可以先(递归地)将它分成两半分别排序,然后将结果归并起来。

归并排序是算法中分治思想的典型应用

归并排序所需的时间和NlgN成正比。辅助数组所需的额外空间和N的大小成正比。

归并排序是一种渐进最优的基于比较排序的算法。

 

1.    原地归并

将涉及的所有元素复制到一个辅助数组,再把归并的结果放回原数组。

private static void merge(Comparable[] a,int lo,int mid,int hi){                                       /*将a[lo..mid]和a[mid+1..hi]归并*/int i=lo;int j=mid+1;for(int k=0;k<=hi;k++)                /*将a[lo..hi]复制到aux[lo..hi]*/aux[k]=a[k];for(int k=lo;k<=hi;k++)                 /*归并回到a[lo..hi]*/{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++];}}

               

2.自顶向下的归并排序

归纳证明:如果它能将两个子数组排列,他就能够通过归并两个子数组来将整个数组排序。

private static Comparable[] aux;       /*归并所需的辅助数组*/public static void sort(Comparable[] a){aux=new Comparable[a.length];         /*一次性分配空间*/sort(a,0,a.length-1);}private static void sort(Comparable[] a,int lo,int hi){                                  /*将数组a[lo..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);             /*归并结果*/}
                             

                                                               

                         

3.自底向上的归并排序

先归并微型数组,然后再成对归并得到子数组

private static Comparable[] aux;public static void sort(Comparable[] a){           /*进行lg次两两归并*/int N=a.length;aux=new Comparable[N]; for(int sz=1;sz<N;sz=2*sz)     /*sz子数组大小,初始值为1每次加倍*/ for(int lo=0;lo<N-sz;lo=lo+2*sz)      /*lo子数组索引*/ merge(a,lo,lo+sz-1,Math.min(lo+2*sz-1,N-1));}

                                                

          

4.附录

 

package _2_Sorting;import java.util.Scanner;public class Merge{/** 算法2.4 自顶向下的归并排序(Top-down mergesort) * 要对子数组a[lo..hi]进行排序, * 先将它分为a[lo..mid]和[mid+1..hi]两部分,分别通过递归调用将他们单独排序, * 最后将有序的子数组归并为最终的排序结果。*/private static Comparable[] aux;       /*归并所需的辅助数组*/public static void sort(Comparable[] a){aux=new Comparable[a.length];         /*一次性分配空间*/sort(a,0,a.length-1);}private static void sort(Comparable[] a,int lo,int hi){                                  /*将数组a[lo..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);             /*归并结果*/}private static void merge(Comparable[] a,int lo,int mid,int hi){                                       /*将a[lo..mid]和a[mid+1..hi]归并*/int i=lo;int j=mid+1;for(int k=0;k<=hi;k++)                /*将a[lo..hi]复制到aux[lo..hi]*/aux[k]=a[k];for(int k=lo;k<=hi;k++)                 /*归并回到a[lo..hi]*/{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++];}}private static boolean less(Comparable v,Comparable w){return v.compareTo(w)<0;}private static void exch(Comparable[] a,int i,int j){Comparable t=a[i];a[i]=a[j];a[j]=t;}private static void show(Comparable[] a){for(int i=0;i<a.length;i++)System.out.println(a[i]+" ");System.out.println();}private 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){Scanner sc=new Scanner(System.in);int N;N=sc.nextInt();String[] a=new String[N];sc.nextLine();                         /*读走换行*/System.out.println("请输入"+N+"个字符串:");for(int i=0;i<N;i++)a[i]=sc.nextLine();sort(a);show(a);}}

package _2_Sorting;import java.util.Scanner;/**自底向上的归并排序(Bottom-up mergesort) * 先进行两两归并、再进行四四归并、然后是八八的归并,一直下去。 * 适合用链表组织的数据*/public class MergeBU{private static Comparable[] aux;public static void sort(Comparable[] a){           /*进行lg次两两归并*/int N=a.length;aux=new Comparable[N]; for(int sz=1;sz<N;sz=2*sz)     /*sz子数组大小,初始值为1每次加倍*/ for(int lo=0;lo<N-sz;lo=lo+2*sz)      /*lo子数组索引*/ merge(a,lo,lo+sz-1,Math.min(lo+2*sz-1,N-1));}private static void merge(Comparable[] a,int lo,int mid,int 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[i],aux[j]))a[k]=aux[i++];else a[k]=aux[j++];}private static boolean less(Comparable v,Comparable w){return v.compareTo(w)<0;}private static void exch(Comparable[] a,int i,int j){Comparable t=a[i];a[i]=a[j];a[j]=t;}public static void show(Comparable[] a){for(int i=0;i<a.length;i++)System.out.println(a[i]);System.out.println();}private 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){Scanner sc=new Scanner(System.in);int N;N=sc.nextInt();String[] a=new String[N];sc.nextLine();                         /*读走换行*/System.out.println("请输入"+N+"个字符串:");for(int i=0;i<N;i++)a[i]=sc.nextLine();sort(a);show(a);}}