使用Loop不变量来证明合并排序的正确性(初始化,维护,终止)

时间:2016-11-09 03:23:56

标签: algorithm loops sorting mergesort invariants

如何通过推理循环不变量的状态来证明合并排序的正确性?我唯一可以想象的是,在合并步骤中,子组合(不变量)在组合时保持它们的状态,即它们是在每个合并步骤再次排序。但我不知道我是否正确进行。我对循环不变量和东西没有太多了解。可以在这一个上启发我吗?解释每个阶段会发生什么

a)初始化 b)维护 c)终止

非常有责任!

1 个答案:

答案 0 :(得分:3)

合并排序的伪代码

MERGE-SORT(A,p,r)

    1 if p < r
    2    then q <-- [(p + r) / 2]
    3          MERGE-SORT(A, p, q)
    4          MERGE-SORT(A, q + 1, r)
    5          MERGE-SORT(A, p, q, r)

MERGE-SORT(A,p,q,r)

    1  n1 <-- q - p + 1 
    2  n2 <-- r - q
    3  create arrays L[1 ... n1 + 1] and R[1 ... n2 + 1]
    4  for i <-- 1 to n1
    5       do L[i] <-- A[p + i - 1]
    6  for j <-- 1 to n2
    7      do R[j] <-- A[q + j]
    8  L[n1 + 1] <-- infinite 
    9  R[n2 + 1] <-- infinite
    10 i <-- 1
    11 j <-- 1
    12 for k <-- p to r
    13     do if L[i] <= R[j]
    14           then A[k] <-- L[i]
    15                i <-- i + 1
    16           else A[k] <-- R[j]
    17                j <-- j + 1

我们尝试对两堆卡进行排序,但我们避免在每个基本步骤中检查堆是否为空,并且我们使用无限作为前哨卡来简化我们的代码。因此,每当前哨卡infinie曝光时,它不能是较小的卡,除非两个桩都暴露了他们的哨兵牌。但是一旦发生这种情况,所有非哨兵牌都已被放置在输出堆上。由于我们事先知道确切的r - p + 1卡片将被放置在输出堆上,我们可以在执行了许多基本步骤后停止。

  • Loop Invariant:

    • 初始化:在循环的第一次迭代之前,我们有k = p,因此子数组A[p ... k - 1]为空。这个空子阵列包含L和R的k - p = 0个最小元素,自i = j = 1起,L [i]和R [j]都是其数组中尚未复制回A的最小元素。

    • 维护:要看到每次迭代都保持循环不变,我们首先假设l [i]&lt; = R [j]。然后L [i]是尚未复制回A的最小元素。因为A[p ... k - 1]包含k - p个最小元素,所以在第14行将L [i]复制到A [k]之后,子数组{{ 1}}将包含A[p ... k]个最小元素。增加k(在for循环更新中)和i(在第15行中)重新建立下一次迭代的循环不变量。如果改为L [i]&gt; R [j],然后第16-17行执行适当的操作以保持循环不变。

    • 终止:终止时,k - p + 1。通过循环不变量,子k = r + 1A[p ... k - 1],按照排序顺序包含A[p ... r]k - p = r - p + 1的{​​{1}}个最小元素。数组L和R一起包含L[1 ... n1 + 1]个元素。除了两个最大的元素之外的所有元素都被复制回A,这两个最大的元素是哨兵。