package com.jwetherell.algorithms.sorts;
import java.util.Random;
/**
* Quicksort is a sorting algorithm which, on average, makes O(n*log n) comparisons to sort
* n items. In the worst case, it makes O(n^2) comparisons, though this behavior is
* rare. Quicksort is often faster in practice than other algorithms.
*
* Family: Divide and conquer.
* Space: In-place.
* Stable: False.
*
* Average case = O(n*log n), Worst case = O(n^2), Best case = O(n) [three-way partition and equal keys]
*
* http://en.wikipedia.org/wiki/Quick_sort
*
* @author Justin Wetherell <phishman3579@gmail.com>
*/
public class QuickSort<T extends Comparable<T>> {
private static final Random RAND = new Random();
public static enum PIVOT_TYPE {
FIRST, MIDDLE, RANDOM
}
public static PIVOT_TYPE type = PIVOT_TYPE.RANDOM;
private QuickSort() { }
public static <T extends Comparable<T>> T[] sort(PIVOT_TYPE pivotType, T[] unsorted) {
int pivot = 0;
if (pivotType == PIVOT_TYPE.MIDDLE) {
pivot = unsorted.length/2;
} else if (pivotType == PIVOT_TYPE.RANDOM) {
pivot = getRandom(unsorted.length);
}
sort(pivot, 0, unsorted.length - 1, unsorted);
return unsorted;
}
private static <T extends Comparable<T>> void sort(int index, int start, int finish, T[] unsorted) {
int pivotIndex = start + index;
T pivot = unsorted[pivotIndex];
int s = start;
int f = finish;
while (s <= f) {
while (unsorted[s].compareTo(pivot) < 0)
s++;
while (unsorted[f].compareTo(pivot) > 0)
f--;
if (s <= f) {
swap(s, f, unsorted);
s++;
f--;
}
}
if (start < f) {
pivotIndex = getRandom((f - start) + 1);
sort(pivotIndex, start, f, unsorted);
}
if (s < finish) {
pivotIndex = getRandom((finish - s) + 1);
sort(pivotIndex, s, finish, unsorted);
}
}
private static final int getRandom(int length) {
if (type == PIVOT_TYPE.RANDOM && length > 0)
return RAND.nextInt(length);
if (type == PIVOT_TYPE.FIRST && length > 0)
return 0;
return length / 2;
}
private static <T extends Comparable<T>> void swap(int index1, int index2, T[] unsorted) {
T index2Element = unsorted[index1];
unsorted[index1] = unsorted[index2];
unsorted[index2] = index2Element;
}
}