8.1 排序算法的下界
插入排序算法作用域包含三个元素的输入序列的决策树情况
最坏情况的下界
在决策树中,从根节点到任意一个可达叶结点之间最长简单路径的长度,表示的是对应的排序算法中最坏情况下的比较次数。
因此,一个比较排序算法中的最坏情况比较次数就等于其决策树的高度。
同时,当决策树中每种排列都是以可达的叶结点的形式出现时,该决策树高度的下界也就是比较排序算法运行时间的下界。
下面的定理给出这样的一个下界。
定理 8.1
在最坏情况下,任何比较排序算法都需要做Ω (nlgn)次比较。
推论 8.2
堆排序和归并排序都是渐进最优的比较排序算法。
证明
堆排序和归并排序的运行时间上界为O(nlgn),这与定理8.1给出的最坏情况的下界Ω(nlgn)是一致的。
8.1-3
Solution
8.2 计数排序
伪代码 过程 COUNTING-SORT
//输入是一个数组A[1..n],A.length=n
//B[1..n]存放排序的输出
//C[0..k]提供临时存储的空间
COUNTING-SORT(A,B,k)
let C[0..k] be a new array
//数组C的值被置为0
for i = 0 to k
C[i] = 0
//遍历每一个输入元素,如果一个输入元素的值为i,就将C[i]值加1
for j = 1 to A.length
C[A[j]] = C[A[j]] + 1//C[i]中保存的就是等于i的元素的个数
//C[i] now contains the number of elements equal to i
//通过加总计算确定对每一个i-0,1,……,k,有多少输入元素是小于或等于i的
for i = 1 to k
C[i] = C [i] + C[i-1]
//C[i] now contains the number of elements less than or equal to i
//把每个元素A[j]放到它在输出数组B中的正确位置上
for j = A.length downto 1
B[C[A[j]]] = A [j]
C[A[j]] = C[A[j]] - 1
计数排序的运行过程
8.2-1
Using Figure 8.2 as a model, illustrate the operation of COUNTING-SORT on the array A =⟨6,0,2,0,1,3,4,6,1,3,2⟩.
以图8.2为模型,说明数组a上计数排序的操作=⟨6,0,2,0,1,3,4,6,1,3,2⟩.
Solution
我们有那个C=⟨2,4,6,8,9,9,11⟩. 然后,在第10-12行循环的连续迭代之后,我们得到
B=⟨,,,,,2.⟩,
B=⟨,,,,,2,3,,,⟩,
B=⟨,,,1,,2,3,,,⟩
最后,
B=⟨0,0,1,1,2,2,3,3,4,6,6⟩.
8.3 基数排序
基数排序是先按最低有效位进行排序来解决卡片排序问题的。
“一叠”7张3位数卡片的基数排序过程
伪代码 过程 RADIX-SORT(A,d)
//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-1
Using Figure 8.3 as a model, illustrate the operation of RADIX-SORT on the following list of English words: COW, DOG, SEA, RUG, ROW, MOB, BOX, TAB, BAR, EAR, TAR, DIG, BIG, TEA, NOW, FOX.
以图8.3为模型,在以下英文单词列表中说明基数排序的操作:COW、DOG、SEA、RUG、ROW、MOB、BOX、TAB、BAR、EAR、TAR、DIG、BIG、TEA、NOW、FOX。
Solution
8.3-4
Solution
首先运行整数列表,并将每个整数转换为基数n,然后对它们进行基数排序。每个数字最多有3位数字,因此只需通过 次。对于每个过程,有n个可能的值可以采用,因此我们可以使用计数排序在O(n)时间内对每个数字进行排序。
8.4 桶排序
伪代码 过程
//输入:一个包含n个元素的数组A,且每个元素A[i]满足0≤A[i]<1
//一个临时数组B[0..n-1]来存放链表(即桶),并假设存在一种用于维护这些链表的机制
BUCKET-SORT(A)
n = A.length
let B[0..n-1] be a new array
for i = 0 to n-1
make B[i] an empty list
for i = 1 to n
insert A[i] into list B[⌊nA[i]⌋]
for i = 0 to n-1
sort list B[i] with insertion sort
concatenate the lists B[0],B[1],...,B[n-1] together in order
在一个包含10个元素的输入数组上的桶排序过程
8.4-1
Using Figure 8.4 as a model, illustrate the operation of BUCKET-SORT on the array A=⟨.79,.13,.16,.64,.39,.20,.89,.53,.71,.42⟩.
以图8.4为模型,说明了BUCKET-SORT在数组A=⟨.79,.13,.16,.64,.39,.20,.89,.53,.71,.42⟩上的操作。
Solution
A=⟨.13,.16,.20,.39,.42,.53,.64,.71,.79,.89⟩.
8.4-2
Solution
如果所有的键都落在同一个bucket中,并且它们恰好是以相反的顺序排列的,那么我们必须使用插入排序将一个bucket中的n个项按相反的顺序排序。这是Θ(n^2)。
我们可以使用合并排序或heapsort来提高最坏情况下的运行时间。选择插入排序是因为它在链表上运行良好,链表具有最佳时间,并且对于短链表只需要恒定的额外空间。如果我们使用另一种排序算法,我们必须将每个列表转换为一个数组,这在实践中可能会减慢算法的速度。