算法导论8.2 Exercises 答案
8.2-1
第一次循环结束后,得到数组$C=\langle2,2,2,2,1,0,2\rangle$.
第二次循环结束后,得到数组$C=\langle2,4,6,8,9,9,11\rangle$.
那么第三次循环,依次得到:
$\begin{array}{ll}
B&C\
\langle\phantom{2},\phantom{2},\phantom{2},\phantom{2},\phantom{2},\phantom{2},\phantom{2},\phantom{2},\phantom{2},\phantom{2},\phantom{2}\rangle & \langle2,4,6,8,9,9,11\rangle\
\langle\phantom{2},\phantom{2},\phantom{2},\phantom{2},\phantom{2},2,\phantom{2},\phantom{2},\phantom{2},\phantom{2},\phantom{2}\rangle & \langle2,4,5,8,9,9,11\rangle\
\langle\phantom{2},\phantom{2},\phantom{2},\phantom{2},\phantom{2},2,\phantom{2},3,\phantom{2},\phantom{2},\phantom{2}\rangle & \langle2,4,5,7,9,9,11\rangle\
\langle\phantom{2},\phantom{2},\phantom{2},1,\phantom{2},2,\phantom{2},3,\phantom{2},\phantom{2},\phantom{2}\rangle & \langle2,3,5,7,9,9,11\rangle\
\langle\phantom{2},\phantom{2},\phantom{2},1,\phantom{2},2,\phantom{2},3,\phantom{2},\phantom{2},6\rangle & \langle2,3,5,7,9,9,10\rangle\
\langle\phantom{2},\phantom{2},\phantom{2},1,\phantom{2},2,\phantom{2},3,4,\phantom{2},6\rangle & \langle2,3,5,7,8,9,10\rangle\
\langle\phantom{2},\phantom{2},\phantom{2},1,\phantom{2},2,3,3,4,\phantom{2},6\rangle & \langle2,3,5,6,8,9,10\rangle\
\langle\phantom{2},\phantom{2},1,1,\phantom{2},2,3,3,4,\phantom{2},6\rangle & \langle2,2,5,6,8,9,10\rangle\
\langle\phantom{2},0,1,1,\phantom{2},2,3,3,4,\phantom{2},6\rangle & \langle1,2,5,6,8,9,10\rangle\
\langle\phantom{2},0,1,1,2,2,3,3,4,\phantom{2},6\rangle & \langle1,2,4,6,8,9,10\rangle\
\langle0,0,1,1,2,2,3,3,4,\phantom{2},6\rangle & \langle0,2,4,6,8,9,10\rangle\
\langle0,0,1,1,2,2,3,3,4,6,6\rangle & \langle0,2,4,6,8,9,9\rangle\
\end{array}$
8.2-2
考虑两个下标$i,j$满足$A[i]=A[j]=x,i< j$。第11行的逆序for循环将会使得$A[j]$先被访问,$A[i]$后被访问。当访问到$A[j]$时,数$A[j]$被放置到了数组$B$中的位置$C[x]$,接下来$C[x]$将会自减$1$。由于这个for循环中,$C$数组中的所有值只会递减,不会递增,因此当访问到$A[i]$时,此时的$C’[x]<C[x]$,即彼时访问$A[j]$前的$C[x]$。因此,$A[i]$将会放置到位置$C’[x]$中,保持了相对顺序。因此,这种实现下的计数排序是稳定的。
8.2-3
将循环正序,并不会影响排序的正确性。只要键相同,先后放置顺序并不重要,不同元素间的顺序将仍然保持。排序程序转换成不稳定的原因是对于两个下标$i,j$满足$A[i]=A[j]=x,i< j$,由于$i$先被遍历,$j$后被遍历,但是第11行的for循环下,$C$数组仍然是递减的,这将导致排序后,$A[i]$会被放置在$A[j]$的后面,因此仍然是不稳定的。
1 | COUNTING-SORT'(A, n, k) |
8.2-4
初始化:一开始值为$n$的循环迭代前,$C[i]$表示数组$A$中有多少个数小于等于$i$,也就是最后一个$i$所放置的位置,循环不变量成立。
保持:在值为$i$的循环开始前,$C[A[i]]$代表着当前数$C[A[i]]$中应该放置的位置。第12行的代码将$A[i]$放置到正确的位置,第13行将$C[A[i]]$自减$1$,如果存在下一个$A[j]=A[i]=x,j< i$,那么它确实应该放置在$C[A[i]]-1$处,因为两个数相同,应该放在一起;如果不存在,那么$C[A[i]]$的值永远不会被访问到,可以忽略。因此,值为$i$的循环完成后,数组$C$的含义仍然保持,循环不变量成立。
终止,循环完成后,数组$C$中所有值都将被忽略,数组$B$是个有序的数组,循环正确终止。
8.2-5
1 | // 没有卫星数据,意味着不需要考虑排序的稳定性,直接赋值即可。 |
8.2-6
可以发现,算法ANSWER-QUERY的第10行中,每次循环都是$O(1)$常数级别的。
1 | //数组Q表示询问列表,Q[i].a和Q[i].b表示题中的a和b。 |
8.2-7
基本思想是:通过对每个浮点数乘以$10^d$转换成整数,再统计到下标中,然后排序完成后再转换成浮点数。
1 | COUNTING-SORT-FLOAT(A, n, k, d) |