算法导论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) |