Overview
Counting Sort is a non-comparison-based sorting algorithm that operates by counting the number of objects that possess distinct key values. It then performs arithmetic to calculate the position of each object in the output sequence. Counting Sort is particularly efficient when the range of input values is not significantly greater than the number of elements to be sorted.Implementation
How It Works
- Find Maximum: Determine the maximum value in the input array to know the range
- Count Occurrences: Create a count array and store the frequency of each element
- Reconstruct: Iterate through the count array and output each value according to its frequency
Counting Sort is a non-comparison sorting algorithm. It doesn’t compare elements against each other, which allows it to break the O(n log n) lower bound of comparison-based sorts.
Complexity Analysis
Time Complexity
- Best Case: O(n + k) where k is the range
- Average Case: O(n + k)
- Worst Case: O(n + k)
- Linear time in all cases!
Space Complexity
- Space: O(k) for count array
- Auxiliary: O(k) where k = max value
- Can be problematic if k is large
Usage Example
Visual Example
Let’s trace through sorting[4, 2, 2, 8, 3, 3, 1]:
Characteristics
Stability
Stability
This implementation is not stable because it doesn’t preserve the original order of equal elements. A stable version would require a modified algorithm that uses cumulative counts.
In-Place
In-Place
No, Counting Sort is not in-place. It requires O(k) additional space for the count array, where k is the range of input values.
Adaptive
Adaptive
No, Counting Sort is not adaptive. It always performs the same operations regardless of input order.
Comparison-Based
Comparison-Based
No, Counting Sort is not comparison-based. This allows it to achieve linear time complexity.
When to Use
Counting Sort is extremely efficient when sorting integers with a small range.
- Small range of integer values (k is small)
- Many duplicate values
- When linear time sorting is required
- As a subroutine in Radix Sort
- Counting frequencies or creating histograms
- Age sorting (range 0-150)
- Grade sorting (range 0-100)
- Range of values is very large (wastes memory)
- Sorting floating-point numbers
- Sorting strings or complex objects
- Range is unknown or unbounded
- Memory is limited and k is large
Performance Insights
Space vs Time Tradeoff
Code Walkthrough
Stable Version
Comparison with Other Sorts
| Algorithm | Best Case | Average Case | Worst Case | Space | Stable | Type |
|---|---|---|---|---|---|---|
| Counting Sort | O(n + k) | O(n + k) | O(n + k) | O(k) | No* | Non-comparison |
| Radix Sort | O(d(n + k)) | O(d(n + k)) | O(d(n + k)) | O(n + k) | Yes | Non-comparison |
| Bucket Sort | O(n + k) | O(n + k) | O(n²) | O(n + k) | Yes* | Distribution |
| Quick Sort | O(n log n) | O(n log n) | O(n²) | O(log n) | No | Comparison |
| Merge Sort | O(n log n) | O(n log n) | O(n log n) | O(n) | Yes | Comparison |
Real-World Applications
Practical Uses of Counting Sort:
- Age Sorting: Sorting people by age (0-150)
- Grade Processing: Sorting exam scores (0-100)
- Character Sorting: Sorting ASCII characters (0-255)
- Histogram Generation: Counting frequencies
- Radix Sort Subroutine: Used in digit-by-digit sorting
- Image Processing: Sorting pixel intensity values (0-255)
- Network Traffic: Sorting packet priorities (0-7)
Limitations
Handling Negative Numbers
To sort arrays with negative numbers, adjust indices:Breaking the O(n log n) Barrier
Why Comparison Sorts Can’t Beat O(n log n):Comparison-based sorting algorithms have a lower bound of Ω(n log n). This is because:
- n! possible permutations exist for n elements
- A decision tree needs log₂(n!) ≈ n log n height
- Each comparison reduces possibilities by at most half