自底向上归并排序(Merge Sort)
一、思路
另一种实现归并排序的方法是,先归并微型数组,再成对归并得到的子数组,直到将整个数组归并在一起。
我们先进行1-by-1归并,然后2-by-2归并,4-by-4归并,如此下去。
在最后一次归并中,第二个数组可能比第一个数组要小。
二、代码实现
关键代码:
public static void sort(Comparable[] input) { int N = input.length; aux = new Comparable[N]; for(int sz = 1; sz < N; sz += sz) { for(int lo = 0; lo < N - sz; lo += sz + sz) { merge(input, lo, lo+sz-1, Math.min(N-1, lo+sz+sz-1)); } } }
测试数据:M E R G E S O R T E X A M P L E
输出结果1:
M E R G E S O R T E X A M P L E merge(input, 0, 0, 1)E M R G E S O R T E X A M P L E merge(input, 2, 2, 3)E M G R E S O R T E X A M P L E merge(input, 4, 4, 5)E M G R E S O R T E X A M P L E merge(input, 6, 6, 7)E M G R E S O R T E X A M P L E merge(input, 8, 8, 9)E M G R E S O R E T X A M P L E merge(input, 10, 10, 11)E M G R E S O R E T A X M P L E merge(input, 12, 12, 13)E M G R E S O R E T A X M P L E merge(input, 14, 14, 15)E M G R E S O R E T A X M P E L merge(input, 0, 1, 3)E G M R E S O R E T A X M P E L merge(input, 4, 5, 7)E G M R E O R S E T A X M P E L merge(input, 8, 9, 11)E G M R E O R S A E T X M P E L merge(input, 12, 13, 15)E G M R E O R S A E T X E L M P merge(input, 0, 3, 7)E E G M O R R S A E T X E L M P merge(input, 8, 11, 15)E E G M O R R S A E E L M P T X merge(input, 0, 7, 15)A E E E E G L M M O P R R S T X A E E E E G L M M O P R R S T X
对比自顶向下:
M E R G E S O R T E X A M P L E merge(input, 0, 0, 1)E M R G E S O R T E X A M P L E merge(input, 2, 2, 3)E M G R E S O R T E X A M P L E merge(input, 0, 1, 3)E G M R E S O R T E X A M P L E merge(input, 4, 4, 5)E G M R E S O R T E X A M P L E merge(input, 6, 6, 7)E G M R E S O R T E X A M P L E merge(input, 4, 5, 7)E G M R E O R S T E X A M P L E merge(input, 0, 3, 7)E E G M O R R S T E X A M P L E merge(input, 8, 8, 9)E E G M O R R S E T X A M P L E merge(input, 10, 10, 11)E E G M O R R S E T A X M P L E merge(input, 8, 9, 11)E E G M O R R S A E T X M P L E merge(input, 12, 12, 13)E E G M O R R S A E T X M P L E merge(input, 14, 14, 15)E E G M O R R S A E T X M P E L merge(input, 12, 13, 15)E E G M O R R S A E T X E L M P merge(input, 8, 11, 15)E E G M O R R S A E E L M P T X merge(input, 0, 7, 15)A E E E E G L M M O P R R S T X A E E E E G L M M O P R R S T X
输出结果2:
M E R G E S O R T E X A M
merge(input, 0, 0, 1)E M R G E S O R T E X A M
merge(input, 2, 2, 3)E M G R E S O R T E X A M
merge(input, 4, 4, 5)E M G R E S O R T E X A M
merge(input, 6, 6, 7)E M G R E S O R T E X A M
merge(input, 8, 8, 9)E M G R E S O R E T X A M
merge(input, 10, 10, 11)E M G R E S O R E T A X M
merge(input, 0, 1, 3)E G M R E S O R E T A X M
merge(input, 4, 5, 7)E G M R E O R S E T A X M
merge(input, 8, 9, 11)E G M R E O R S A E T X M
merge(input, 0, 3, 7)E E G M O R R S A E T X M
merge(input, 8, 11, 12)E E G M O R R S A E M T X
merge(input, 0, 7, 12)A E E E G M M O R R S T X
A E E E G M M O R R S T X
对比自顶向下:
M E R G E S O R T E X A M
merge(input, 0, 0, 1)E M R G E S O R T E X A M
merge(input, 2, 2, 3)E M G R E S O R T E X A M
merge(input, 0, 1, 3)E G M R E S O R T E X A M
merge(input, 4, 4, 5)E G M R E S O R T E X A M
merge(input, 4, 5, 6)E G M R E O S R T E X A M
merge(input, 0, 3, 6)E E G M O R S R T E X A M
merge(input, 7, 7, 8)E E G M O R S R T E X A M
merge(input, 7, 8, 9)E E G M O R S E R T X A M
merge(input, 10, 10, 11)E E G M O R S E R T A X M
merge(input, 10, 11, 12)E E G M O R S E R T A M X
merge(input, 7, 9, 12)E E G M O R S A E M R T X
merge(input, 0, 6, 12)A E E E G M M O R R S T X
A E E E G M M O R R S T X
当数组长度为2的幂时,自顶向下和自底向上所用的比较次数和数组访问次数正好相同,只是顺序不同。
否则,两种方法所用的比较次数和数组访问次数有所不同。
三、性能分析
结论:对于长度为N的任意数组,自底向上归并排序需要1/2NlgN至NlgN次比较,最多访问数组6NlgN次。
分析:见P279
四、排序复杂度
没有任何基于比较的算法能够保证使用少于lgN! ~ NlgN次比较将长度为N的数组排序。