The “Introduction to Algorithm” provides an pseudo-implementation of counting sort.
COUNTING-SORT(A, B, k)
1 for i ← 0 to k
2 do C[i] ← 0
3 for j ← 1 to length[A]
4 do C[A[j]] ← C[A[j]] + 1
5 ► C[i] now contains the number of elements equal to i
6 for i ← 1 to k
7 do C[i] ← C[i] + C[i -1]
8 ► C[i] now contains the number of elements less than or equal to i
9 for j ← length[A] downto 1
10 do B[C[A[j]]] ← A[j]
11 C[A[j]] ← C[A[j]] - 1
It works well, but still there is room for improvement.
Below is another version that makes counting sort a bit more faster:
COUNTING-SORT-2(A, B, k)
1 for i ← 0 to k
2 do C[i] ← 0
3 for j ← 1 to length[A]
4 do C[A[j]] ← C[A[j]] + 1
5 ► C[i] now contains the number of elements equal to i
6 n = 0
7 for i ← 0 to k
8 for j ← 1 to C[i]
9 do B[n] ← i
10 n ← n + 1
Start from line 6 is where the two implementations differentiate.
when no optimization is taken into account.
In COUNTING-SORT line 6 to line 11 takes:
k + len(A) * 2 assignments, and k + len(A) pluses
In COUNTING-SORT-2 line 6 to line 10 takes:
len(A) * 2 assignments, and len(A) pluses
The two implementations both cost
$$\Omega(len(A))$$
but in the latter the constant k is eliminated.
At the end is a short python test that gives a taste of difference in real performance on my 2.8GHz Win7 laptop:
|
|
Sorting with counting_sort_2:
|
|
time elapsed in counting_sort_2: 22.000 ms
While doing the same sort with counting_sort:
|
|
time elapsed in counting_sort: 36.000 ms