Author: Hayden Smith 2021
Why?
What?
General idea:
Generally implemented recursively. Though can be implemented iteratively with a stack.
void quicksort(Item a[], int lo, int hi) {
if (hi <= lo) return;
int i = partition(a, lo, hi);
quicksort(a, lo, i-1);
quicksort(a, i+1, hi);
}
int partition(Item a[], int lo, int hi) {
Item v = a[lo]; // pivot
int i = lo+1, j = hi;
for (;;) {
while (less(a[i],v) && i < j) i++;
while (less(v,a[j]) && j > i) j--;
if (i == j) break;
swap(a,i,j);
}
j = less(a[i],v) ? i : i-1;
swap(a,lo,j);
return j;
}
As you can see, the choice of pivot is very important
Rather than choosing a static or random pivot, try to find a good "intermediate" value by the median-of-three rule. Make sure the 3 elements (high, low, mid) arei nt he right order
void medianOfThree(Item a[], int lo, int hi) {
int mid = (lo+hi)/2;
if (less(a[mid],a[lo])) swap(a, lo, mid);
if (less(a[hi],a[mid])) swap(a, mid, hi);
if (less(a[mid],a[lo])) swap(a, lo, mid);
// now, we have a[lo] < a[mid] < a[hi]
// swap a[mid] to a[lo+1] to use as pivot
swap(a, mid, lo+1);
}
void quicksort(Item a[], int lo, int hi) {
if (hi <= lo) return;
medianOfThree(a, lo, hi);
int i = partition(a, lo+1, hi-1);
quicksort(a, lo, i-1);
quicksort(a, i+1, hi);
}Recursive function calls have high overhead. Quicksorting partitions with sizes < 5 (approx) have very little benefit compared to simple sorts.
Solution: Handle small partitions with insertion sort
void quicksort(Item a[], int lo, int hi) {
if (hi-lo < Threshhold) {
insertionSort(a, lo, hi);
return;
}
medianOfThree(a, lo, hi);
int i = partition(a, lo+1, hi-1);
quicksort(a, lo, i-1);
quicksort(a, i+1, hi);
}