Algorithm 什么是循环不变量?

Algorithm 什么是循环不变量?,algorithm,terminology,definition,clrs,loop-invariant,Algorithm,Terminology,Definition,Clrs,Loop Invariant,我正在读CLRS的“算法简介”。在第二章中,作者提到了“循环不变量”。什么是循环不变量?在本例中,不变量意味着在每次循环迭代的某一点上必须为真的条件 在契约式编程中,不变量是在调用任何公共方法之前和之后必须为真的条件(根据契约)。简单地说,循环不变量是对循环的每次迭代都有效的谓词(条件)。例如,让我们看一个简单的For循环,它如下所示: int j = 9; for(int i=0; i<10; i++) j--; intj=9; 对于(inti=0;i=0&&i我喜欢这个非常简

我正在读CLRS的“算法简介”。在第二章中,作者提到了“循环不变量”。什么是循环不变量?

在本例中,不变量意味着在每次循环迭代的某一点上必须为真的条件


在契约式编程中,不变量是在调用任何公共方法之前和之后必须为真的条件(根据契约)。

简单地说,循环不变量是对循环的每次迭代都有效的谓词(条件)。例如,让我们看一个简单的
For
循环,它如下所示:

int j = 9;
for(int i=0; i<10; i++)  
  j--;
intj=9;

对于(inti=0;i=0&&i我喜欢这个非常简单的定义:()

循环不变量是[在程序变量之间]的一种条件,它在循环的每次迭代之前和之后都必须是真的(注意,在迭代的一部分,这并没有说明它的真或假)

循环不变量本身作用不大。但是,如果给定适当的不变量,它可以用来帮助证明算法的正确性。CLRS中的简单示例可能与排序有关。例如,让循环不变量类似,在循环开始时,此数组的第一个
i
项是sorterd、 如果您可以证明这确实是一个循环不变量(即,它在每次循环迭代之前和之后都保持不变),您可以用它来证明排序算法的正确性:在循环结束时,仍然满足循环不变量,计数器
i
是数组的长度。因此,对第一个
i
项进行排序意味着对整个数组进行排序

一个更简单的例子:


我对循环不变量的理解是,它是一种系统的、形式化的工具,用于对程序进行推理。我们只做了一个声明,我们专注于证明它是正确的,我们称之为循环不变量。这就组织了我们的逻辑。虽然我们也可以非正式地讨论某些算法的正确性,但使用循环不变量会迫使我们非常认真地思考仔细考虑并确保我们的推理是严密的。

应该注意的是,循环不变量可以帮助设计迭代算法,当考虑到一个断言时,该断言表示变量之间的重要关系,该关系在每次迭代开始时和循环终止时必须为真。如果这个断言成立,则计算在t上有效性之路。如果错误,则算法失败。

除了所有好的答案之外,我想杰夫·爱德蒙的《如何思考算法》中的一个很好的例子可以很好地说明这个概念:

示例1.2.1“查找最大双指算法”

1) 规范:一个输入实例由一个列表L(1..n)组成 元素。输出由索引i组成,使得L(i)具有最大值 价值如果有多个条目具有相同的值,则 其中一个被退回

2) 基本步骤:选择两指法。你的右手手指 列出清单

3) 衡量进步:衡量进步的标准是沿着道路走多远 列出你的右手手指是什么

4)循环不变式:循环不变式表示,您的左手手指指向用户迄今为止遇到的最大条目之一 右手指

5) 主要步骤:每次迭代,您将右手手指向下移动一个 列表中的条目。如果你的右手手指现在指向一个入口 这比左手手指的入口大,然后向左移动 手指要和你的右手手指在一起

6) 取得进展:你取得进展是因为你的右手手指在动 一个条目

7)保持循环不变量:您知道循环不变量已按如下方式保持。对于每个步骤,新的左指元素 是Max(旧的左指元素,新元素)。根据循环不变量, 这是Max(Max(较短列表),新元素)。数学上,这是 最大值(较长列表)

8)建立循环不变量:首先通过将两个手指指向第一个元素来建立循环不变量

9) 退出条件:当你的右手手指完成时,你就完成了 遍历列表

10) 结尾:最后,我们知道问题的解决方法如下。通过 在退出条件下,您的右手手指遇到了所有 条目。根据循环不变量,您的左手手指指向最大值 其中之一。返回此条目

11) 终止和运行时间:所需的时间是恒定的 乘以列表的长度

12) 特殊情况:检查有多个条目时会发生什么情况 具有相同的值或当n=0或n=1时

13) 编码和实现细节:

14) 形式证明:算法的正确性遵循 以上步骤


有一件事很多人在处理循环和不变量时没有马上意识到。它们混淆了循环不变量和循环条件(控制循环终止的条件)

正如人们指出的,循环不变量必须为真

  • 在循环开始之前
  • 在循环的每次迭代之前
  • 循环终止后
  • (尽管在循环体期间它可能暂时为false)。另一方面,循环终止后,循环条件必须为false,否则循环将永远不会终止

    因此,循环不变量和循环条件必须是不同的条件

    复杂循环不变量的一个好例子是用于二进制搜索

    bsearch(type A[], type a) {
    start = 1, end = length(A)
    
        while ( start <= end ) {
            mid = floor(start + end / 2)
    
            if ( A[mid] == a ) return mid
            if ( A[mid] > a ) end = mid - 1
            if ( A[mid] < a ) start = mid + 1
    
        }
        return -1
    
    }
    
    b搜索(类型A[],类型A){
    起点=1,终点=长度(A)
    而(开始a)结束=中间-1
    如果(A[mid]
    因此,循环条件似乎非常简单——当开始>结束时
    if ( A[mid] == a ) then ( start <= mid <= end )
    
    INSERTION-SORT(A)
        for j ← 2 to length[A]
            do key ← A[j]
            // Insert A[j] into the sorted sequence A[1..j-1].
            i ← j - 1
            while i > 0 and A[i] > key
                do A[i + 1] ← A[i]
                i ← i - 1
            A[i + 1] ← key
    
    for(int i=0; i<10; i++)
    { }