1 /*************************************************************************
  2  *  Compilation:  javac QuickSort.java
  3  *  Execution:    java QuickSort N
  4  *
  5  *  Generate N random real numbers between 0 and 1 and quicksort them.
  6  *
  7  *  On average, this quicksort algorithm runs in time proportional to
  8  *  N log N, independent of the input distribution. The algorithm
  9  *  guards against the worst-case by randomly shuffling the elements
 10  *  before sorting. In addition, it uses Sedgewick's partitioning
 11  *  method which stops on equal keys. This protects against cases
 12  *  that make many textbook implementations, even randomized ones,
 13  *  go quadratic (e.g., all keys are the same).
 14  *
 15  *************************************************************************/
 16 
 17 public class QuickSort {
 18     private static long comparisons = 0;
 19     private static long exchanges   = 0;
 20 
 21    /***********************************************************************
 22     *  Quicksort code from Sedgewick 7.1, 7.2.
 23     ***********************************************************************/
 24     public static void quicksort(double[] a) {
 25         shuffle(a);                        // to guard against worst-case
 26         quicksort(a, 0, a.length - 1);
 27     }
 28 
 29     // quicksort a[left] to a[right]
 30     public static void quicksort(double[] a, int left, int right) {
 31         if (right <= left) return;
 32         int i = partition(a, left, right);
 33         quicksort(a, left, i-1);
 34         quicksort(a, i+1, right);
 35     }
 36 
 37     // partition a[left] to a[right], assumes left < right
 38     private static int partition(double[] a, int left, int right) {
 39         int i = left - 1;
 40         int j = right;
 41         while (true) {
 42             while (less(a[++i], a[right]))      // find item on left to swap
 43                 ;                               // a[right] acts as sentinel
 44             while (less(a[right], a[--j]))      // find item on right to swap
 45                 if (j == left) break;           // don't go out-of-bounds
 46             if (i >= j) break;                  // check if pointers cross
 47             exch(a, i, j);                      // swap two elements into place
 48         }
 49         exch(a, i, right);                      // swap with partition element
 50         return i;
 51     }
 52 
 53     // is x < y ?
 54     private static boolean less(double x, double y) {
 55         comparisons++;
 56         return (x < y);
 57     }
 58 
 59     // exchange a[i] and a[j]
 60     private static void exch(double[] a, int i, int j) {
 61         exchanges++;
 62         double swap = a[i];
 63         a[i] = a[j];
 64         a[j] = swap;
 65     }
 66 
 67     // shuffle the array a[]
 68     private static void shuffle(double[] a) {
 69         int N = a.length;
 70         for (int i = 0; i < N; i++) {
 71             int r = i + (int) (Math.random() * (N-i));   // between i and N-1
 72             exch(a, i, r);
 73         }
 74     }
 75 
 76 
 77 
 78     // test client
 79     public static void main(String[] args) {
 80         int N = Integer.parseInt(args[0]);
 81 
 82         // generate N random real numbers between 0 and 1
 83         long start = System.currentTimeMillis();
 84         double[] a = new double[N];
 85         for (int i = 0; i < N; i++)
 86             a[i] = Math.random();
 87         long stop = System.currentTimeMillis();
 88         double elapsed = (stop - start) / 1000.0;
 89         System.out.println("Generating input:  " + elapsed + " seconds");
 90 
 91         // sort them
 92         start = System.currentTimeMillis();
 93         quicksort(a);
 94         stop = System.currentTimeMillis();
 95         elapsed = (stop - start) / 1000.0;
 96         System.out.println("Quicksort:   " + elapsed + " seconds");
 97 
 98         // print statistics
 99         System.out.println("Comparisons: " + comparisons);
100         System.out.println("Exchanges:   " + exchanges);
101     }
102 }
103