Quicksort#

https://gifimage.net/wp-content/uploads/2018/04/quick-sort-gif-5.gif

Quick Sort#

Divide the array into two partitions (subarrays)

  • need to pick a pivot and rearrange the elements into two partitions

Conquer Recursively each half

  • call Quick Sort on each partition (i.e. solve 2 smaller problems)

Combine Solutions

  • there is no need to combine the solutions

Partition#

Implementation#

1void quicksort(int *A, int n, int m)              
2{
3    // shuffle the array  
4    std::random_shuffle(A, A + n);
5    
6    // call recursive quicksort  
7    r_quicksort(A, 0, n - 1);
8}
 1void r_quicksort(int *A,int lo, int  hi)                                           
 2{
 3    if (hi <= lo) return;
 4    
 5    int p = partition(A, lo, hi);  
 6    
 7    r_quicksort(A, lo, p - 1);  
 8    
 9    r_quicksort(A, p + 1, hi);
10}
 1int partition (int *A, int lo, int hi)                      
 2{
 3    int i = lo;
 4    int j = hi + 1;  
 5    while (1) {
 6      
 7        // while A[i] < pivot, increase i 
 8        while (A[++i] < A[lo])
 9            if (i == hi) break;
10
11        // while A[i] > pivot, decrease j 
12        while (A[lo] < A[--j])
13            
14            if (j == lo) break;
15          
16            // if i and j cross exit theloop
17            if(i >= j) break;
18            
19            // swap A[i] and A[j]
20            std::swap(A[i], A[j]);
21    }
22    // swap the pivot with A[j]  
23    std::swap(A[lo], A[j]);
24
25    //return pivot's position
26    return j;
27}

Analysis of Quick Sort#

Worst-Case

image
\[\begin{split} c \{ n + (n-1) + (n-2) + (n-3) + ... 1 \} \\ c * \frac{n(n+1)}{2} \\ = \Theta(n^2) \end{split}\]

input sorted, reverse order, equal elements

\[\begin{split}\begin {align} T(n) &= T(n - 1) + T(0) + \Theta(n) \\ &= T(n - 1) + \Theta(1) + \Theta(n) \\ &= T(n - 1) + \Theta(n) \\ &= \dots \\ &= \Theta(n^2) \\ \end {align}\end{split}\]

can shuffle or randomize the array (to avoid the worst-case)

Best-Case

image
  • pivot partitions array evenly (almost never happens)

\[\begin{split} \begin {align} T(n) &= 2T(\frac{n}{2}) + \Theta(n) \\ &= \dots \\ &=\ \Theta(n\ log\ n) \end {align}\end{split}\]

Average-Case

  • analysis is more complex

  • Consider a 9-to-1 proportional split

  • Even a 99-to-1 split yields same running time

  • Faster than merge sort in practice (less data movement)

\[\begin{split}\begin {align} T(n) &= T(\frac{n}{10}) + T(\frac{9n}{10}) + \Theta(n) \\ &= \dots \\ &= \Theta(n\ log\ n) \\ \end {align}\end{split}\]
image

Add all \(cn\) from side of tree with greatest depth (right subtree):

\[\begin{split} = cn * log_{\frac{10}{9}}\ n \\ = \Theta(n\ log\ n) \\ \end{split}\]

Comments on Quick Sort#

Properties
  • it is in-place but not stable

  • benefits substantially from code tuning

Improvements

use insertion sort for small arrays

  • avoid overhead on small instances (~10 elements) median of 3 elements

  • estimate true median by inspecting 3 random elements three-way partitioning

  • create three partitions \( \le pivot\), \(== pivot\), \( \ge pivot\)

Sorting Algorithms#

Best-Case

Average-Case

Worst-Case

Stable

In-place

Selection Sort

Insertion Sort

Merge Sort

Quick Sort

Best-Case

Average-Case

Worst-Case

Stable

In-place

Selection Sort

\(n^2\)

\(n^2\)

\(n^2\)

No

Yes

Insertion Sort

\(n\)

\(n^2\)

\(n^2\)

Yes

Yes

Merge Sort

\(n\ log\ n\)

\(n\ log\ n\)

\(n\ log\ n\)

Yes

No

Quick Sort

\(n\ log\ n\)

\(n\ log\ n\)

\(n^2\)

No

Yes

Empirical Analysis#