package username.sorting; import java.util.Comparator; import java.util.Random; /** * Sort using the legendary Quicksort routine. * * @author Samuel A. Rebelsky * @version 1.1 of May 2006 */ public class Quicksorter implements Sorter { /** * The random number generator used to select the pivot. */ Random rng; public Quicksorter() { this.rng = new Random(); } // Quicksorter public Vector sort(Vector vec, Comparator c) { int len = vec.size(); // Quicksort is traditionally an in-place sort, so we // make an exact copy of the vector and then sort it in // place. Vector copy = new Vector(len); for (int i = 0; i < len; i++) { copy.add(vec.get(i)); } // for // We use a helper routine that takes lb and ub as parameters // to do the real sorting. this.sort(copy, 0, len-1, c); return copy; } // sort(Vector, Comparator) /** * Sort the subvector of elements between lb and ub inclusive. */ void sort(Vector vec, int lb, int ub, Comparator c) { // If the subvector has one element or zero elements, we're // done. if (ub <= lb) return; // Pick a pivot and put it at the front of the subvector. int pivotPos = pickPivotPos(vec, lb, ub); vec.swap(lb, pivotPos); // Rearrange the vector so that small things are at the left and // large things are at the right. T pivot = vec.get(lb); int left = lb; int right = ub; while (left < right) { // Retreat the right cursor until we hit a small value. // Note that we must hit a small value because the value at // lb is small. while (c.compare(pivot, vec.get(right)) < 0) { right--; } // while // Advance the left cursor until we hit a large value or // reach the right cursor. while ((left < right) && (c.compare(pivot, vec.get(left)) >= 0)) { left++; } // while // At this point, right is on a small value and either left // is on a large value or left and right are the same place. // In both cases, left <= right. Hence, we can swap the values at // left and right and get large things on the right and small things // on the left. vec.swap(left, right); } // while // At this point, we know that (1) left = right, (2) everything // to the left of left is small (including the thing at left), and // (3) everything to the right of right is large. We swap the // pivot into this middle position (so that we can be sure that it's // where it belongs), and then sort the two halves. vec.swap(lb, left); this.sort(vec, lb, left-1, c); this.sort(vec, left+1, ub, c); } // sort(Vector, int, int, Comparator) int pickPivotPos(Vector vec, int lb, int ub) { int offset = rng.nextInt(1 + ub - lb); return lb + offset; } // pickPivotPos(Vector, int, int) } // class Quicksorter