HarmonyFidelisHarmonyFidelis
登录
新闻重大项目人物与组织学院

算法:为查找最大值制定规格、执行过程并说明理由

从契约到证明:跟踪最大值查找,测试其限制,并区分方法、程序、正确性与终止性。

算法:为查找最大值制定规格、执行过程并说明理由

1. 目标、难度与先备知识

  • 定义算法允许的输入和必须提供的输出。
  • 使用变量、条件和循环跟踪最大值查找。
  • 说明正确性与终止性,并区分证明与测试。

算法描述一种明确的方法,用于将输入数据转化为结果。这里我们学习确定性算法,它们必须对每一种允许的输入都能终止。程序用机器能够执行的语言表达这样的方法;同一种方法可以对应多个程序。

完成本入门单元后,你将能够明确输入和预期输出,跟踪变量的值,并说明为什么查找最大值的过程能够终止并给出正确结果。这项能力用于验证一个过程,而不是轻信看似合理的输出。

难度:初级。只需能够比较整数,并阅读一个有顺序的数值序列,这里称之为列表。允许使用负数。不需要掌握任何编程语言:先在纸上开始。转为代码是一种应用,而不是隐藏的先决条件。

2. 先定义问题,再考虑方法

我们要找出一个有限、非空的整数列表中的最大值。输入可以包含重复值,不需要预先排序。输出是一个值,不是它的位置,也不是它出现的次数。对于 [3, 7, 7, 2],预期结果是 7。

“非空”是前置条件,用来明确允许的输入。后置条件表达结果必须满足的要求:输出属于该列表,且大于或等于列表中的每一个值。空列表没有可返回的最大值。如果一个过程也要接受这种情况,就应明确规定报错或其他结果,而不应凭空返回零。

3. 构造没有歧义的过程

保留一个名为 best 的候选值。用第一个值将其初始化,然后按顺序遍历其余值。如果当前检查的值严格大于 best,就用该值替换 best;否则保持不变。检查完最后一个值后,返回 best。

赋值会改变已存储的值:best ← x 的含义是“将 x 当前的值存入 best”。它不是一个永远成立的等式。条件用于选择要执行的操作,循环则对剩余值重复这些步骤。顺序、初始化和条件,与最终结果一样,都是方法的一部分。

best ← 列表的第一个值
对于第一个值之后的每一个值 x:
    如果 x > best:
        best ← x
返回 best

这是伪代码:它描述方法,却不限定某种语言的语法。不能将它原样粘贴到 Python 解释器中。

四个数值组成的列表及保存在记忆中的数值的概念插图。

借助人工智能生成的插图。它用于提示记忆的作用;精确的数值过程及其理由见正文和表格。

4. 跟踪一个已解例题

对于 [3, 7, 7, 2],初始化得到 best = 3。还剩三个值需要比较。

检查的值比较前的 bestx > best?比较后的 best
73是7
77否7
27否7

第二次出现的 7 不会改变最大值。恰好进行三次比较后,结果为 7。只有一个值时,循环不执行,直接返回该值。统计比较次数并不等于测量实际运行时间:运行时间还取决于程序和机器。

5. 说明正确性与终止性

每个步骤结束后,best 都是已经遍历部分的最大值。这种始终保持的性质称为不变式。它在开始时成立,因为已经遍历的部分仅包含第一个值。如果下一个值更大,用它替换候选值会保持这个性质;否则,保留候选值也会保持这个性质。结束时,已经遍历的部分就是整个列表,因此后置条件得到满足。

一个包含 n 个值的有限列表,在第一个值之后还剩 n − 1 个值。每一步处理其中一个,而且不往回走,所以剩余个数会不断减少,直到为零。这说明过程能够终止,且比较次数为 n − 1,即使所有值都相等也如此。用例测试能够揭示错误,但不能代替针对所有允许输入的这一论证。

6. 转写为 Python 程序

下面是针对非空整数列表的一种转写。values[0] 表示第一个值;range(1, len(values)) 遍历其后的索引。缩进界定循环和条件的范围。

PYTHON
def maximum(values):
    best = values[0]
    for i in range(1, len(values)):
        x = values[i]
        if x > best:
            best = x
    return best

这个函数假定前置条件已经满足。它并不是一个完整的输入验证接口:对于空列表,访问 values[0] 时会报错。缺失值、混合类型和无限列表不在所定义的问题范围内。复用前,应明确契约以及如何处理被拒绝的输入。此代码旨在帮助理解方法;在实践中,使用内置的最大值函数可能更合适。

