Counting Sort
Overview
Counting sort sorts integers drawn from a known range . It is not a comparison sort, so it evades the lower bound. Instead, it counts occurrences of each value, computes cumulative counts to determine output positions, and places each element directly into its correct sorted position.
Running time is ; space is . Counting sort is stable. It is practical linear time only when .
Algorithm
Given input array A of length and maximum value :
- Allocate a count array
C[0..k], initialise all entries to 0. - For each element in
A, incrementC[v]. - Convert
Cto cumulative counts: for to , setC[i] = C[i] + C[i-1]. NowC[i]is the number of elements . - Allocate output array
B[1..n]. Iterate throughAfrom right to left (to preserve stability): for each , place it atB[C[v]], then decrementC[v].
The right-to-left pass in step 4 is what guarantees stability: when duplicate values exist, the element appearing later in the input is placed later in the output.
Worked Example
Sort A = [2, 5, 3, 0, 2, 3, 0, 3] with .
Step 1: Count occurrences
| 0 | 1 | 2 | 3 | 4 | 5 | |
|---|---|---|---|---|---|---|
C[i] | 2 | 0 | 2 | 3 | 0 | 1 |
Step 2: Cumulative counts
| 0 | 1 | 2 | 3 | 4 | 5 | |
|---|---|---|---|---|---|---|
C[i] | 2 | 2 | 4 | 7 | 7 | 8 |
Interpretation: there are 2 elements , 2 elements , 4 elements , etc. So the value 2 will occupy output positions 3 and 4 (1-indexed: C[2] = 4, then decrement yields 3 for next occurrence).
Step 3: Place elements (right to left)
- :
C[3] = 7→B[7] = 3,C[3] = 6 - :
C[0] = 2→B[2] = 0,C[0] = 1 - :
C[3] = 6→B[6] = 3,C[3] = 5 - :
C[2] = 4→B[4] = 2,C[2] = 3 - :
C[0] = 1→B[1] = 0,C[0] = 0 - :
C[3] = 5→B[5] = 3,C[3] = 4 - :
C[5] = 8→B[8] = 5,C[5] = 7 - :
C[2] = 3→B[3] = 2,C[2] = 2
Output: B = [0, 0, 2, 2, 3, 3, 3, 5]. Notice that the two 0s preserve their original relative order, as do the two 2s and three 3s. The sort is stable.
Complexity Analysis
| Step | Cost |
|---|---|
Initialise C[0..k] | |
| Count occurrences | |
| Cumulative counts | |
| Place elements | |
| Total |
Space: for the output array and count array. Counting sort is not in-place.
When Is It Linear?
If , then . This is the practical regime. If is much larger than (e.g. sorting a handful of 64-bit integers), then counting sort is -dominated and wastes both time and space.
Why It Beats the Lower Bound
The lower bound applies only to comparison-based sorting. Counting sort never compares elements against each other; it inspects the numerical value of each key directly and uses that value as an array index. This is not a valid operation in the comparison model.
Stability
Counting sort is stable because we iterate the input from right to left when placing elements. The last occurrence of a value in the original array is placed at the rightmost available position for that value in the output, preserving relative order amongst equal keys.
Summary
| Property | Value |
|---|---|
| Type | Non-comparison, integer sort |
| Worst-case time | |
| Space | |
| Stable | Yes |
| In-place | No |
| Practical when | |
| Beats | Yes (not comparison-based) |