next up previous contents
Next: Heapsort: Introduction Up: Sorting Previous: Mergesort: Introduction   Contents

Quicksort: Introduction [149]

Divide and Conquer: repeatedly cut problem into ``equal'' halves.



\framebox[18cm][c]{unsorted list}



``Partition'' the list into two lists:



\framebox[9cm][c]{unsorted list 1} \framebox[9cm][c]{unsorted list 2}

Invariant: numbers in list 1 <= list 2.



Partition by selecting a ``pivot'' element value.

If the pivot is about the ``median'' then the lists will be same size.

Scan inwards from left using i. Stop if a[i] >= pivot.

Scan inwards from right using j. Stop if a[j] <= pivot.

If i and j have not crossed each other, swap and continue scan.

The scan is O(n).

Repeat the process on the sublists. Get empty lists in O(log n).

Quicksort: O( )



Quicksort: Example [150]

Pick the pivot to be the first element in the list: 6

Pick pivot:
6 1 4 9 0 3 5 2 7 8

Hide pivot:
8 1 4 9 0 3 5 2 7 6
$i$               $j$  

Scan:
8 1 4 9 0 3 5 2 7 6
i             j    

Swap:
2 1 4 9 0 3 5 8 7 6
i             j    

Scan:
2 1 4 9 0 3 5 8 7 6
      i     j      

Swap:
2 1 4 5 0 3 9 8 7 6
      i     j      

Scan:
2 1 4 5 0 3 9 8 7 6
          j i      

Swap pivot:
2 1 4 5 0 3 6 8 7 9
          j i      

Repeat:
2 1 4 5 0 3
8 7 9



Quicksort: Median-of-3 Partitioning [151]

What if list is presorted ascending or descending?

What about a sentinel?

New approach: compare the first, center, last element. Pick median.

Also: sort the 3 elements.

input_type median3( input_type a[], int left, int right )
{
  int center;
  center = (left + right) / 2;
  if (a[left]   > a[center]) swap( &a[left],   &a[center] );
  if (a[left]   > a[right])  swap( &a[left],   &a[right] );
  if (a[center] > a[right])  swap( &a[center], &a[right] );
  
  /* invariant: a[left] <= a[center] <= a[right] */
  
  swap( &a[center], &a[right-1] );  /* why? */
  return( a[right-1] );
}



Quicksort: quick [152]

% gcc -o quick quick.c                                 > tcc quick.c

Data File with Test Case: quick.dat: 10 6 1 4 9 0 3 5 2 7 8

% quick quick.dat
10   55   40 [  0  1  2  3  4  5  6  7  8  9 ]  0  0



Quicksort: quick.dat [153]

% quick quick.dat step
 n move comp    1  2  3  4  5  6  7  8  9 10    i  j
10    0    0 [  6  1  4  9  0  3  5  2  7  8 ]  0  0
10    6    3 [  0  1  4  9  7  3  5  2  6  8 ]  1 10
10    9    7 [  0  1  4  2  7  3  5  9  6  8 ]  1 10
10   12    9 [  0  1  4  2  5  3  7  9  6  8 ]  1 10
10   15   12 [  0  1  4  2  5  3  6  9  7  8 ]  1 10
10   21   15 [  0  1  5  2  3  4  6  9  7  8 ]  1  6
10   24   18 [  0  1  2  5  3  4  6  9  7  8 ]  1  6
10   27   20 [  0  1  2  3  5  4  6  9  7  8 ]  1  6
10   30   23 [  0  1  2  3  5  4  6  9  7  8 ]  1  3
10   33   25 [  0  1  2  3  5  4  6  9  7  8 ]  1  3
10   42   28 [  0  1  2  3  5  4  6  7  8  9 ]  8 10
10   45   30 [  0  1  2  3  5  4  6  7  8  9 ]  8 10
10   46   31 [  0  1  2  3  5  4  6  7  8  9 ]  2  2
10   47   32 [  0  1  2  3  5  4  6  7  8  9 ]  3  3
10   48   33 [  0  1  2  3  5  4  6  7  8  9 ]  4  4
10   49   34 [  0  1  2  3  5  4  6  7  8  9 ]  5  5
10   50   35 [  0  1  2  3  5  5  6  7  8  9 ]  6  6
10   51   36 [  0  1  2  3  4  5  6  7  8  9 ]  6  5
10   52   37 [  0  1  2  3  4  5  6  7  8  9 ]  7  7
10   53   38 [  0  1  2  3  4  5  6  7  8  9 ]  8  8
10   54   39 [  0  1  2  3  4  5  6  7  8  9 ]  9  9
10   55   40 [  0  1  2  3  4  5  6  7  8  9 ] 10 10



