这个循环是不变的,它的非正式证明是否正确? (CLRS第3版,练习2-1-3)

时间:2018-02-14 13:51:36

标签: algorithm search clrs loop-invariant

给出以下线性搜索算法(将索引1称为元素数组中第一个元素的索引):

found_idx = nil
for i = 1 to A.length
  if A[i] == value
    found_idx = i
    return found_idx
  end-if
end-for
found_idx

我想知道这个循环不变量是否正确: “在for循环的每次迭代开始时,found_idx是数组中以i-1结尾的索引,如果该值存在,则该值存在”

以下是我根据CLRS中的格式提出的关于此循环不变量的非正式解释:

  1. 初始化:在第一次迭代之前为真,因为i = 1且结束于i-1的数组为空,因此found_idx为nil。
  2. 维护:每次迭代后都是如此,因为i的每个值都会检查A[i],然后然后 i增加,意味着在每次新迭代之前已经检查了所有直到i-1的元素。
  3. 终止:这会在i > A.length时终止,这意味着已经检查了包括A.length在内的所有元素。
  4. 我主要关注的是引用以i-1结尾的索引感觉不正确,因为循环以i为1开始,这是数组的第一个元素。换句话说,引用阵列的子阵列感觉是错误的,其中子阵列以小于阵列的起始索引的索引结束,对于该阵列,子阵列首先应该是子阵列。这似乎意味着上面给出的循环不变量在循环的第一次迭代之前实际上是假的。

    思想?

1 个答案:

答案 0 :(得分:1)

由于循环提前终止,其不变量如下:

found_idx = nil && ∀k<i : A[k] ≠ value

&&之后的部分表示&#34; A以下索引的所有i元素都不等于value&#34;

  • 在进入循环之前,这很简单。
  • 条件是将found_idx保留在nil,或提前终止循环
  • i到达A.length
  • 时,循环终止

循环的后置条件为found_idx = nil && ∀k<A.length : A[k] ≠ value,这意味着value不属于A个元素。这也意味着您可以通过重写循环来消除found_idx,如下所示:

for i = 1 to A.length
    if A[i] == value
        return i
    end-if
end-for
return nil