Randomized quicksort modifies quicksort by choosing the pivot at random. This removes dependence on input order and prevents consistently bad partitions.
The algorithm retains the same structure as quicksort but replaces deterministic pivot selection with a random choice.
Problem
Given an array of length , reorder it such that:
Idea
Instead of always choosing a fixed pivot position, pick a random index between and , then swap it with the last element and use it as the pivot.
This makes every permutation equally likely, so worst case behavior becomes extremely unlikely.
Algorithm
randomized_quicksort(A, lo, hi):
if lo >= hi:
return
p = randomized_partition(A, lo, hi)
randomized_quicksort(A, lo, p - 1)
randomized_quicksort(A, p + 1, hi)randomized_partition(A, lo, hi):
r = random integer in [lo, hi]
swap A[r] and A[hi]
return partition(A, lo, hi)The partition step is the same as standard quicksort.
Example
Let:
Suppose a random pivot index selects value .
Swap with last element:
Partition around :
Then recursively sort left and right parts.
Correctness
Randomization changes only pivot selection. The partition step still ensures that the pivot is placed between smaller and larger elements. The recursive structure remains valid, so correctness follows from standard quicksort.
Complexity
| case | time |
|---|---|
| expected | |
| worst |
The worst case remains possible but occurs with very low probability.
Expected recurrence:
where is random.
Properties
| property | value |
|---|---|
| stable | no |
| in-place | yes |
| randomized | yes |
| expected performance | strong |
Notes
Randomization protects quicksort from adversarial inputs. It is widely used in practice because it is simple and effective.
In many implementations, a pseudo random generator is used, which is sufficient for performance purposes.
Implementation
import random
def randomized_quicksort(a):
def sort(lo, hi):
if lo >= hi:
return
p = partition(lo, hi)
sort(lo, p - 1)
sort(p + 1, hi)
def partition(lo, hi):
r = random.randint(lo, hi)
a[r], a[hi] = a[hi], a[r]
pivot = a[hi]
i = lo
for j in range(lo, hi):
if a[j] <= pivot:
a[i], a[j] = a[j], a[i]
i += 1
a[i], a[hi] = a[hi], a[i]
return i
sort(0, len(a) - 1)
return aimport "math/rand"
func RandomizedQuickSort(a []int) {
var sort func(int, int)
sort = func(lo, hi int) {
if lo >= hi {
return
}
p := randomizedPartition(a, lo, hi)
sort(lo, p-1)
sort(p+1, hi)
}
sort(0, len(a)-1)
}
func randomizedPartition(a []int, lo, hi int) int {
r := lo + rand.Intn(hi-lo+1)
a[r], a[hi] = a[hi], a[r]
pivot := a[hi]
i := lo
for j := lo; j < hi; j++ {
if a[j] <= pivot {
a[i], a[j] = a[j], a[i]
i++
}
}
a[i], a[hi] = a[hi], a[i]
return i
}