《算法基础:打开算法之门》一2.3 循环不变式

2.3 循环不变式

对于线性查找的3个算法,我们能很容易地看到每个算法均能生成正确的结果。但是有时候生成正确的结果看起来有点难。这涉及一系列技术,在这里不能一一讲解。

证明正确性的一个常用方法是使用循环不变式证明:即证明循环的每次迭代之前循环不变式为真。循环不变式能够帮助我们证明正确性,关于循环不变式,我们必须证明以下3条性质。

初始化:循环的第一次迭代之前,它为真。

保持:如果循环的每次迭代之前它为真,那么下次迭代之前它仍为真。

终止:循环终止时,当它确实终止时,伴随循环终止的原因,循环不变式为我们提供了一个有用的性质。以BETTERLINEARSEARCH算法为例,以下是一个循环不变式:

在第1步迭代开始时,如果数组A中存在x,那么x一定在A[i]~A[n]的子数组(数组的一段连续部分)中。我们甚至不需要循环不变式来证明如果程序返回了一个索引而非NOTFOUND,则被返回的索引是正确的:在第1A步中该程序能返回索引i的唯一方式是因为x等于A[i]。下面,我们使用循环不变式来证明如果程序是在第2步中返回NOTFOUND,那么数组中一定不包含x。初始化:初始时,i=1,因此循环不变式的子数组是A[1]~A[n],此时代表整个数组。保持:假定当前循环变量是i,在迭代开始时,如果数组A中包含x,那么它一定在从A[i]到A[n]的子数组中。如果执行这次循环迭代而没有返回值,我们能得出A[i]≠x,因此能确定地说如果x在数组A内,那么它一定出现在A[i+1]~A[n]的子数组内。因为i在下次迭代之前会自增1,21所以循环不变式在下次迭代之前仍为真。终止:循环一定会终止,或者因为程序会在第1A步返回,或者由于i>n。我们已经对程序因在第1A步返回而导致循环终止的情况进行了验证。为了处理因i>n而导致循环终止的情况,我们依据循环不变式的等价性来证明。命题“如果A那么B”的逆否命题是“如果非B那么非A”。一个命题为真当且仅当与它等价的命题也为真。该循环不变式的等价命题为“如果x没有出现在A[i]~A[n]的子数组中,那么数组A中就不存在x”。现在,当i>n时,A[i]~A[n]这个子数组为空。因此这个子数组中不可能包含x。因此,根据循环不变式的等价式,x不可能出现在数组A的任意位置上,因此第2步中返回NOTFOUND是恰当的。这一系列的推理仅仅是为了说明这么一个简单的循环?每次写一个循环时,我们都必须添加上述证明吗?我不会,但是针对每一个简单的循环,依旧有几个计算机科学家坚持这样严格的推理。在实际编程时,我发现在我写一个循环的大部分时间里,我会在头脑里想出循环不变式。它可能深藏在我的头脑中以至于我甚至没有意识到我的大脑里会存在该循环不变式,但是如果要求我必须陈述该循环不变式,我能够完整地将其表述下来。虽然我们中的大多数人认为循环不变式对于理解像BETTERLINEARSEARCH这样的简单循环没有必要,但是我们想要理解复杂的循环能够执行正确的操作时使用循环不变式会很方便。

时间: 2025-01-24 15:57:46

《算法基础:打开算法之门》一2.3 循环不变式的相关文章

《算法基础:打开算法之门》一导读

前言 Algorithms Unlocked 计算机是如何解决问题的呢?小小的GPS是如何只在几秒钟内就从无数条可能路径中找出到达目的地的最快捷路径的呢?在网上购物时,又如何防止他人窃取你的信用卡账号呢?解决这些问题,以及大量其他问题的答案均是算法.我写本书的目的就是为你打开算法之门,解开算法之谜. 我是<算法导论>的合著者之一.<算法导论>是一本特别好的书(当然,这是我个人的主观评价),但是它确实相当专业. 本书并不是<算法导论>,甚至不能被称为一本教材.它既没有对计

《算法基础:打开算法之门》一1.2 资源利用

