Page last updated 4/20/08
Work through an example
12 4 34 17 6 3 9 21 15 10 5 11 25 8 18
An animation site maintained by Jason Harrison at harrison@cs.ubc.ca.
public static void quickSort( int first , int last )
{
if (first < last)
{
int splitPoint;
splitPoint = split(first , last);
// values[first] .. values[splitPoint-1] <= splitVal
// values[splitPoint+1] .. values[last] > splitVal
quickSort(first , splitPoint-1);
quickSort(splitPoint+1 , last);
}
static int split( int first, int last )
{
int splitVal = values[first];
int saveF = first;
boolean onCorrectSide;
first++;
do
{
onCorrectSide = true;
while (onCorrectSide)
if (values[first] > splitVal)
onCorrectSide = false;
else
{
first++;
onCorrectSide = (first <= last);
}
onCorrectSide = (first <= last);
while (onCorrectSide)
if (values[last] <= splitVal)
onCorrectSide = false;
else
{
last--;
onCorrectSide = (first <= last);
}
if (first < last)
{
swap(first, last);
first++;
last--;
}
} while (first <= last);
swap(saveF, last);
return last;
}
Count of comparisons of array elements in the algorithm as a measure of the complexity: Let C(n) be the number of comparisons for the quicksort of list of size n. Again we use recurrence relations and we want to solve for C(n)
Base: C(1) = C(0) = 0
In general: C(n) = n-1 + C(t) + C(n-t-1)
For the average or worst case analysis we want to know t
C(1) = 0
C(2) = 1 + C(1) =1
C(3) = 2 + C(2) = 2+1
C(4) = 3 + C(3) =3+2+1
....
C(n) = n-1 + C(n-1) = (n-1) + (n-2) + ...+3+2+1
= n(n-1)/2
=O(n2)
(similar for number of swaps: worst case O(n2)
So the quicksort can degrade to a selection sort performance, but the data almost has to be arranged to cause the pivot to always be an extreme value.
So C(n,p) = the number of comparisons for n elements with pivot at position p
and C(n,p) = n-1 + C(p-1) + C(n-p)
where t = p-1
To compute C(n) we must average C(n,p) for p=1,2,..,n
C(n) = 1/nΣ C(n,p), for p=1,2...,n
C(n) = 1/n Σ(n-1 + C(p-1) + C(n-p))
C(n) = (n-1) + 2/n (C(0) + C(1) + ... + C(n-1))
A: nC(n) = n2-n + 2C(0) + 2C(1) + ...+ 2C(n-1)
Note C(n-1) = (n-2) + 2/(n-1) (C(0) + ... + C(n-2))
B: (n-1)C(n-1) = n2-n-2(n-1) + 2C(0) + ...+ 2C(n-2)
Subtracting B from A
nC(n) - (n-1)C(n-1) = 2(n-1) + 2C(n-1)
nC(n) = 2(n-1) + (n-1)C(n-1) + 2C(n-1)
nC(n) = 2(n-1) + (n+1)C(n-1)
C(n)/(n+1) = 2(n-1)/n(n+1) + C(n-1)/n
when you have a pattern like C(n) = f(n) + C(n-1), the recurrence relation is solved by summing the f(n) term
C(n)/(n+1) = 0 + 1/3 + 1/3 + 1/4+ 1/5 + 5/21 + 4/14 + 7/36 + ...
This sequence is bounded by the harmonic sequence : x(1/2 + 1/3+ 1/4+ 1/5+ ...) which is O(log n)
C(n)/(n+1) = O(log n)
so
C(n) = O(n log n)