Stable variant of counting sort using prefix sums to preserve relative order of equal keys.
Stable counting sort extends counting sort by preserving the relative order of equal elements. This property is required in multi-pass algorithms such as radix sort.
The algorithm uses prefix sums to compute exact output positions for each element.
Problem
Given an array of elements with integer keys in range , produce a sorted array while preserving the relative order of elements with equal keys.
Idea
Count occurrences, convert counts into cumulative positions, then place elements into the correct position from right to left.
Let:
- store the number of elements
- This gives the final position of each key
Algorithm
stable_counting_sort(A, k):
C = [0] * (k + 1)
for x in A:
C[x] += 1
for i in range(1, k + 1):
C[i] += C[i - 1]
B = [0] * len(A)
for i from length(A) - 1 down to 0:
x = A[i]
C[x] -= 1
B[C[x]] = x
return BExample
Let:
Counts:
| value | count |
|---|---|
| 1 | 1 |
| 2 | 2 |
| 3 | 2 |
| 4 | 1 |
| 8 | 1 |
Prefix sums:
| value | position |
|---|---|
| 1 | 1 |
| 2 | 3 |
| 3 | 5 |
| 4 | 6 |
| 8 | 7 |
Final sorted array:
Stability
The reverse traversal ensures that later occurrences of equal keys are placed later in the output. This preserves the original order.
Correctness
Each element is assigned a unique position based on cumulative counts. The mapping from input to output is one-to-one and order preserving for equal keys.
Complexity
| component | cost |
|---|---|
| counting | |
| prefix sum | |
| placement | |
| total |
Space:
When to Use
Use stable counting sort when:
- stable ordering matters
- keys lie in a small integer range
- used as a subroutine in radix sort
- deterministic linear time is required
Implementation (Python)
def stable_counting_sort(a, k):
count = [0] * (k + 1)
for x in a:
count[x] += 1
for i in range(1, k + 1):
count[i] += count[i - 1]
output = [0] * len(a)
for i in range(len(a) - 1, -1, -1):
x = a[i]
count[x] -= 1
output[count[x]] = x
return output