Quicksort
Bart Massey
Divide-and-Conquer
Already seen with Mergesort
Idea: Break problem up into smaller subproblems, solve the subproblems, combine the solutions to solve the larger problem; solve small-enough problems directly
Inherently recursive: works when subproblems are always ultimately divisible into base cases, recombinable into solution
Efficient when splitting and combining are efficient, for example O(n) for Mergesort
Quicksort: Divide-and-Conquer for Arrays
Idea: Instead of splitting arbitrarily, split the array so that everything in the first part is smaller than everything in the second part
This allows replacing the merge with just concatenation — but splitting followed by concatenation is identity, so arrays!
Trick is to partition the array evenly into small and large elements in O(n) time
Partitioning: Pick a Pivot and Proceed
- Imagine we knew the median value of the array; we could then place that value at the front of the array (by swapping it with the first element) and proceed using the following partitioning algorithm (Hoare Partitioning, Wikipedia)
ALGORITHM HOARE PARTITION
To partition an array a:
i ← 0
j ← |a|
p ← a[j]
loop
do
i ← i + 1
while a[i] < pdo
j ← j - 1
while a[j] > pif i ≥ j
return ja[i] ↔ a[j]
Using Partition To Sort (quick)
Now we have a linear-time partition algorithm, so we can just use divide-and-conquer recursion to derive Quicksort
ALGORITHM QUICKSORT
quicksort(a):
if |a| ≤ 1
return
m ← partition(a)
quicksort(a[1..m])
quicksort(a[m+1..])
Worst-case Complexity Of Quicksort
It is tempting to apply the Master Theorem here and conclude n lg n
Sadly, the partition algorithm in no way guarantees an even split
Consider a sorted array of integers… Now you are O(n2)
Average-case Complexity Of Quicksort
Strangely, the average case isn't too bad here: on average the pivot of a random array will be near the middle
Playing with the proof (not shown, for good reason) gets you n lg n average-case performance
Pick A Better Pivot
There are better plans than picking the last element as the pivot
Simple: take the median value of the first, last and middle elements
Can move the pivot to the end with a swap
Way fancier options are available
Constant factors better: Wikipedia suggests 2-3x faster than Heapsort (next week) or Mergesort in typical practice