Counting Sort is an integer sorting algorithm that is based on counting the number of occurrences of each distinct element in the input array. The idea is to determine, for each distinct element, the number of elements less than or equal to it. This allows us to place each element directly into its correct position in the sorted output.
Counting Sort is particularly efficient when the range of input values (the difference between the maximum and minimum elements) is not significantly larger than the number of elements to be sorted. It is a non-comparative sorting algorithm, which means that it doesn't rely on comparing the elements directly.
Find the Range of Input: We first find the minimum and maximum elements in the array to determine the range of the data. This helps us decide how large the counting array should be.
Create a Counting Array: We create an auxiliary array (often called the counting array) where the index represents the element's value and the value at that index represents the frequency of that element in the input array.
Count the Frequency of Elements: Iterate over the input array and for each element, increment the value at its corresponding index in the counting array. For example, if the element is 5, we increment the value at index 5 of the counting array.
Cumulative Count: To determine the positions of the elements in the sorted array, we modify the counting array to store the cumulative count. This allows us to place each element at its correct index in the output array.
Place Elements in Sorted Order: Finally, we place each element in its correct position in the output array, using the counting array to determine its position.
Copy to Original Array: After sorting, we copy the elements from the output array back into the original array if necessary.
// Function to perform Counting Sort
void countingSort(int arr[], int n) {
// Step 1: Find the maximum and minimum elements in the array
int maxVal = arr[0], minVal = arr[0];
for (int i = 1; i < n; i++) {
if (arr[i] > maxVal) maxVal = arr[i];
if (arr[i] < minVal) minVal = arr[i];
}
// Step 2: Create a counting array to store frequencies of each value
int range = maxVal - minVal + 1; // range of input values
int count[range] = {0}; // initialize count array to 0
// Step 3: Count the occurrences of each element in the input array
for (int i = 0; i < n; i++) {
count[arr[i] - minVal]++;
}
// Step 4: Modify the count array to store cumulative counts
for (int i = 1; i < range; i++) {
count[i] += count[i - 1];
}
// Step 5: Place the elements in the correct position in the output array
int output[n]; // output array to store the sorted elements
for (int i = n - 1; i >= 0; i--) { // we iterate backwards to maintain stability
output[count[arr[i] - minVal] - 1] = arr[i];
count[arr[i] - minVal]--;
}
// Step 6: Copy the sorted elements back into the original array
for (int i = 0; i < n; i++) {
arr[i] = output[i];
}
}
Let’s walk through an example of how Counting Sort works:
Consider the array:
arr = [4, 2, 2, 8, 3, 3, 1]
The maximum element is 8 and the minimum element is 1. The range of values is from 1 to 8.
We create a counting array of size 8 - 1 + 1 = 8. The counting array represents the frequency of each value in the input array, but since the minimum value is 1, we offset by subtracting 1 from each element when updating the count.
Initially, the count array looks like this:
count = [0, 0, 0, 0, 0, 0, 0, 0]
We count how many times each number appears in the array:
4 appears once2 appears twice8 appears once3 appears twice1 appears onceAfter counting, the count array becomes:
count = [1, 2, 2, 1, 1, 0, 0, 1]
To determine the positions of elements in the sorted output, we modify the count array to store the cumulative count:
count = [1, 3, 5, 6, 7, 7, 7, 8]
Now, the count array indicates that:
12348Now, we use the count array to place the elements in their correct positions in the output array. We iterate over the input array backwards to maintain the stability of the sort (elements with the same value will remain in their original relative order).
1 in the output array at position count[1] - 1 = 0.3 at count[3] - 1 = 5.3 at count[3] - 2 = 4.2 at count[2] - 1 = 2.2 at count[2] - 2 = 1.4 at count[4] - 1 = 6.8 at count[8] - 1 = 7.The output array becomes:
output = [1, 2, 2, 3, 3, 4, 8]
Finally, copy the elements from the output array back into the original array:
arr = [1, 2, 2, 3, 3, 4, 8]
The time complexity of Counting Sort is as follows:
Counting the Frequencies: This step takes O(n) time, where n is the number of elements in the input array.
Cumulative Count: Modifying the count array to store cumulative counts takes O(k) time, where k is the range of the input (the difference between the maximum and minimum values).
Placing Elements in the Output Array: This step also takes O(n) time because we iterate over the input array.
Thus, the overall time complexity of Counting Sort is:
n is the number of elements and k is the range of the input values.The space complexity of Counting Sort is:
n is the number of elements in the input array and k is the range of input values.We need an additional count array of size k and an output array of size n to store the sorted elements.
k) is small relative to the number of elements (n), as the time complexity is linear in terms of n and k.k) is known and relatively small. For large ranges, it can become inefficient and consume too much memory.Open this section to load past papers