1.2 资源利用 什么样的算法才能称为高效使用计算资源的算法呢?我们在讨论近似算法时提及了一个衡量效率的标准:时间.一个能给出正确输出但是会花费很长时间才能得出结果的算法可能是没有价值的.如果你的GPS需要一个小时才能计算出推荐的驾驶路线,你还会愿意打开GPS吗?诚然,一旦我们知道某算法能给出一个正确输出,时间便是我们用来衡量算法效率的主要方式.但是时间不是唯一的衡量标准.由于一个计算机算法必须能够在可用的内存空间上运行,因此我们可能还需要考虑该算法需要占用多大的计算机内存空间(它的"内存占用量

《算法基础:打开算法之门》一第3章 排序算法和查找算法

第3章 Algorithms Unlocked 排序算法和查找算法 在第2章中,我们看到了在数组上进行线性查找的三个算法.我们能做得更好吗?答案是:看情况.如果不清楚数组中的元素是否有序,我们是不可能做得更好的.在最坏情况下,我们必须查找数组的所有n个元素,因为如果在前n-1个元素中不能找到要找的值,那么要查找的元素可能在第n个位置上.因此,当我们不清楚数组中的元素是否有序时,我们不可能实现比Θ(n)更好的最坏情况运行时间. 然而,假定数组是以非递减顺序排序的,那么根据"非递减"的含义

《算法基础:打开算法之门》一2.1 如何描述计算机算法

2.1 如何描述计算机算法 将计算机算法描述成一个可执行程序可以有多种选择,例如使用通用的编程语言表示,像Java.C.C++.Python或Fortran.诚然,许多教科书上的算法都是这么表示的.但是使用实际的编程语言来表示算法所带来的问题是你可能会在语言细节上越陷越深,而对算法本身的认识反而模糊不清.另一种表示算法的方式是"伪代码",就像我们在<算法导论>中使用的一样,它听起来像是多种编程语言和英语的混合表示.如果你曾用一种实际的编程语言编写过程序,那么你就能很容易地搞

数据结构与算法系列(2)基础排序算法

前言 在计算机中实现存储数据最普遍的两种操作就是排序和查找.这是从计算机产业初始就已经确认的 了.这意味着排序和查找也是计算机科学领域最值得研究的两种操作.本书提到的许 多数据结构的主要设计目的就是为了使排序和/或查找更加简单,同时也是为了数据在结构内的存 储更加有效. 本章会介绍有关数据排序和查找的基础算法.这些算法仅依赖数组作为数据结构,而且所采用的 "高级"编程技术只是递归.本章还介绍了用来非正式分析不同算法之间速度与效率的方 法,此方法贯穿全书. 1.排序算法 人们在日常生活中

程序员必须知道的10大基础实用算法及其讲解

算法一:快速排序算法 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来. 快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists). 算法步骤: 1 从数列中挑出一个元素,称为 "

java-一道基础的算法,答案是什么?

问题描述 一道基础的算法,答案是什么? 看开始看算法(第四版) 第一张的一道练习 给出以下表达式的类型和值 d. 1+2+'3'**** 这个我觉得java是会自动转化为字符型吗? 我就自己println试验了一下. System.out.println(1+2+'3'); 结果为54,不懂了,求教. 但是我看了网上的答案是33?一样不懂 我已经知道了,题目中是我错误 原题是双引号,字符型 1+2+"3" 我看成1+2+'3'了.不过倒是加深了理解,谢谢各位 解决方案 带单引号的3是字

程序员必须知道的10大基础实用算法及其讲解(转)

  算法一:快速排序算法 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序n个项目要Ο(nlogn)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(nlogn)算法更快,因为它的内部循环(innerloop)可以在大部分的架构上很有效率地被实现出来. 快速排序使用分治法(Divideandconquer)策略来把一个串行(list)分为两个子串行(sub-lists). 算法步骤: 1从数列中挑出一个元素,称为"基准"(p

一道算法基础题 uva1586

问题描述 一道算法基础题 uva1586 题目链接在这儿 http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=830&page=show_problem&problem=4461 我自己做的代码如下 但是通不过 测了好多数据都没问题 #include<cstdio> #include<cstring> using namespace std; in

java 算法基础之二快速排序算法

http://www.cnblogs.com/hexiaochun/archive/2012/09/03/2668324.html java 算法基础之二快速排序算法 所谓的快速排序的思想就是,首先把数组的第一个数拿出来做为一个key,在前后分别设置一个i,j做为标识,然后拿这个key对这个数组从后面往前遍历,及j--,直到找到第一个小于这个key的那个数,然后交换这两个值,交换完成后,我们拿着这个key要从i往后遍历了,及i++;一直循环到i=j结束,当这里结束后,我们会发现大于这个key的值