11/05/10
19:53:27
1
32
CS61B:
Lecture 31
Wednesday, November 10, 2010
QUICKSORT
=========
Quicksort is a recursive divideandconquer algorithm, like mergesort.
Quicksort is in practice the fastest known comparisonbased sort for arrays,
even though it has a Theta(n^2) worstcase running time.
If properly designed,
however, it virtually always runs in O(n log n) time.
On arrays, this
asymptotic bound hides a constant smaller than mergesort’s, but mergesort is
usually slightly faster for sorting linked lists.
Given an unsorted list I of items, quicksort chooses a "pivot" item v from I,
then puts each item of I into one of two unsorted lists, depending on whether
its key is less or greater than v’s key.
(Items whose keys are equal to v’s
key can go into either list; we’ll discuss this issue later.)
Start with the unsorted list I of n input items.
Choose a pivot item v from I.
Partition I into two unsorted lists I1 and I2.
 I1 contains all items whose keys are smaller than v’s key.
 I2 contains all items whose keys are larger than v’s.
 Items with the same key as v can go into either list.
 The pivot v, however, does not go into either list.
Sort I1 recursively, yielding the sorted list S1.
Sort I2 recursively, yielding the sorted list S2.
Concatenate S1, v, and S2 together, yielding a sorted list S.
The recursion bottoms out at oneitem and zeroitem lists.
(Zeroitem lists
can arise when the pivot is the smallest or largest item in its list.)
How
long does quicksort take?
The answer is made apparent by examining several
possible recursion trees.
In the illustrations below, the pivot v is always
chosen to be the first item in the list.


4  7  1  5  9  3  0
0  1  3  4  5  7  9
v = pivot


/

\
/ 
\
* = empty list
  
/  
1  3  0 4 7  5  9
*
0 1  3  4  5  7  9
I1  I2
 
/

\
v
/

\
v / 
\
  
  
/  
0 1 3
5 7 9
*
1 3  4  5  7  9
I1  I2 I1  I2
 
v
v
v / 
\
/  
0
1
3
4
5
7
9
*
3 4  5  7  9
 
In the example at left, we get lucky, and the pivot
v / 
\
always turns out to be the item having the median key.
/  
Hence, each unsorted list is partitioned into two pieces
*
4 5  7  9
of equal size, and we have a wellbalanced recursion
 
tree.
Just like in mergesort, the tree has O(log n)
v / 
\
levels.
Partitioning a list is a lineartime operation,