Quicksort: quick.c [154]

void q_sort( input_type a[], int left, int right ) {
  int i, j;
  input_type pivot;
  if (left + CUTOFF <= right) {    /* CUTOFF should be 20 but example is 2 */
    pivot = median3( a, left, right );
    i = left; j = right-1;              /* why? */
    for (;;) {
      while (a[++i] < pivot); 
      while (a[--j] > pivot); 
      if (i < j) 
        swap( &a[i], &a[j] );
      else
        break;
    }
    swap( &a[i], &a[right-1] );        /* why? */ 
    q_sort( a, left, i-1 );
    q_sort( a, i+1, right);
  }
}

void quick_sort( input_type a[], int n ) {
  q_sort( a, 1, n);
  insertion_sort( a, n ); /* n<=20: insertion is better, use CUTOFF */
}



Quicksort: Analysis [155]

Let i= length of the first sublist.

T(n)= running time on a list of n elements.

T(1) = 1

T(n)= running time on two sublists + linear time on parititioning.

T(n)=T(i) + T(n-i-1) +cn

Worst-Case: pivot is smallest element and i=0.

T(n)=T(0) + T(n-1) +cn which is approximately T(n-1) + cn

Telescope:

T(n-1) = T(n-2) + c(n-1)

T(n-2) = T(n-3) + c(n-2)

$\cdots$

T(2) = T(1) + c(2)

${\displaystyle T(n) = T(1) + c\sum_{i=2}^n i = O(\hspace{2cm}) }$



Quicksort: Analysis [156]

Best-Case: pivot is in middle and i=n/2.

T(n) = T(n/2) + T(n/2) + cn=2T(n/2)+cn

Divide by n:



$\frac{T(n)}{n} = \frac{T(n/2)}{n/2} + c$



Telescope:



$\frac{T(n/2)}{n/2} = \frac{T(n/4)}{n/4} + c$



$\frac{T(n/4)}{n/4} = \frac{T(n/8)}{n/8} + c$



...



$\frac{T(2)}{2} = \frac{T(1)}{1} + c$



There are log n of the above equations.



$\frac{T(n)}{n} = \frac{T(1)}{1} + c\log n$



$T(n) = cn\log n + n = O(\hspace{2cm})$



Quicksort: Analysis [157]

Average-Case: each i=0..n-1 is equally likely with probability 1/n.

${\displaystyle T(i) = T(n-i-1) = \frac{1}{n} \sum_{j=0}^{n-1} T(j)}$

${\displaystyle T(n) = \frac{2}{n} \sum_{j=0}^{n-1} T(j) + cn}$

${\displaystyle nT(n) = 2 \sum_{j=0}^{n-1} T(j) + cn^2}$

Similarly:

${\displaystyle (n-1)T(n-1) = 2 \sum_{j=0}^{n-2} T(j) + c(n-1)^2}$

Subtract:

nT(n)-(n-1)T(n-1) = 2 T(n-1) + 2cn-c

Rearrange and drop -c:

nT(n) = (n+1)T(n-1) + 2cn

Divide by n(n+1):

$\frac{T(n)}{n+1} = \frac{T(n-1)}{n} + \frac{2c}{n+1}$



Quicksort: Analysis [158]



$\frac{T(n)}{n+1} = \frac{T(n-1)}{n} + \frac{2c}{n+1}$



Telescope:



$\frac{T(n-1)}{n} = \frac{T(n-2)}{n-1} + \frac{2c}{n}$



$\frac{T(n-2)}{n-1} = \frac{T(n-3)}{n-2} + \frac{2c}{n-1}$

...



$\frac{T(2)}{3} = \frac{T(1)}{2} + \frac{2c}{3}$



Summing:

${\displaystyle \frac{T(n)}{n+1} = \frac{T(1)}{2} + 2c \sum_{i=3}^{n+1} \frac{1}{i} = \frac{1}{2} + 2c[\log_e(n+1)+0.577-\frac{3}{2}]}$



${\displaystyle \frac{T(n)}{n+1} = O(\hspace{2cm})}$



T(n) = O( )


next up previous contents
Next: Heapsort: Introduction Up: Sorting Previous: Mergesort: Introduction   Contents
Ted Billard 2001-10-25