python - 二叉树和的循环不变量
问题描述
我想为下面的一段代码找到一个循环不变量,我似乎无法弄清楚这段代码中呈现的任何类型的关系。
该算法的目标是找到二叉树中所有元素的总和。它将节点存储在一个名为 的堆栈中s
。
def TreeSum(root):
res = 0
s.push(root)
while s.size > 0:
node = s.pop()
res = res + node.num
if node.right != None:
s.push(node.right)
elif node.left != None:
s.push(node.left)
return res
我注意到这res
是所有当前节点的父节点及其父节点左侧的总和,但我不知道如何将其表述为循环不变量。
解决方案
该算法应该计算二叉树中数字的总和。为了证明它的正确性,有两个重要的事实需要证明:首先它确实计算了它访问的节点的总和,其次它访问了每个节点一次。因此,我们需要找到至少两个不变量,一个用于证明这些事实中的每一个。
为了更正式地讨论“已访问”或“未访问”节点,让我们在算法中添加几行代码,以跟踪“已访问”节点列表。这些行显然不会改变算法的行为,因为visited
只写入,从不读取:
def TreeSum(root):
res = 0
s = Stack()
s.push(root)
visited = [] # added line to simplify proof
while s.size > 0:
node = s.pop()
visited.append(node) # added line to simplify proof
res = res + node.num
if node.right != None:
s.push(node.right)
elif node.left != None:
s.push(node.left)
return res
我还添加了算法所必需的一行,让它s
成为一个新堆栈,否则要么s
没有定义,要么如果它是一个全局变量,那么我们不能保证在算法启动时它是空的。
所需的不变量如下:
res
等于a.num
for的总和a in visited
。- 对于所有节点
a in visited
,以及c not in visited
作为 的后代的所有节点a
,c in s
或者有一个唯一的节点b in s
,它b
是 的后代a
和祖先c
。 - 要么
root in s
要么root in visited
。
需要第三个不变量来得出结论,visited
当循环终止时包含每个节点,因此这res
是每个节点的总和。没有这个,其他两个不变量在visited
为空且res
为 0 时得到满足,但第三个不变量允许我们拒绝这种可能性。
推荐阅读
- python - 如何使用 Marshmallow / SQLAlchemy 仅将外键加载到嵌套字段中
- javascript - javascript中的删除运算符如何工作?
- c++ - 将向量分配给另一个向量后缺少元素
- python-3.x - 寻找有关如何更有效地清理 Web api 返回的 Python NoneType 值的建议
- angular - Angular 9:更新对象属性时重新渲染 ngFor
- excel - 删除 excel 列的每个单元格中的特定单词列表
- htmx - htmx:如何使每一行表现得像一个表格?
- ios - cordova 平台 ios 不考虑 confi.xml 首选项
- c++ - CUDA 和 C++ 之间的 static_casting 行为不一致
- html - 响应式电子邮件 - 在 gmail 应用程序 (iOs) 中隐藏图像