/**
 * Quicksort.java
 * <br>
 * A class to demonstrate quick sorting.
 * <br>
 * Created: Sun Feb 16 15:07:55 2003
 *
 * @author <a href="mailto:shapiro@cse.buffalo.edu">Stuart C. Shapiro</a>
 */

public class Quicksort {

    /**
     * Sorts the integer array a, using quicksort.
     * <p>
     * post: a[min .. max] is sorted.
     *
     * @param a an <code>int</code> array, part of which is to be sorted.
     * @param min the minimum index of the part of a to be sorted.
     * @param max the maximum index of the part of a to be sorted.
     */
    public static void sort(int[] a, int min, int max) {
	if (max-min < 1) {return;}
 	if (max-min == 1) {
 	    if (a[min] > a[max]) {swap(a, min, max);}
 	    return;
 	}
 	// max-min > 1
	// => min < max-1

	int pivot = a[max];
	// a[max] == pivot;

	// gefilter is a filter that lets pass items that are >= pivot
	int gefilter = max-1; // a[gefilter+1 .. max] >= pivot

	// ltfilter is a filter that lets pass items that are < pivot
	int ltfilter = min; // a[min .. ltfilter-1] < pivot

	// ltfilter < gefilter
	while (ltfilter < gefilter) {
	    // Need to filter a[ltfilter .. gefilter]

	    while (a[ltfilter] < pivot) { // Note, a[max] == pivot.
		ltfilter++;
	    }
	    // a[ltfilter] >= pivot

	    while (gefilter >= ltfilter && a[gefilter] >= pivot) {
		gefilter--;
	    }
	    // ltfilter > gefilter or a[gefilter] < pivot

	    if (ltfilter < gefilter) {
		swap(a, ltfilter, gefilter);
		// a[min .. ltfilter] < pivot <= a[gefilter .. max]
	    }
	} // end of while (ltfilter < gefilter)

	/* a[gefilter] < pivot <= a[ltfilter]
	 * So gefilter < ltfilter
	 * and a[min .. gefilter] < pivot <= a[ltfilter .. max]
	 *  a[max] = pivot */
	swap(a, ltfilter, max);
	// a[min .. gefilter] < pivot = a[ltfilter] <= a[ltfilter+1 .. max] */
	sort(a, min, gefilter);
	sort(a, ltfilter+1, max);
    }

    /**
     * Swaps the values of a[i] and a[j].
     * <p>
     * post: a[i]@post == a[j]@pre and a[j]@post == a[i]@pre.
     *
     * @param a an <code>int[]</code> value
     * @param i an <code>int</code> value
     * @param j an <code>int</code> value
     */
    private static void swap(int[] a, int i, int j) {
	int temp = a[i];
	a[i] = a[j];
	a[j] = temp;
    }

    /**
     * Prints an array to System.out, followed by a newline.
     *
     * @param a an <code>int[]</code> to be printed.
     */
    private static void arrayPrintln (int[] a, int min, int max) { 
	System.out.print("\t{" + a[min]);
	for (int j = min+1; j <= max; j++) {System.out.print(", " + a[j]);}
	System.out.println("}");
    }

    /**
     * Tests the sort method.
     *
     */
    private static void test(int[] a) {
	int max = a.length-1;
	System.out.print("Original: ");
	arrayPrintln(a, 0, max);
	sort(a, 0, max);
	System.out.print("Sorted: ");
	arrayPrintln(a, 0, max);
    }

    /**
     * Demonstrates Quicksort.
     *
     * @param args a <code>String[]</code> value
     */
    public static void main (String[] args) {
	test(new int[] {345,75,72,88,2,75,45,756,187,73,724,952,457});
    } // end of main ()
    
    
}// Quicksort
