关键代码实现:
public static void sort(Comparable[] input) { int N = input.length; aux = input.clone();//must be clone(the same as input) // StdOut.println("input:" + input + " aux:" + aux);//for test sort(aux, input, 0, N-1); } //take input from source, sort it and put output in destination //source and destination is the same at the beginning private static void sort(Comparable[] source, Comparable[] destination, int lo, int hi) { if(lo >= hi)//just one entry in array return; int mid = lo + (hi-lo)/2; sort(destination, source, lo, mid);//first get input from destination, sort it and put output in source sort(destination, source, mid+1, hi); merge(source, destination, lo, mid, hi);//merge sorted source to destination } private static void merge(Comparable[] source, Comparable[] destination, int lo, int mid, int hi) { int i = lo; int j = mid + 1; for(int k = lo; k <= hi; k++) { if(i > mid) destination[k] = source[j++]; else if(j > hi) destination[k] = source[i++]; else if(less(source[j], source[i])) destination[k] = source[j++]; else destination[k] = source[i++]; } // StdOut.println("source:" + source + " destination:" + destination); // StdOut.printf("merge(source, destination, %4d, %4d, %4d)", lo, mid, hi); // show(destination);//for test }
测试用例:
package com.qiusongde; import edu.princeton.cs.algs4.In; import edu.princeton.cs.algs4.StdOut; public class MergeAvoidCopy { private static Comparable[] aux; public static void sort(Comparable[] input) { int N = input.length; aux = input.clone();//must be clone(the same as input) // StdOut.println("input:" + input + " aux:" + aux);//for test sort(aux, input, 0, N-1); } //take input from source, sort it and put output in destination //source and destination is the same in start private static void sort(Comparable[] source, Comparable[] destination, int lo, int hi) { if(lo >= hi)//just one entry in array return; int mid = lo + (hi-lo)/2; sort(destination, source, lo, mid);//first get input from destination, sort it and put output in source sort(destination, source, mid+1, hi); merge(source, destination, lo, mid, hi);//merge sorted source to destination } private static void merge(Comparable[] source, Comparable[] destination, int lo, int mid, int hi) { int i = lo; int j = mid + 1; for(int k = lo; k <= hi; k++) { if(i > mid) destination[k] = source[j++]; else if(j > hi) destination[k] = source[i++]; else if(less(source[j], source[i])) destination[k] = source[j++]; else destination[k] = source[i++]; } // StdOut.println("source:" + source + " destination:" + destination); // StdOut.printf("merge(source, destination, %4d, %4d, %4d)", lo, mid, hi); // show(destination);//for test } private static boolean less(Comparable v, Comparable w) { return v.compareTo(w) < 0; } private static void show(Comparable[] a) { //print the array, on a single line. 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) { //Read strings from standard input, sort them, and print. String[] input = In.readStrings(); // show(input);//for test sort(input); assert isSorted(input); // show(input);//for test } }
测试结果:
M E R G E S O R T E X A M P L E input:[Ljava.lang.String;@1b6d3586 aux:[Ljava.lang.String;@4554617c source:[Ljava.lang.String;@1b6d3586 destination:[Ljava.lang.String;@4554617c merge(source, destination, 0, 0, 1)E M R G E S O R T E X A M P L E source:[Ljava.lang.String;@1b6d3586 destination:[Ljava.lang.String;@4554617c merge(source, destination, 2, 2, 3)E M G R E S O R T E X A M P L E source:[Ljava.lang.String;@4554617c destination:[Ljava.lang.String;@1b6d3586 merge(source, destination, 0, 1, 3)E G M R E S O R T E X A M P L E source:[Ljava.lang.String;@1b6d3586 destination:[Ljava.lang.String;@4554617c merge(source, destination, 4, 4, 5)E M G R E S O R T E X A M P L E source:[Ljava.lang.String;@1b6d3586 destination:[Ljava.lang.String;@4554617c merge(source, destination, 6, 6, 7)E M G R E S O R T E X A M P L E source:[Ljava.lang.String;@4554617c destination:[Ljava.lang.String;@1b6d3586 merge(source, destination, 4, 5, 7)E G M R E O R S T E X A M P L E source:[Ljava.lang.String;@1b6d3586 destination:[Ljava.lang.String;@4554617c merge(source, destination, 0, 3, 7)E E G M O R R S T E X A M P L E source:[Ljava.lang.String;@1b6d3586 destination:[Ljava.lang.String;@4554617c merge(source, destination, 8, 8, 9)E E G M O R R S E T X A M P L E source:[Ljava.lang.String;@1b6d3586 destination:[Ljava.lang.String;@4554617c merge(source, destination, 10, 10, 11)E E G M O R R S E T A X M P L E source:[Ljava.lang.String;@4554617c destination:[Ljava.lang.String;@1b6d3586 merge(source, destination, 8, 9, 11)E G M R E O R S A E T X M P L E source:[Ljava.lang.String;@1b6d3586 destination:[Ljava.lang.String;@4554617c merge(source, destination, 12, 12, 13)E E G M O R R S E T A X M P L E source:[Ljava.lang.String;@1b6d3586 destination:[Ljava.lang.String;@4554617c merge(source, destination, 14, 14, 15)E E G M O R R S E T A X M P E L source:[Ljava.lang.String;@4554617c destination:[Ljava.lang.String;@1b6d3586 merge(source, destination, 12, 13, 15)E G M R E O R S A E T X E L M P source:[Ljava.lang.String;@1b6d3586 destination:[Ljava.lang.String;@4554617c merge(source, destination, 8, 11, 15)E E G M O R R S A E E L M P T X source:[Ljava.lang.String;@4554617c destination:[Ljava.lang.String;@1b6d3586 merge(source, destination, 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
性能比较:
For 20000 random Doubles 1000 trials Merge is 3.4s MergeFasterM is 3.1s MergeUseInsert is 3.2s MergeSkipMerge is 3.3s MergeAvoidCopy is 3.0s