1、1.证明 graham-scan 的正确性 2.优化 matrix-chain-orderPrint-optimal-parens,并构建优化三角剖分解如果在一个Q3 的点集 Q 上运行 graham-scan,则在过程终止时,栈 S 从底部到顶部包含了按逆时针方向排列在 CH(Q)中的各个顶点。证明:我们有点序列。对 i=2,3,m,定义一个点子集 Qi=p0,p1,pi。Q-Qm 中的点是那些被删除的点,因为它们与 Qm 中的某个点相对于 p0 的极角相同;这些点不在 CH(Q)中,因而 CH(Qm)=CH(Q) 。于是,只要证明当 graham-scan 终止时,栈 S 中包含了 CH(
2、Qm)的顶点,且这些顶点是按照逆时针从底部自顶部在栈中排列的。注意,正如 p0,p1 和 pm 是 CH(Q)中的顶点一样,p0,p1 和 pi 也是 CH(Qi)中的顶点。用循环不变式:初始化:在首次进入循环时,这个循环不变式得到保持,因为此时栈 S 中恰包含了 Q2=Qi-1 中的顶点,这三个顶点的集合形成了它们各自的凸包。此外,它们按逆时针排列,从底至顶地出现在栈 S 中。保持:进行 for 循环的一层迭代后,栈 S 顶上的点为 pi-1,它是在上一次迭代最后被压入栈的。设第 1011 行中 while 循环执行后,第 12 行将 pi 压入栈之前,栈 S 顶部的点为 pj。设 pk 为
3、栈 S 中紧靠 pj 之下的点。在 pi 成为栈顶且尚未将 pi 压入栈时,栈 S 中包含了与 for 循环的第 j 次迭代后一样的点。因此,根据循环不变式,在该时刻,栈 S 中恰包含了 CH(Qi)中的顶点,它们按逆时针自底向上地出现在栈中。我们继续关注单 pi 被压入栈之前的这一时刻。我们已经知道,pi相对于 p0 的极角大于 pj 的极角并且角 pkpjpi 是左转的。由于 S 恰包含了 CH(Qj)中顶点,因此,一旦压入 pi,栈 S 中恰包含了CH(Qjpi)中的顶点,并且这些点仍然按逆时针顺序自底向上地出现在栈中。考虑任意一个在 for 循环的第 i 次迭代中被弹出的点 pt,设
4、pr 和pt 被弹出时栈 S 中紧靠在 pt 下面的点。角 prptpi 所做的是非左转向,而 pt 相对于 p0 的极角大于 pr 的极角,pt 必定在由 p0,pr 和pi 构成的三角形内部,或者在这个三角形的某条边上。显然,由于pt 在一个由 Qi 的其他三个点构成的三角形内部,故不可能是CH(Qi)的一个顶点。所以:CH(Qi-pt)=CH(Qi)设 pi 为 for 循环的第 i 次迭代中弹出点的集合。由于上式适合 pi中所有点,故可以用它来反复说明 CH(Qi-pi)=CH(Qi) 。但是,Qi-pi=Qjpi,故 CH(Qjpi)= CH(Qi-pi)=CH(Qi)终止:当循环终
5、止时,有 i=m+1,因而,循环不变式意味着栈 S 中恰包含了 CH(Qm)中按逆时针顺序从栈底向上排列的顶点。执行第一行的代码需要时间 (n) ,应用归并排序或堆排序对极角进行排序,用叉积方法对极角进行比较,执行第 2 行代码所需要的时间为 O(nlgn) 。第 58 行代码执行时间为 O(1) 。因为 mn-1,所以第 912for 循环至多执行 n-3 次,因为 push 的时间为 O(1) ,故,除执行 while 时间,for 用时 O(n) 。While 循环时间为 O(n) 。对 i=0,1,m 每个点 pi 压入栈一次,执行 push 至多与 pop 一样。至少有三个顶点不会从
6、栈中弹出,所以事实上总共至多执行 m-2 次迭代。由于第 10 行的测试用时 O(1)每次调用 pop 所需时间 O(1),且 mn-1,所以 while 用时 O(n) ,故 graham-scan 用时 O(nlgn) 。2.Optimal-polygon-triangulation(p)nlength(p)-1for i1 to ndo ti,j 0for 12 to n dofor i1 to n-1+1 doji+1-1ti,j for ki to j-1 doqti,k+tk+1,j+W(i-1,k,j)if qi+1then print-optimal-parens(s.i,si,j)print Vi-1Vsi,j,Vsi,jVjprint-optimal-parens(s,si,j+1.j)return