线性时间排序——计数排序
计数排序的基本思想:对每一个输入元素x,确定小于x的元素个数。
在计数排序算法的代码中,假设输入是一个数组A[1..n],A.length=n。此外,还需要两个数组:B[1..n]存放排序的输出,C[0..k]提供临时存储空间。
伪代码如下:
COUNTING-SORT(A, B, k)
1 let C[0..k] be a new array 2 for i=0 to k 3 C[i] = 0 4 for j=1 to A.length 5 C[A[j]]=C[A[j]]+1 6 //C[i] now contains the number of elements equal to i. 7 for i=1 to k 8 C[i]=C[i]+C[i-1] 9 //C[i] now contains the number of elements less than or equal to i. 10 for j=A.length downto 1 11 B[C[A[j]]=A[j] 12 C[A[j]=C[A[j]-1
下图1为计数排序的运行过程(图片源于《算法导论》第3版109页):
图1:COUNTING-SORT在输入数组A[1..8]上的处理过程,其中A中的每一个元素都是不大于k=5的非负整数。
Python实现代码:
a = [2, 5, 3, 0, 2, 3, 0, 3] c = [] b = [] k = 6 for i in range(0, k): c.append(0) for i in range(0, len(a)): b.append(0) for j in range(0, len(a)): c[a[j]] = c[a[j]] + 1 for i in range(1, k): c[i] = c[i] + c[i-1] for j in range(0, len(a))[::-1]: b[c[a[j]]-1] = a[j] c[a[j]] = c[a[j]] - 1 print b
算法分析:
计数排序是使用输入元素的实际值来确定其在数组中的位置,并不是一个比较排序算法。
我们现在来分析计数排序的时间代价。
在伪代码中,第2~3行时间代价θ(k);第4~5行时间为θ(n);第7~8行时间为θ(k),第10~12行时间为θ(n)。因此,总的运行时间是θ(k+n)。当k= O(n)时,运行时间为θ(n)。
性质:
稳定:具有相同值的元素在输出数组中的相对次序与它们在输入数组中的相对次序相同。
Efficiency is intelligent laziness.