在上一篇的排序中提到的算法,在排序的最终结果中各元素的次序依赖于它们之间的比较,我们把这类排序算法称为比较排序。下面总结三种线性时间复杂度的排序算法:计数排序,基数排序和桶排序,这三种算法是用运算而不是比较来确定排序顺序的。
线性时间排序
计数排序
counting_sort(A,B,k)
let C be a new array
for i = 0 to k
C[i] = 0
// step1 :C[i] now contains the number of elements equal to i
for j = 1 to A.length
C[A[j]] = C[A[j]] + 1
// step2 :C[i] now contains the number of elements less than or equal to i
for i = 1 to k
C[i] = C[i] + C[i - 1]
// step3 :ouput each element at the particular position of B from the A's tail with C
for j = A.length to 1
B[C[A[j]]] = A[j]
C[A[j]] = C[A[j]] - 1
通过以下数组的变化能更好理解上面的代码:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
2 | 5 | 3 | 0 | 2 | 3 | 0 | 3 |
通过代码中step1的运算(C[A[j]] = C[A[j]] + 1)得出以下数组C
0 | 1 | 2 | 3 | 4 | 5 |
2 | 0 | 2 | 3 | 0 | 1 |
通过代码中step2的运算(C[i] = C[i] + C[i - 1])数组C的值发生变化
0 | 1 | 2 | 3 | 4 | 5 |
2 | 2 | 4 | 7 | 7 | 8 |
通过代码中step3的运算,依次输出A的元素到数组B
以下以A[8] = 3为例:根据数组C可知,3的前面有7个小于或等于它的数,因此把3放在输出数组B第7个位置,同时将数组C里C[3]的值减1
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
3 |
0 | 1 | 2 | 3 | 4 | 5 |
2 | 2 | 4 | 6 | 7 | 8 |
基数排序
radix_sort(A, d)for i = 1 to duse a stable sort to sort array A on digit i
桶排序
A | B | |||
0.78 | 0 | |||
0.17 | 1 | 0.12 | 0.17 | |
0.39 | 2 | 0.21 | 0.23 | 0.26 |
0.26 | 3 | 0.39 | ||
0.72 | 4 | |||
0.94 | 5 | |||
0.21 | 6 | 0.68 | ||
0.12 | 7 | 0.72 | 0.78 | |
0.23 | 8 | |||
0.68 | 9 | 0.94 |
bucket_sort(A)
n = A.length
let B[0..n-1] be a new array
for i = 0 to n-1
let B[i] be an empty list
for i = 1 to n
insert A[i] into list B[nA[i]] // nA[i]向下取整
for i = 0 to n-1
sort list B[i]
concatenate the lists B[0],B[1],..B[n-1] together in order
选择(中位数和顺序统计量)
randomized_select(A,p,r,i)
if p == rreturn A[p]q = ramdomized_partition(A,p,r)k = q - p + rif k == ireturn A[q]else if k < ireturn randomized_select(A,q+1,r,i - k)elsereturn randomized_select(A,p,q - 1,i)
同样一道来自庞果英雄会的一道题,可以利用以上的选择算法。