Counting Sort: Mechanism, Complexity Analysis & Interactive Visualizer
Counting Sort
An efficient, non-comparison-based sorting algorithm that runs in linear time. It works by counting the occurrences of each key within a specific range.
How it works
Counting Sort bypasses the O(n log n) comparison-based sorting limit by exploiting key distributions. It works under the assumption that the input values lie within a known, relatively small range from a minimum to a maximum value.
- Find the range of elements by identifying the minimum and maximum values in the input array.
- Create a helper array
countof size equal to this range, initialized to zero. - Scan the input array and count the occurrences of each number, storing the counts in the
countarray. - Calculate the prefix sums of the counts to find the exact starting position of each number in the output.
- Build the sorted output array by scanning the input array in reverse, placing elements in their correct indices, and decrementing their counts to preserve stability.
- Copy the output array back to the original array.
Complexity
Interactive visualization
Pseudocode
procedure countingSort(A): n ← length(A) min, max ← findMinMax(A) range ← max - min + 1 count ← array of size range initialized to 0 output ← array of size n for i from 0 to n - 1: count[A[i] - min] ← count[A[i] - min] + 1 for i from 1 to range - 1: count[i] ← count[i] + count[i - 1] for i from n - 1 down to 0: val ← A[i] pos ← count[val - min] - 1 output[pos] ← val count[val - min] ← count[val - min] - 1 for i from 0 to n - 1: A[i] ← output[i]
JavaScript implementation
function countingSort(arr) { const n = arr.length; if (n <= 1) return arr; let min = arr[0]; let max = arr[0]; for (let i = 1; i < n; i++) { if (arr[i] < min) min = arr[i]; if (arr[i] > max) max = arr[i]; } const range = max - min + 1; const count = new Array(range).fill(0); const output = new Array(n); for (let i = 0; i < n; i++) { count[arr[i] - min]++; } for (let i = 1; i < range; i++) { count[i] += count[i - 1]; } for (let i = n - 1; i >= 0; i--) { const val = arr[i]; const pos = count[val - min] - 1; output[pos] = val; count[val - min]--; } for (let i = 0; i < n; i++) { arr[i] = output[i]; } return arr; }
Pros and cons
Pros
- Extremely fast O(n + k) linear-time execution.
- Stable sorting algorithm by nature.
- Highly effective when sorting integers with tight bounds.
- No comparison logic required.
Cons
- Not an in-place sort, requires O(n + k) auxiliary space.
- Inefficient when the range k is significantly larger than n.
- Can only sort keys that can be mapped to integer indices (e.g. not suitable for floating point numbers).
When to use it
- Tight Key Range: when sorting integer datasets where range $k$ is roughly proportional to $n$ (such as grades, ages, or status flags).
- As a subroutine: commonly used as the stable sorting engine inside Radix Sort.
Related reading
Sleep Sort: Mechanism, Complexity Analysis & Interactive Visualizer
A unique concurrency-based sorting algorithm: spawns a separate thread for each element, sleeping for a duration proportional to the element value before writing it to the output.
By Md. Harun-Or-Roshid
Cube Sort: Mechanism, Complexity Analysis & Interactive Visualizer
A parallel dimension sorting algorithm: organizes elements in a 3D coordinate cube and sorts vectors along the height, width, and depth axes sequentially to achieve sorted order.
By Md. Harun-Or-Roshid
Patience Sort: Mechanism, Complexity Analysis & Interactive Visualizer
A card-game inspired sorting algorithm: distributes elements onto a series of piles such that each pile's top is \(\ge\) the incoming value, then performs a multi-way merge across pile tops.
By Md. Harun-Or-Roshid
Library Sort: Mechanism, Complexity Analysis & Interactive Visualizer
A gapped variation of Insertion Sort: leaves empty slots (gaps) in the array, allowing elements to be inserted in \(O(1)\) shift time on average by avoiding massive shifts.
By Md. Harun-Or-Roshid