Counting Sort Algorithm

Claire Lee
7 min readSep 22, 2022

--

A non in-place sorting algorithm that sorts the elements of an array by counting the frequency of each unique element. An auxiliary array is required to maintain those counts. Then using those counts to compute every element’s position in the final sorted array. Counting sort is an efficient algorithm that runs in O(n + k) time (n is the number of elements in the array; k is the range of values to be sorted). If the range of input array(ie. k) is very large, this algorithm requires a lot of space and becomes inefficient.

counting sort summary card

How Does Counting Sort Algorithm Work?

Counting sort algorithm sorts the elements of an array by counting the number of times each element appears and assign it into an auxiliary array. We can fetch those counts to build up the final sorted output.

Auxiliary array — counts

Map elements in the input array to counts array indices.

auxiliary array — counts

We can retrieve the frequency of an element by counts[element].

Build up the sorted array

1. rearrange array using simple counts

Iterate through the counts array and fill up the elements to the array in order.

rearrange array

The simplified version of counting sort is easy to implement and understand. However, it only works for numbers. Numbers are indistinguishable, so stability is not an issue. If we use this simple way to handle non-numeric elements, the output will be not stable.

A stable sorting algorithm keeps the same order of equal elements/keys in the sorted output as they appear in the given input.

stable vs. unstable sort

For stability sake, we need to use cumulative counts in counting sort.

2. generate a sorted array using cumulative counts

position(1-based), index(0-based), position = index + 1

By calculating the running sum of counts array(counts[i] += counts[i-1]), it indicates the position of the last elements in the sorted output. According to cumulative counts, it shows that the number of elements smaller than or equal to element i for each input element i. For example, counts[8] = 6 represents six elements are smaller or equal to element 8. Therefore, the last element of 8 must be assigned to the sixth position in the sorted output.

cumulative counts

This information helps to place elements in the right location in the sorted output.

assign elements to the sorted array

Now we can determine the position of the last elements from the cumulative counts. To complete the sorting, we iterate the input array in the reversed order and put elements to the current position in the sorted output. Then we decrement the corresponding value in the cumulative counts by 1 which is the position for the equal elements/keys to be placed. Because we scan backward, the order of the equal element/keys will be maintained in the sorted output. It is stable.

Counting sort for negative numbers

We have known that counting sort maps array values to the indices of the counts/auxiliary array. However, negative numbers map to negative indices will not work properly. Therefore, we need an offset to allow to map the negative elements to the counts indices.

offset = 0 - minValue

Offset is calculated by 0 subtract the minimum number to be sorted. Now this minimum number is counted at index 0.

offset

Let’s say, the minimum number to be sorted is -2, so the offset is 2(0–2=2). An element with value of 5 is counted at the index 7(element + offset = 5 + 2).

With above fine tune, we can apply counting sort on negative numbers.

Graphical Explanation

1. Positive array

positive sorting array

Rearrange array using simple counts

  • step1.a: get the maximum value to be sorted in the array
  • step1.b: initialize an auxiliary array to store the frequency of each element. (set all values to 0)
  • step2: count the frequency of each element of the array
  • step3: rearrange the array to a sorted version
simplified counting sort

Generate a sorted array using cumulative counts

  • step1.a: get the maximum value to be sorted in the array
  • step1.b: initialize two auxiliary arrays.(set all values to 0)
    - counts: store the frequency of each element
    - sortedArray: store the final sorted array
  • step2: count the frequency of each element of the array
  • step3: compute the cumulative sum of the count array
counts[i] += counts[i-1]
  • step4: Build up sorted array by iterating backward through the array
    4.1: place the element at the final position
    4.2: decrement the corresponding value in counts by 1
1
2
3
4
5
6
result

2. Array contains negative values

sorting array has negative values

Generate a sorted array using cumulative counts

  • step1.a: get the maximum and minimum value to be sorted in the array
  • step.b: calculate offset
offset = 0 - minValue
  • step1.c: initialize two auxiliary arrays.(set all values to 0)
    - counts: store the frequency of each element
    - sortedArray: store the final sorted array
  • step2: count the frequency of each element of the array
  • step3: compute the cumulative sum of the count array
counts[i] += counts[i-1]
  • step4: Build up sorted array by iterating backward through the array
    4.1: place the element at the final position
    4.2: decrement the corresponding value in counts by 1
1
2
3
4
5
final result

Code Implementation

Complexity

Time: O(n + k)
Space: O(n + k)
n: the total number of elements in the input array
k: the range of elements to be sorted

Pseudocode

  • Positive array
# find the input range
maxValue = max(array)
# initialize auxiliary arrays and set all elements to 0
counts with length of (1+maxValue)
storedArray with length of array
# count the frequency of every elements
for i from 0 to len(array):
element = array[i]
counts[element] += 1
# calculate cumulative counts
for i from 1 to len(counts):
counts[i] += counts[i-1]
# build up the sorted array
for i from len(array) to 0: # iterate backward
# place element to final position
element = array[i]
position = counts[element]
sortedIdx = position -1
sortArray[sortedIdx] = element
# decrement corresponding value by 1
counts[element] -= 1
  • Array contains negative values
# find the input range
maxValue = max(array)
minValue = min(array)
# calculate the offset
offset = 0 - minVlaue
# initialize auxiliary arrays and set all elements to 0
counts with length of (1+maxValue+offset)
storedArray with length of array
# count the frequency of every elements
for i from 0 to len(array):
element = array[i]
counts[element+offset] += 1
# calculate cumulative counts
for i from 1 to len(counts):
counts[i] += counts[i-1]
# build up the sorted array
for i in from len(array) to 0: # iterate backward
# place element to final position
element = array[i]
position = counts[element+offest]
sortedIdx = position -1
sortArray[sortedIdx] = element
# decrement corresponding value by 1
counts[element+offset] -= 1

Golang

  • Positive array
  • Array contains negative values

Python

  • Positive array
  • Array contains negative values

--

--