关键代码:
public static void sort(Comparable[] a) { StdRandom.shuffle(a);//eliminate dependence on input StdOut.print("After shuffle:");//for test show(a);//for test int largest = largest(a); exch(a, largest, a.length - 1); StdOut.print("After find largest and exchange:");//for test show(a);//for test sort(a, 0, a.length-1); } private static void sort(Comparable[] a, int lo, int hi) { if(hi <= lo) return; int j = partition(a, lo, hi); sort(a, lo, j-1); sort(a, j+1, hi); } private static int partition(Comparable[] a, int lo, int hi) { int i = lo; int j = hi + 1; Comparable v = a[lo]; StdOut.println();//for test StdOut.printf("partition(input, %4d, %4d) ", lo, hi);//for test while(true) { while(less(a[++i], v));//find item larger or equal to v while(less(v, a[--j]));//not need to worry about j will be out of bound StdOut.println("i:" + i + " j:" + j);//for test if(i >= j)//cross break; exch(a, i, j); show(a);//for test } exch(a, lo, j); StdOut.printf("j is %4d ", j);//for test show(a);//for test return j; }
测试用例:
package com.qiusongde; import edu.princeton.cs.algs4.In; import edu.princeton.cs.algs4.StdOut; import edu.princeton.cs.algs4.StdRandom; public class QuickSentinel { public static void sort(Comparable[] a) { StdRandom.shuffle(a);//eliminate dependence on input StdOut.print("After shuffle:");//for test show(a);//for test int largest = largest(a);//find largest item exch(a, largest, a.length - 1);//set sentinel in right bound StdOut.print("After find largest and exchange:");//for test show(a);//for test sort(a, 0, a.length-1); } private static void sort(Comparable[] a, int lo, int hi) { if(hi <= lo) return; int j = partition(a, lo, hi); sort(a, lo, j-1); sort(a, j+1, hi); } private static int partition(Comparable[] a, int lo, int hi) { int i = lo; int j = hi + 1; Comparable v = a[lo]; StdOut.println();//for test StdOut.printf("partition(input, %4d, %4d) ", lo, hi);//for test while(true) { while(less(a[++i], v));//find item larger or equal to v while(less(v, a[--j]));//not need to worry about j will be out of bound StdOut.println("i:" + i + " j:" + j);//for test if(i >= j)//cross break; exch(a, i, j); show(a);//for test } exch(a, lo, j); StdOut.printf("j is %4d ", j);//for test show(a);//for test return j; } private static void exch(Comparable[] a, int i, int j) { Comparable t = a[i]; a[i] = a[j]; a[j] = t; } private static int largest(Comparable[] a) { assert a != null; assert a.length > 1; int largestindex = 0; for(int i = 1; i < a.length; i++) { if(less(a[largestindex], a[i])) largestindex = i; } return largestindex; } 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[] a = In.readStrings(); show(a); sort(a); assert isSorted(a); show(a); } }
输出结果:
红色部分可看到右子数组的最左元素可作为左子数组右边界的哨兵。
K R A T E L E P U I M Q C X O S After shuffle:E S I X E T P K C O R Q L U M A After find largest and exchange:E S I A E T P K C O R Q L U M X partition(input, 0, 15) i:1 j:8 E C I A E T P K S O R Q L U M X i:2 j:4 E C E A I T P K S O R Q L U M X i:4 j:3 j is 3 A C E E I T P K S O R Q L U M X partition(input, 0, 2) i:1 j:0 j is 0 A C E E I T P K S O R Q L U M X partition(input, 1, 2) i:2 j:1 j is 1 A C E E I T P K S O R Q L U M X partition(input, 4, 15) i:5 j:4 j is 4 A C E E I T P K S O R Q L U M X partition(input, 5, 15) i:13 j:14 A C E E I T P K S O R Q L M U X i:14 j:13 j is 13 A C E E I M P K S O R Q L T U X partition(input, 5, 12) i:6 j:12 A C E E I M L K S O R Q P T U X i:8 j:7 j is 7 A C E E I K L M S O R Q P T U X partition(input, 5, 6) i:6 j:5 j is 5 A C E E I K L M S O R Q P T U X partition(input, 8, 12) i:13 j:12 j is 12 A C E E I K L M P O R Q S T U X partition(input, 8, 11) i:10 j:9 j is 9 A C E E I K L M O P R Q S T U X partition(input, 10, 11) i:12 j:11 j is 11 A C E E I K L M O P Q R S T U X partition(input, 14, 15) i:15 j:14 j is 14 A C E E I K L M O P Q R S T U X A C E E I K L M O P Q R S T U X
性能对比:
For 2000 random Doubles 10000 trials
Quick is 2.3s QuickSentinel is 2.3s
没有大区别。