Quick Sort Algorithm: Implementation, Running Time, and Improvements - Prof. Sugih Jamin, Study notes of Algorithms and Programming

An outline of the quick sort algorithm, including its implementation, running time analysis, and improvements such as tail recursion removal and pivot selection strategies. It covers the partition function, the best, average, and worst-case running times, and the intuition behind the performance of quick sort compared to other sorting algorithms.

Typology: Study notes

Pre 2010

Uploaded on 09/17/2009

koofers-user-0x8
koofers-user-0x8 🇺🇸

9 documents

1 / 18

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Outline
Today:
Quick sort and improvements
Distribution sort
Sugih Jamin ([email protected])
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12

Partial preview of the text

Download Quick Sort Algorithm: Implementation, Running Time, and Improvements - Prof. Sugih Jamin and more Study notes Algorithms and Programming in PDF only on Docsity!

Outline

Today:

  • Quick sort and improvements
  • Distribution sort

Quick Sort

Like mergesort, it is a divide-and-conquer algorithm

Mergesort: easy division, complex combination

mergesort(left half) mergesort(right half) merge(left, right)

Quicksort: complex division, easy combination

partition(left, right) quicksort(left partition) quicksort(right partition)

Partition [Lomuto]

int partition(int a, left, right) { int i, j, pivot; pivot = a[left]; for (i = left, j = i+1; j < right; j++) { / continue to look for elt < pivot / if (a[j] < pivot) { i++; / swap with first >= elt / swap(a[i], a[j]); } } / put pivot in place, swap with last elt < pivot */ swap(a[left], a[i]); return i; }

Running time:

Running Time of Quicksort

Think of it as building a binary tree

Best case:

  • partition: O(N )
  • height of tree: O(log N )
  • total: O(N log N )

Worst case: when array is pre-sorted

  • partition: O(N )
  • height of tree: O(N )
  • total: O(N 2 )

Average case: O(N log N )

Quicksort is In-place, but...

Recursion uses up stack space Worst case needs Θ(N ) stack space

Small list:

  • do insertion sort if array size is below threshold
  • but quicksort works by reducing array size!
  • terminate quick sort when array is below threshold, leave unsorted subarrays in place
  • subarrays are sorted relative to each other
  • do insertion sort on the whole array as last step

Quicksort is not stable

Tail-Recursion Removal

Tail recursion:

  • when the last statement of a recursive function calls itself
  • can be replaced by an itera- tive loop

Examples:

int count(link *list) { if (!list) return 0; return 1+count(list->next); }

void walk(link *list) { if (!list) return; visit(list); walk(list->next); } void reverse_walk(link *list) { if (!list) return; reverse_walk(list->next); visit(list); }

Improved Quicksort

void qsort(int *a, left, right) { qsort_tr(a, left, right); isort(a, right-left); }

void qsort_tr(int a, left, right) { while (right-left > smallsize) { split = partition(a, left, right); if (split < ((left+right) >> 1)) { qsort_tr(a, left, split-1); left = split+1; / right stays / } else { qsort_tr(a, split+1, right); right = split-1; / left stays */ } } return; }

Running Times of Sorting Algorithms

Algorithm Best Average Worst Linear insertion O(n) O(n^2 ) O(n^2 ) Binary insertion O(n log n) O(n^2 ) O(n^2 ) Bubble O(n^2 ) O(n^2 ) O(n^2 ) Quicksort O(n log n) O(n log n) O(n^2 ) Straight selection O(n^2 ) O(n^2 ) O(n^2 ) Heapsort O(n log n) O(n log n) O(n log n) Mergesort O(n log n) O(n log n) O(n log n)

Decision Tree and The Information Theoretic Lower Bound

Is O(n log n) the best we can do? Yes, if we use binary comparison on the key values

N elements in a decision tree result in N! permutations of the elements at the leaves (see Preiss Fig. 15.11). Let h be the height of tree:

2 h^ = N! h = dlog N !e dlog N !e ≥ log 2 N! ≥ log 2 (1 · 2 · 3 ·... · N ) ≥

∑^ N i=

log 2 i

≥ log 2 1 + log 2 2 + log 2 3 +... log 2 N 2 +... + N ≥ N 2 log 2 N 2 = Ω(N log N )

Distribution/Digital Sort

To escape the Information Theoretic Lower bound, instead of comparing keys, use them as data:

  • bucket/counting sort
  • radix sort
  • radix exchange sort

Radix Sort

Useful when key values are large but consist of base/radix (e.g., digits or chars) that each can be sorted using bucket sort Examples:

  • “hello” is a string of 5 characters, radix-
  • “429” is a string of 3 digits, radix-

Algorithm:

  • do bucket sort on the least significant (rightmost) radix
  • then sort the resulting list on the next significant radix
  • algorithm works only if the bucket sort used is stable
  • not in-place

Example: sort CX AX BZ BY AZ BX AY

  • first pass: CX AX BX BY AY BZ AZ
  • second pass: AX AY AZ BX BY BZ CX

Radix Sort

Running time:

  • let d be the string length (assume equal length strings), N : number of strings, and R the radix size
  • algorithm makes d passes over the strings: O(dN )
  • at each pass, the i-th element of the strings are sorted: O(dR)
  • total running time: O(d(R + N )) = O(N ) for d and R small
  • but note that if keys are treated as binary numbers and radix-2 is used, algorithm degenerates into O(N log N ) (each binary number becomes a binary comparison, for 32-bit key, N = 2^32 and d = 32 is d = log N )