Hoare划分的正确性)本章中的PARTITION算法并不是其最初的版本。下面给出的是最早由C. R. Hoare所设计的划分算法:
  思考题 7-1 Hoare划分的正确性
  a. 试说明HOARE-PARTITION在数组A = {13, 19, 9, 5, 12, 8, 7, 4, 11, 2, 6, 21}上的操作过程,并说明在每一次执行第4~14行while循环时数组元素的值和辅助变量的值。
  后续的三个问题要求读者仔细论证HOARE-PARTITION的正确性。在这里假设子数组A[p..r]A[p..r]至少包含2个元素,试证明下列问题:
  b. 下标iijj可以使我们不会访问在子数组A[p..r]A[p..r]以外的数组AA的元素。
  c. 当HOARE-PARTITION结束时,它返回的值jj满足pj<rp ≤ j < r
  d. 当HOARE-PARTITION结束时,A[p..j]A[p..j]中的每一个元素都小于或等于A[j+1..r]A[j+1..r]中的元素。
  在7.1节的PARTITION过程中,主元(原来存储在A[r]A[r]中)是与它所划分的两个分区分离的。与之对应,在HOARE-PARTITION中,主元(原来存储在A[p]A[p]中)是存在于分区A[p..j]A[p..j]A[j+1..r]A[j+1..r]中的。因为有pj<rp ≤ j < r,所以这一划分总是非平凡的。
  e. 利用HOARE-PARTITION,重写QUICKSORT算法。
  
  
  a.
  思考题 7-1 Hoare划分的正确性
  
  b.
  虽然下标iijj分别被初始化为p1p-1r+1r+1,但是在第一轮while迭代中,ii会被先加1,而jj会被先减1,这样下标iijj分别从pprr开始。所以在迭代开始,下标iijj没有超出数组范围。
  由于以首个元素作为划分主元,所以在第一轮while迭代中,ii会停留在pp,而jj会一直向左移动,直到遇到一个小于或等于xx的元素。下面分两种情况说明:
  1) 如果jj在向左移动的过程中一直没有遇到小于或等于xx的元素,那么jj会一直向左移动直到j=pj = p为止,因为A[p]=xA[p] = x满足jj的停止条件。此时,由于ii一直停留在pp的位置,所以i=ji = j,故while迭代退出。在这个过程中,iijj都没有超出数组A[p..r]A[p..r]的范围。
  2) 如果jj遇到了一个小于或等于xx的元素 (该元素不为A[p]A[p]),那么A[j]A[j]A[i]A[i] (A[i]A[i]A[p]A[p]) 交换。这说明在下标jj的左侧至少有一个小于或等于xx的元素,并且在下标ii的右侧至少有一个大于或等于xx的元素,这可保证iijj在移动过程中不会超出数组范围。
  
  c.
  在第一轮while迭代中,下标ii一定会停留在pp,而下标jj分2种情况:
  1) 如果jjrr位置停留下来了,此时有i<ji < j (因为已经假设数组元素不少于2个),那么交换A[i]A[i]A[j]A[j],继续进行第二轮while迭代。在第二轮while迭代中,jj一定至少向左移动一个位置,故一定有j<rj < r
  2) 如果jj没有在rr位置停留,而是继续向左移动,此时也有j<rj < r
  再根据b的结论,jj不会超出数组范围,故jpj ≥ p。所以jj一定满足pj<rp ≤ j < r
  
  d.
  先给出循环不变式:在每轮while迭代开始之前,A[p..i]A[p .. i]中的元素都小于或等于xx,并且A[j..r]A[j .. r]中的元素都大于或等于xx。这个循环不变式应该不难证明,这里省略证明过程。
  下面分析while迭代的终结时的情况。在while迭代中,代码第5 ~ 7行的repeat迭代和第8~10行的repeat迭代结束时,必然有A[p..i1]A[p..i-1]中的元素都小于或等于A[j+1..r]A[j+1..r]中的元素。在最后一次while迭代中,repeat迭代结束后,必然有i=ji = ji=j+1i = j+1。如果i=ji = j,那么必然有A[i]=xA[i] = x,由于A[p..i1]A[p..i-1]中的元素都小于或等于A[j+1..r]A[j+1..r]中的元素,将A[i]A[i]加入A[p..i1]A[p..i-1],于是有A[p..i]A[p..i] (即A[p..j]A[p..j]) 中的元素都小于或等于A[j+1..r]A[j+1..r]中的元素。如果i=j+1i = j+1,那么j=i1j = i-1,于是有A[p..j]A[p..j]中的元素都小于或等于A[j+1..r]A[j+1..r]中的元素。
  
  e.
  思考题 7-1 Hoare划分的正确性

代码链接:https://github.com/yangtzhou2012/Introduction_to_Algorithms_3rd/tree/master/Chapter07/Problem_7-1

相关文章: