Quicksort variant that partitions into less than, equal to, and greater than pivot.
Three way quicksort extends quicksort by handling duplicate keys efficiently. Instead of partitioning into two parts, it splits the array into three regions:
- elements less than the pivot
- elements equal to the pivot
- elements greater than the pivot
This reduces unnecessary comparisons when many elements are equal.
Problem
Given an array of length , reorder it such that:
Idea
Use a three way partition (also called Dutch National Flag partition). Maintain three regions:
During partitioning, elements are rearranged into these regions in one pass.
Algorithm
three_way_quicksort(A, lo, hi):
if lo >= hi:
return
lt = lo
i = lo
gt = hi
pivot = A[lo]
while i <= gt:
if A[i] < pivot:
swap A[lt], A[i]
lt += 1
i += 1
else if A[i] > pivot:
swap A[i], A[gt]
gt -= 1
else:
i += 1
three_way_quicksort(A, lo, lt - 1)
three_way_quicksort(A, gt + 1, hi)Example
Let:
Choose pivot .
Partition result:
| region | values |
|---|---|
| < 3 | [2, 1] |
| = 3 | [3, 3, 3] |
| > 3 | [5, 5] |
Recursively sort left and right:
Final result:
Correctness
The partition step ensures:
- all elements in the left region are less than the pivot
- all elements in the middle region equal the pivot
- all elements in the right region are greater than the pivot
The pivot region is already in final position. Recursively sorting the left and right regions produces a fully sorted array.
Complexity
| case | time |
|---|---|
| best | (all equal) |
| average | |
| worst |
Three way partition improves performance when duplicates are frequent, often reducing recursion depth.
Space:
| case | space |
|---|---|
| average | |
| worst |
Properties
| property | value |
|---|---|
| stable | no |
| in-place | yes |
| duplicate handling | excellent |
| practical performance | very strong |
Notes
Three way quicksort is especially effective when the input contains many repeated values. Standard quicksort degrades in such cases because it repeatedly partitions equal elements.
This variant avoids that by grouping equal elements in a single step.
Implementation
def three_way_quicksort(a):
def sort(lo, hi):
if lo >= hi:
return
lt = lo
i = lo
gt = hi
pivot = a[lo]
while i <= gt:
if a[i] < pivot:
a[lt], a[i] = a[i], a[lt]
lt += 1
i += 1
elif a[i] > pivot:
a[i], a[gt] = a[gt], a[i]
gt -= 1
else:
i += 1
sort(lo, lt - 1)
sort(gt + 1, hi)
sort(0, len(a) - 1)
return afunc ThreeWayQuickSort(a []int) {
var sort func(int, int)
sort = func(lo, hi int) {
if lo >= hi {
return
}
lt, i, gt := lo, lo, hi
pivot := a[lo]
for i <= gt {
if a[i] < pivot {
a[lt], a[i] = a[i], a[lt]
lt++
i++
} else if a[i] > pivot {
a[i], a[gt] = a[gt], a[i]
gt--
} else {
i++
}
}
sort(lo, lt-1)
sort(gt+1, hi)
}
sort(0, len(a)-1)
}