Counting Sort
S.1: Sorting in Linear Time
There are many algorithms to sort collections of elements into a prefixed order (usually increasing or decreasing) from arrays, trees, heaps, etc. The most efficient sorting algorithms operate in O(n*log n) time. However, if there are size/range restrictions on the elements to be sorted, then sorting algorithms may operate in O(n) time, a linear time-complexity.
S.2: Counting Sort
Counting sort assumes all elements are integers in the range for a finite constant . Essentially, counting sort uses an auxiliary array of size to store the repetition counts of every element in the given range.
Algorithm
- Create an array with size , where stores the number of times appears in the original array. We can do this by initializing to all , and then as we read through the original array , we increment by 1.
- At this point, is a frequency count array across all elements in range. Next, we update as follows - we want to be the sum of all where in the previous iteration of . This way, the new updated is organized so that contains one more than the number of elements to come before it is to be in the array at all.
- Here comes the step where we actually create the sorted array. Initialize an empty array with the same size as original .
- We iterate the following step as we loop through : If is currently the element in question, then we set to be (this is equivalent to inserting into the th position in the new array ). Then, we update by decrementing by 1 so in case a future )
- By the end of this process, is a sorted version of .
Example
Original Array : Determine in that the maximal element of the array is 8, so we restrict the range from 0 to 8. Then create array and fill in frequencies: Create Array : Fill in the first element, 4, into the right position, 2. Then, update 4 count. Fill in the second element, 2, into the right position, 3. Then, update 2 count. Fill in the third element, 1, into the right position, 1. Then, update 1 count. Fill in the fourth element, 8, into the right position, 8. Then, update 8 count. Fill in the fifth element, 2, into the right position, 2. Then, update 2 count. Fill in the sixth element, 5, into the right position, 6. Then, update 5 count. Fill in the seventh element, 7, into the right position, 7. Then, update 7 count. Fill in the seventh element, 4, into the right position, 4. Then, update 4 count. And now is sorted! Step 1 takes , Step 2 takes , Step 3 takes , Step 4 takes , so the overall runtime is since is constant. No matter what the initial array is, the same steps are performed, so the runtime is always , best, worst, and average.
Exercises
Question: List the time-complexities for each of the four steps in the counting sort algorithm. Then, find the overall runtime. Question: In a stable sorting algorithm, when there are multiple instances of the same element, they will appear in the output array in the same order as they appeared in the input array. Is Counting Sort stable? Why or Why not? Answer: Yes, as the algorithm moves left to right, so it places instances of the same element that occur later in the array after previous instances.
Code Example: Java
class CountingSort {
void countSort(int array[], int size) {
int[] output = new int[size + 1];
// Determine range from maximal element in array
int max = array[0];
for (int i = 1; i < size; i++) {
if (array[i] > max)
max = array[i];
}
int[] count = new int[max + 1];
// Initialize frequency count array with all zeros.
for (int i = 0; i < max; ++i) {
count[i] = 0;
}
// Store the the frequency of each element
for (int i = 0; i < size; i++) {
count[array[i]]++;
}
// Store the cummulative frequency count of every element
for (int i = 1; i <= max; i++) {
count[i] += count[i - 1];
}
// Find the index of each element of the original array in count array, and
// place the elements in output array
for (int i = size - 1; i >= 0; i--) {
output[count[array[i]] - 1] = array[i];
count[array[i]]--;
}
// Copy the sorted elements into original array
for (int i = 0; i < size; i++) {
array[i] = output[i];
}
}
// Driver code
public static void main(String args[]) {
int[] data = { 4, 2, 1, 8, 2, 5, 4 };
int size = data.length;
CountingSort cs = new CountingSort();
cs.countSort(data, size);
System.out.println("Sorted Array in Ascending Order: ");
System.out.println(Arrays.toString(data));
}
}
Code Example: Python
def countingSort(array):
size = len(array)
output = [0] * size
count = [0] * 10
for i in range(0, size):
count[array[i]] += 1
for i in range(1, 10):
count[i] += count[i - 1]
i = size - 1
while i >= 0:
output[count[array[i]] - 1] = array[i]
count[array[i]] -= 1
i -= 1
for i in range(0, size):
array[i] = output[i]
data = [4,2,2,8,3,3,1]
countingSort(data)
print(data)