7. 引导练习

跟踪最大值查找

对 [5, 1, 9, 3] 手动执行这一过程。制作表格,列出所检查的值、比较前的 best 和比较后的 best;注明输出与比较次数。

达成标准 : 跟踪记录用第一个值初始化 best,每个其余值检查一次,并解释每次比较中的决定。

引导解答,请在自行尝试后查看:候选值从 5 开始,检查 1、9、3 后,依次为 5、9、9。三次比较后输出为 9。每一行都应显示所检查的值、检查前的候选值和检查后的候选值;仅有正确的输出不足以解释推理过程。

8. 适度的项目

为过程制定规格并测试

对 [12, 8, 15, 15, 4] 写出前置条件和后置条件,跟踪最大值查找,并说明终止性。增加测试 [-4, -2, -9]、[6] 和 [3, 3]。解释计划如何处理空列表,以及为什么初始化为零存在危险。

达成标准 : 交付成果包含明确的契约、四份跟踪记录、不变式论证和结束理由,区分允许的输入与被拒绝的空列表。

先在纸上完成。如果随后使用程序,请将其输出与你的跟踪记录比较。在这几个案例中得到一致结果,只是一种有限的验证;同时也要保留不变式论证和终止性说明。交付成果是一份简短的规格说明,附有跟踪记录和测试,不收集个人数据。

9. 迁移能力评估

将方法迁移到最小值

调整该过程,使其查找一个有限、非空整数列表的最小值。给出伪代码,跟踪 [6, -1, 4, -1],并解释保持的性质与终止性。找出初始化为零的反例,然后说明为什么空列表仍然不在契约范围内。

达成标准 : 方法对所声明的整个范围都有效,处理重复值与单元素列表,区分测试与证明,并说明初始化、比较和结束的理由,而不是没有解释地复述记住的规则。

不看笔记,写出你的论证并解释每一个选择。然后将你的方法与查找最大值的方法比较:哪些步骤保留不变,哪一个判断发生了变化?

10. 限制与常见错误

将 best 初始化为零,看起来对某些正数列表有效,但在 [-4, -2, -9] 上会失败:程序会返回 0,而 0 甚至不属于输入。用第一个值初始化可以避免这一隐藏假设。单元素列表和重复值都属于允许的情况,并非异常。

列表的最大值既不是各值之和,也不一定是只在列表中出现一次的值。算法可以是正确的,而不必是唯一可行的方法。另一种方法可以先排序,再选取最后一个元素,但对于这一个问题而言,这增加了不必要的工作。本单元既没有证明任意过程都能终止,也没有证明任意程序都符合其方法;这两项性质各自需要相应的论证。

11. 总结、主动回忆与下一步

步骤如下:定义契约,选择方法,跟踪一个案例,说明所保持的性质和过程如何结束,然后验证转写。看似合理的输出不是一般性的证明。明天不重读内容,回答以下四个问题:

  1. 你如何区分算法与程序?
  2. 对于 [2, 5, 4],候选值依次取哪些值,进行了多少次比较?
  3. 为什么初始化为零会在某些输入上失败?
  4. 请向初学者解释,为什么该过程会在每个有限、非空列表上终止。

简短参考回答:方法与其转写不同;跟踪从 2 开始,变为 5 后保持为 5,共进行了两次比较。零错误地为各值设置了下界。尚待处理的元素个数每次减少一,直到为零。

建议的下一步:比较在列表中查找某个值与查找最大值。尚未指定后续课程:在图结构通过资格验证后,这一根单元仍可用于扩展课程体系。

12. 来源与编辑方法

本原创单元对照了两份独立的机构课程文件:法国 Première 年级的“Numérique et sciences informatiques”课程,2019 年 1 月 22 日 BO,附件第 8 页“Langages et programmation”和第 9 页“Algorithmique”;以及英格兰 2013 年 computing 课程中的“Key stage 2”和“Key stage 3”。上述来源已于 2026 年 10 月 12 日重新阅读。对应范围是规格说明、顺序、选择、重复、测试与论证;这并不认证对这些课程的完整覆盖。

正文、示例与活动是在人工智能的辅助下准备的。公开交付前,必须检查跟踪记录、计算案例以及八种语言版本。未声称存在学习收益,也未声称经过人工审查。