第 8 章 线性时间排序

来源:互联网 发布:警用证件夹淘宝 编辑:程序博客网 时间:2024/06/03 14:37

  到目前为止,我们已经介绍了几种能在O(nlgn)时间内排序的n个数的算法。归并排序和堆排序达到了最坏情况下的上界;快速排序在平均情况下达到上界。这些算法都有一个性质:在排序的最终结果中,个元素的次序依赖于它们之间的比较。称这些排序算法为比较排序
  8.1节证明对包含n个元素的输入序列来说,任何比较排序在最坏情况下都要经过Ω(nlgn)次比较。因此,归并排序和堆排序是渐近最优的,并且任何已知的比较排序最多就是在常数因子上由于它们。
  8.2、8.3、8.4节讨论三种线性时间复杂度的排序算法:计数排序、基数排序和桶排序。

8.1 排序算法的下界

定理8.1 在最坏情况下,任何比较排序算法都需要做Ω(nlgn)次比较。
推论8.2 堆排序和归并排序都是渐近最优的比较排序算法。

8.2 计数排序

计数排序假设n个输入元素中的每一个都是在0到k区间内的一个整数,其中k为某个整数。当k=O(n)时,排序的运行时间为θ(n)。
  计数排序的基本思想:对每一个输入元素x,确定小于x的元素个数。利用这一信息,就可以直接把x放到它输出数组中的位置上了。
  在计数排序算法中,假设输入是一个数组A[1..n],A.length=n。还需要两个数组:B[1..n]存放排序的输出,C[0..k]提供临时存储空间。
COUNTNG-SORT(A, B, k)

let C[0..k] be a new arrayfor i = 0 to k    C[i] = 0for j = 1 to A.length    C[A[j]] = C[A[j]] + 1//C[i]now contains the number of elements equal to ifor i = 1 to k    C[i] = C[i] + C[i-1]//C[i]now contains the number of elements less than or equal to ifor j = A.length downto 1    B[C[A[j]]] = A[j]    C[A[j]] = C[A[j]]-1

计数排序的总的时间代价是θ(k+n)。在实际工作中,当k = O(n),一般采用计数排序,这使得运行时间为θ(n)。
  计数排序的一个重要性质就是它是稳定的:具有相同值的元素在输出数组中的相对次序与它们在输入数组中的相对次序相同。也就是说,对两个相同的数,在输入数组中先出现的数,在输出数组中也位于前面。计数排序的稳定性很重要的另一个原因是:计数排序经常会被用作基数排序算法的一个子过程。

8.3 基数排序

基数排序是一种用在卡片排序机上的算法。
基数排序算法是非常直观的。在下面的代码中,我们假设n个d位的元素存放在数组A中,其中第 1 位是最低位,第 d 位是最高位
RADIX-SORT(A,d)

for i = 1 to d    use a stable sort to sort array A on digit i

引理8.3 给定n个d位数,其中一个数位有k个可能的取值。如果RADIX-SORT使用的稳定排序方法耗时θ(n+k),那么他就可以在θ(d(n+k))时间内将这些数排好序。
当d为常数且k=O(n)时,基数排序具有线性的时间代价。
引理8.4 给定一个b位数和任何正整数r<=b,如果RADIX-SORT使用的稳定排序算法对数据取值区间是0到k的输入进行排序耗时θ(n+k),那么它就可以在θ((b/r)(n+2r))时间内将这些数排好序。
利用计数排序作为中间稳定排序的基数排序不是原址排序。当主存的容量比较宝贵时,更倾向于想快速排序这样的原址排序。

8.4 桶排序

  桶排序假设输入数据服从均匀分布,平均情况下它的时间代价是O(n)。与计数排序类似,因为对输入数据作了某种假设,桶排序的速度也很快。具体来说,计数排序假设输入数据都属于一个小区间内的整数,而桶排序则假设输入是由一个随机过程产生,该过程将元素均匀、独立地分布在[0, 1)区间上。
  桶排序将[0,1)区间划分为n个相同大小的子区间,或称为。然后,将n个输入数分别放到各个桶中。因为输入数据是均匀的、独立地分布在[0, 1)区间上,所以一般不会出现很多数落在同一个桶中的情况。为了得到输出结果,我们先对每个桶中的数进行排序,然后遍历每个桶,按照次序把各个桶中的元素列出来即可。
  在桶排序的代码中,我们假设输入是一个包含n个元素的数组A,且每个元素A[i]满足0<=A[i]<=1.此外,算法还有一个临时数组B[0..n-1]来存放链表(即桶),并假设存在一种用于维护这些链表的机制。
BUCKET-SORT(A)

n = A.lengthlet B[0..n-1] be a new arrayfor i = 0 to n-1    make B[i] an empty listfor i = 1 to n    insert A[i] into list B[⌊nA[i]⌋]for i = 0 to n-1    sort list B[i] with insertion sortconcatenate the list B[0],B[1], ... , B[n-1] together in order

桶排序的期望运行时间为:θ(n)。即使输入数据不服从均匀分布,桶排序也仍然可以线性时间内完成。只要输入数据满足下列性质:所有桶的大小的平方和与总的元素数呈线性关系,那么桶排序任然能在线性时间内完成。