LEARNING JOURNAL
把理解,连成一张地图.
从一个概念出发,留下追问、延伸和写过的文章。
2026 年 10 月 13—14 日的编程基础讨论及迭代与递归系列。概念来自讨论与文章中的展开,“已讨论”记录触及过的内容,“已复盘”由你主动标记。
自上而下看概念延伸 · 点击节点查看文章与复盘问题
已复盘 0 / 26 个概念循环与迭代
从控制下一轮,到解释总工作量
递归与调用栈
从函数调用,到理解尚未完成的状态
递推与深度分析
把正确性、累计工作与峰值状态分开
尾递归与优化
从累加器到运行时的实现边界
递归树与记忆化
沿调用树识别重复子问题
显式栈与算法取舍
保存未完成的动作,再比较实际成本
按概念查看全部文章与复盘问题
for 与 while
for 从迭代器取下一项;while 在每轮开始前检查条件。选用依据是控制机制和可读性。
复盘问题:不查资料,说明两种循环由谁决定下一轮,并各给出一个适用场景。
迭代
重复执行某些步骤是迭代过程,循环语句是实现它的控制结构;每轮数据和状态可以改变。
复盘问题:解释迭代、循环和遍历的关系,给出一个不需要遍历容器的迭代例子。
状态与退出条件
步长、状态更新、条件检查和提前退出相互配合。条件存在,还必须能在有限步内到达。
复盘问题:写一个动态步长循环;说明 continue 跳过状态更新时可能发生什么。
可迭代对象
可迭代对象提供获取迭代器的能力;for 无需先统计元素总数。
复盘问题:说明 range(3) 与 iter(range(3)) 的区别,并解释逐行读文件为何不需要预先统计行数。
嵌套循环
循环体中还可以包含循环,但缩进层数不能直接决定时间复杂度。
复盘问题:构造一个两层嵌套但只有线性总工作量的例子。
迭代器
保存逐项获取的进度,提供下一项,并用 StopIteration 表示耗尽。迭代范围比迭代器协议更广。
复盘问题:用自己的话区分“重复执行步骤”与“按需提供下一项数据”。
实际执行次数
按实际行为计算乘积或求和,检查内层状态是否重置、是否跨轮复用,以及是否提前退出。
复盘问题:推导 n²、3n 和 n(n−1)/2 的次数关系;把 n 改成 10 和 100 运行核验。
迭代器与递归
继续区分迭代器这种对象协议与递归这种调用组织方式。该追问已讨论,尚未整理成独立文章。
复盘问题:解释这两个概念为何不能简单一一对应;思考迭代器内部能否使用递归。
这个追问已讨论,尚未整理成独立文章。
时间与空间复杂度
总成本还取决于单次操作。倍增推进可以产生 n log n;一层显式循环也可能是平方复杂度。
复盘问题:分别说明共享进度、倍增推进和循环中调用 sum 的总成本;再单独分析额外空间。
递归
把问题转化为同类型的子问题,通过新的调用解决子问题,再继续当前层尚未完成的工作。
复盘问题:以 factorial(3) 为例,指出基础情形、递归调用及当前层还剩下的工作。
调用栈
保存尚未完成的调用状态。普通递归中,上层调用等待子调用返回后再继续。
复盘问题:画出 factorial(3) 到基础情形时尚未结束的调用,再按返回顺序逐层移除。
栈帧与执行状态
每个尚未结束的调用需要保留参数、局部状态和恢复位置;同一函数可对应多份调用状态。
复盘问题:指出一份调用状态至少需要哪些信息;解释只保留一份为何无法正确逐层返回。
独立局部状态
每次调用有自己的局部变量绑定;局部变量独立,不代表引用的对象一定独立。
复盘问题:解释不同调用中的 n 为何互不覆盖,再给出不同局部变量引用同一个列表的例子。
返回与恢复位置
子调用返回后,调用者从暂停的表达式继续;如何使用返回值,取决于调用所在的语句。
复盘问题:追踪 child = factorial(n−1) 的求值和绑定顺序;与 return n * factorial(n−1) 比较。
多个未结束调用
尚未结束不等于同时运行。在单线程的普通递归中,通常是当前子调用执行,上层等待。
复盘问题:分别指出“当前执行的调用”和“等待中的调用”,解释为什么这不等同于多线程并行。
递推关系
S(n)=n+S(n−1) 说明当前答案怎样依赖较小问题。
复盘问题:建议练习:推导 S(3),说明每层负责的工作。
基本情况与输入契约
终止条件必须对允许的输入可到达,且给出最小问题的正确答案。
复盘问题:建议练习:比较 n==0 与 n==1 两种基本情况的允许输入。
调用总数与峰值深度
累计进入次数决定工作量,当前未完成路径决定调用栈峰值。
复盘问题:建议练习:分别数求和与斐波那契的累计调用和峰值深度。
尾递归
子调用的结果直接成为当前调用结果,返回后没有待完成的计算。
复盘问题:建议练习:判断 return n + solve(n−1) 为何不属于尾递归。
累加器与不变量
把已完成结果作为下一层参数,用 acc+S(n) 核对总目标。
复盘问题:建议练习:追踪 (3,0) 到 (0,6),说明什么始终保持不变。
尾调用优化边界
代码形式和运行时优化分开判断;CPython 不优化用户函数尾调用。
复盘问题:建议练习:解释尾递归形式为什么仍会增加 CPython 调用深度。
递归树
节点对应一次调用,整棵树记录累计过程,不是单次调用栈快照。
复盘问题:建议练习:画出 fib(5) 的九个节点与一个四层调用栈。
重复子问题
相同参数在不同调用分支重复出现,不会自动复用已有答案。
复盘问题:建议练习:指出两个 fib(3) 的共同答案和重复工作。
记忆化
缓存减少重复求解,递归深度、缓存容量和失效规则仍需独立分析。
复盘问题:建议练习:说明缓存如何减少 fib(6) 的实际求解次数。
显式栈与继续阶段
程序保存参数与待完成动作,expanded 标记模拟返回后的继续位置。
复盘问题:建议练习:解释后序遍历为何依次压当前、右子树、左子树。
实现方式的取舍
以结果顺序、最深路径、状态数量和维护成本选择实现方式。
复盘问题:建议练习:比较直接累加、递归、显式栈分别需要保存什么。
THE PATH SO FAR
讨论怎样一步步展开
按可确认的讨论顺序记录;与上方的概念关系一起看,更容易找回当时的问题。
- 01
- 02
- 03
- 04
继续追问迭代器
迭代器来自迭代的概念吗?为什么没有对称的递归器?
已讨论 · 待整理成文章 - 05
- 06