8.2-2 证明COUNTING-SORT是稳定的。
问题解答:
假设输入数组A[1...n],length[A]=n,数组A中有两个元素具有相同的值,下标分别为a,b(1≤a<b≤n)即A[a] = A[b]。经过计数排序运行至行7,C[A[a]] = C[A[b]]。在第9~11行中循环部分中,循环变量 i 用于指示数组A的下标,其值从 length[A] 到 1 递减遍历。由b>a可知,A[b]优先插入数组B中。在循环执行体行10、行11中,每当将一个值A[i]放入数组B位置C[A[i]]时,都要使C[A[i]]的值减1。因此,A[b]首先插入数组输出数组B中,且A[a]插入在A[b]的前一个位置上。
8.2-3 在COUNTING-SORT过程中,假设第9中for循环的首部改成改写成如下形式
9 for j ← 1 to length[A]
证明该算法仍能正常的工作。修改后的算法是稳定的吗?
问题解答:
在第9~11行中循环部分中,循环变量i用于指示输入数组A的下标。循环首部的改变,仅改变数组A中元素遍历次序,即数组A中元素插入数组B的次序,从 大下标优先插入变为 小下标优先插入。数组A中元素插入数组B的位置为C[A[i]],只和元素的值有关,和元素的下标无关。所以修改后的算法仍然能正常的工作。
修改后的算法,数组A中元素插入数组B的次序是 小下标优先插入。如果有两个元素有相同的值,即指向C中同一个元素,则较小下标的元素优先插入数组B中,然后使指向的C中元素减1,所以较大下标的元素插入到较小下标的元素的前面。算法是不稳定的。
8.3-2 下面的算法中那些是稳定的:插入排序,合并排序,堆排序和快速排序?给出一个能是任何排序算法都稳定的方法。给出的方法带来的额外时空开销是多少?
问题解答:
插入排序、合并排序均是稳定的;快速排序,堆排序不稳定。
先给每个元素增加一个域index,表示在输入数组中的索引值。元素之间的比较,先比较元素的值,若值是相等的话,需进一步比较index。每个index可用 lg n位大小的整数来表示,需额外的 Ω ( n lg n )空间。由于增加的额外的比较次数至多和原先的比较次数相同,时间复杂度并不变。(参考答案)
8.3-4说明如何在O(n)时间内,对0到n^2-1之间的n个整数进行排序。
问题解答:
引理8.3 给定n个d位数,每一个数位可以取k种可能的值。如果所用的稳定排序需要Θ(n+k)的时间,基数排序算法能以Θ(d(n+k))的时间正确地对这些数进行排序。
若采用n进制对0到n^2-1之间的数表示,需要2位数即可。由上述引理可得,基数排序的时间为Θ(d(n+k))=Θ(2(n+n)) =Θ(n) (参考答案)
8.4-2 桶排序的最坏情况运行时间是什么?如果要在保持其线性运行时间的同时,使最坏情况时间为O(nlgn),要对算法做什么样的修改?
问题解答:
最坏情况下,即所有的输入元素均落入一个桶内,桶排序就退化为一个插入排序。而插入排序的最坏情况时间代价为Θ(n^2)。如果要在保持其线性运行时间的同时,使最坏情况时间为O(nlgn),对桶内元素排序方法更换为最坏情况为O(nlgn)的合并排序。
8.4-3在单位圆内有n个点,pi=(xi, yi),使得0<xi^2 + yi^2 ≤1, i = 1,2,....,n。假设所有点是均匀分布的,亦即,某点落在圆的任一区域中的概率与该区域的面积成正比。请设计一个Θ(n)期望的算法,来根据点到原点的距离di=sqrt(xi^2 + yi^2)对n个点排序。
问题解答:
桶排序是把区间[0,1)区间划分成n个大小相同的子区间(即桶),且要求输入元素等可能落在任何桶中。按照桶排序的思想,把单位圆划分成n个等面积的同心环即可。
设:输入元素有两个域x,y,分别表示横坐标和纵坐标。元素之间的大小比较是通过比较di=sqrt(xi^2 + yi^2)来判断的。
算法伪代码:
BUCKET-SORT'(A)
n ← length(A)
for i ←1 to n
do index ← floor( n( A[i].x^2 + A[i].y^2 ) )
insert A[i] into B[index]
for i ←1 to n
do sort list B[i] with insertion sort
concatenate the list B[0], B[1], ..., B[n-1] together in order
思考题
8-2 以线性时间原地排序
假设有一个有n个数据记录组成的数组要排序,且每个记录的关键字的值为0或1。排序这样一组记录的一个算法应具备如下三个特性中的一部分。
1)算法的运行时间为O(n)。
2)算法是稳定的。
3)算法是原地排序的,它可以使用除输入数组以外的固定量的存储空间。
a)给出一个满足上述条件1和条件2的算法。
b)给出一个满足上述条件1和条件3的算法。
c)给出一个满足上述条件2和条件3的算法。
d)在a)~c)中给出的算法能否用来在O(bn)时间内排序,对有b位关键字的n个记录进行基数排序?如果行,说明如何做;如果不行,说明原因。
e)假设一个n个记录中每个的关键字都介于1到k之间。说明如何修改计数排序,使得可以在O(n+k)时间内对n个记录原地排序。除输入数组外,可另用O(k)的存储空间。你给出算法是稳定的吗?(提示:当k=3时应该如何做)
问题解答:
a)使用计数排序即可满足要求。
b)由于记录的关键字的值只有两种情况(0或1),可使用类似快速排序中PARTITION将数组划分为两个区域,一区域只含关键字值均为0,另一区域关键字均为1。
具体算法为:
PARTITON-SORT(A)
n ← lenght[A]
i ← 1
while A[i] = 0 and i ≤ n
do i ← i + 1
p← i
i ← i - 1
for j ← p to n
do if A[j] = 0
then i ← i + 1
exchange A[i] ↔ A[j]
c) 使用插入排序或合并排序即可满足要求
d)
a)算法可以,对数组元素的每一位的排序都采用计数排序即可。
b)算法不可以,是由于快速排序算法的数组分割是不稳定的。
c)算法也不可以,是由于插入排序和合并排序的最坏运行时间为O(n^2)。
e) 说明暂时不会