Sorting in Linear Time
我们已经介绍了几种能在 O ( n l g n ) O(nlgn) O(nlgn)时间内排序n个数的算法:
归并排序和堆排序在最坏情况下到达此上界,快速排序以平均速度到达这种情况。
一个上述的共同特点:排序的最终结果中,各元素的次序依赖于它们之间的比较。为此,我们将这类排序称为比较排序。
*任何比较问题在最坏情况下,排列n个元素时一定会进行 Ω ( n l g n ) \Omega(nlgn) Ω(nlgn)次的比较。
排序算法的下界
- 我们先假设不存在 a i = a j a_i=a_j ai=aj的情况
The decision-tree model
决策树是一棵完全二叉树。
因为任何正确的排序算法都能够生成输入的每一个排列,所以对于一个正确的比较排序算法,n个元素的n!中可能都会出现在决策树的叶结点上。而且每一个叶结点都必须是可以从根节点经由某条路径达到的。
最坏情况的下界
一个比较排序算法中的最坏情况比较次数就等于决策树高度。
定理8.1:在最坏情况下,任何比较排序算法都需要做 Ω ( n l g n ) \Omega(nlgn) Ω(nlgn)次比较。
推论8.2:堆排序和归并排序都是渐进最优的比较排序算法。
计数排序
假设n个输入元素中的每一个都是在0到整数k之间区间内的一个整数。 k = O ( n ) k=O(n) k=O(n)时,排序的运行时间为 θ ( n ) \theta(n) θ(n)。
基础玩法就是对每一个输入元素x,确定小于x的元素个数,然后就可以直接把x放到输出数组的对应位置上了。
如下图: B [ 1... n ] B[1...n] B[1...n]存放排序的输出, C [ 0... k ] C[0...k] C[0...k]提供临时存储空间
这部分可能有些复杂,我们之后再来看看这部分是如何实现的。
计数排序的最大优点就是稳定:具有相同值得元素在输出数组中的相对次序与它们在输入数组中的相对次序相同。相同的数,在输入和输出中的出现顺序是一样的。
基数排序
-
一种用在卡片排序机上的算法
-
最低有效位排序进行排序
-
代码非常直观,假设n个d位的元素存放在数组A中,第1位是最低位,第d位是最高位
引理8.3:给定n个d位数,其中每一个数位有k个可能的取值。如果 R A D I X − S O R T RADIX-SORT RADIX−SORT使用的稳定排序方法耗时 θ ( n + k ) \theta(n+k) θ(n+k)。共有d轮,因此基数排序的总时间为 θ ( d ( n + k ) ) \theta(d(n+k)) θ(d(n+k))。
当d为常数且 k = O ( n ) k=O(n) k=O(n)时,基数排序具有线性的时间代价。
引理8.4:给定一个 b b b位数和任何正整数 r ≤ b r\leq b r≤b,如果 R A D I X − S O R T RADIX-SORT RADIX−SORT使用的稳定排序算法对数据取值区间是 0 0 0到 k k k的输入进行排序耗时 θ ( n + k ) \theta(n+k) θ(n+k),那么它就可以在 θ ( ( b / r ) ( n + 2 r ) ) \theta((b/r)(n+2^r)) θ((b/r)(n+2r))时间内将这些数排好序。
*快速排序可以可以有效地利用硬件的缓存;此外,利用计数排序作为中间稳定排序的基数排序不是原址排序。
说白了就是基数排序现在压根不常用
桶排序
假设输入数据服从均匀分布,平均情况下它的时间代价为 O ( n ) O(n) O(n)。
同样对输入数据做了某种假设,速度也很快。
假设的是输入由一个随机过程产生,该过程将元素均匀,独立地分布在 [ 0 , 1 ) [0,1) [0,1)区间上。
桶排序将 [ 0 , 1 ) [0,1) [0,1)区间划分为n个相同大小的子区间,或称为桶。然后,将n个输入数分别放在各个桶中。
代码:
运行时间:
最坏情况下,除了第八行以外,都是 O ( n ) O(n) O(n),我们还需要分许第八行中n次插入排序调用所花费的总时间。
如果我们使用的是插入排序:
然后我们来分析桶排序在平均情况下的运行时间。通过对输入数据取期望,可以计算出期望的运行时间。
正如我们上文所说,n是个 落在0到1的小数,我们断言:
因为每一个元素都是等概率的,因此每一个桶 i i i具有相同的期望值 E [ n i 2 ] E[n_i^2] E[ni2]。我们定义对所有 i = 0 , 1... , n − 1 i=0,1...,n-1 i=0,1...,n−1和 j = 1 , 2... , n j=1,2...,n j=1,2...,n。
有:
然后就是概率论的知识了:
注意 k ! = j k!=j k!=j,带入后我们最后得:
由以上我们得到桶排序的期望运行时间为:
输入数据不服从均匀分布,桶排序仍然可以线性时间内完成。只需要输入数据满足:所有桶的大小的平方和与总的元素数呈线性关系。