What is Counting Sort?¶
Counting Sort is a non-comparison-based sorting algorithm. Its core idea is to count the occurrences of each element and then directly construct the sorted array based on these counts. Unlike comparison-based algorithms like Quick Sort or Merge Sort, Counting Sort does not require comparing element sizes. Instead, it uses a “counting” approach to sort elements. This algorithm is particularly suitable for scenarios where the range of integers is not large, such as student scores (0-100) or ages (0-150).
Basic Idea¶
Let’s use a concrete example to illustrate the steps of Counting Sort. Suppose we want to sort the array [4, 2, 2, 8, 3, 3, 1].
-
Count Element Frequencies:
First, find the maximum value in the array (here, it is 8). Create a count arraycountwith sizemax_val + 1to record the frequency of each element. Traverse the original array to count occurrences:
-count[0] = 0(no 0s)
-count[1] = 1(element 1 appears once)
-count[2] = 2(element 2 appears twice)
-count[3] = 2(element 3 appears twice)
-count[4] = 1(element 4 appears once)
-count[5] = 0(no 5s)
-count[6] = 0(no 6s)
-count[7] = 0(no 7s)
-count[8] = 1(element 8 appears once) -
Construct the Sorted Array:
Based on the frequency counts, insert elements into the result array in order:
- Element 1 (1 occurrence) → Result:[1]
- Element 2 (2 occurrences) → Result:[1, 2, 2]
- Element 3 (2 occurrences) → Result:[1, 2, 2, 3, 3]
- Element 4 (1 occurrence) → Result:[1, 2, 2, 3, 3, 4]
- Element 8 (1 occurrence) → Result:[1, 2, 2, 3, 3, 4, 8]
C++ Code Implementation¶
Here is the complete C++ implementation of Counting Sort:
#include <iostream>
using namespace std;
// Counting Sort function: sorts array arr
void countingSort(int arr[], int n) {
// Step 1: Find the maximum value in the array
int max_val = arr[0];
for (int i = 1; i < n; i++) {
if (arr[i] > max_val) {
max_val = arr[i];
}
}
// Step 2: Create a count array with size max_val + 1, initialized to 0
int count[max_val + 1] = {0};
// Step 3: Count the occurrences of each element
for (int i = 0; i < n; i++) {
count[arr[i]]++;
}
// Step 4: Construct the sorted array
int output[n]; // Result array
int index = 0; // Current index of the result array
for (int i = 0; i <= max_val; i++) {
// Insert element i count[i] times into the result array
while (count[i] > 0) {
output[index] = i;
index++;
count[i]--;
}
}
// Step 5: Copy the sorted result back to the original array
for (int i = 0; i < n; i++) {
arr[i] = output[i];
}
}
// Test function
int main() {
int arr[] = {4, 2, 2, 8, 3, 3, 1};
int n = sizeof(arr) / sizeof(arr[0]);
cout << "Array before sorting: ";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
countingSort(arr, n);
cout << "\nArray after sorting: ";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
Code Explanation¶
- Find Maximum Value: Traverse the array to determine the maximum element, which is used to size the count array.
- Count Frequencies: The
countarray records how many times each element appears (e.g.,count[2] = 2means element 2 appears twice). - Build Result Array: Traverse the count array and insert each element into the result array
outputas many times as it appears. - Copy Back to Original Array: Transfer the sorted result from
outputback to the original arrayarr.
Time and Space Complexity¶
- Time Complexity: O(n + k), where
nis the array length andkis the range of values (max - min). Traversing the array to count takes O(n), and constructing the result takes O(n), resulting in O(n + k) total time. - Space Complexity: O(k), as we need additional arrays
countandoutputwhose sizes depend on the maximum valuek.
Applicable Scenarios and Considerations¶
- Applicable Scenarios:
- Elements are non-negative integers with a small range (e.g., student scores, ages).
-
Requires efficient sorting and does not care about the relative order of equal elements (stable sorting requires additional handling).
-
Handling Negative Numbers: For arrays with negative values, use an offset to convert negatives to non-negatives. For example, for
[-1, 3, -2], add the minimum value (offset = 2) to get[1, 5, 0], sort, then subtract the offset.
By following these steps, Counting Sort achieves linear time complexity and is an efficient algorithm for sorting small-range integers. Beginners only need to understand the core logic of “count frequencies → build result” to quickly master its implementation.