【问题标题】:Loop invariant for the sum of a binary tree二叉树和的循环不变量
【发布时间】:2019-11-03 21:45:05
【问题描述】:

我想为下面这段代码找到一个循环不变量,我似乎无法弄清楚这段代码中呈现的任何类型的关系。

此算法的目标是找到二叉树中所有元素的总和。它将节点存储在一个名为 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 是所有当前节点的父节点及其父节点左侧的总和,但我不知道如何将其表述为循环不变量。

【问题讨论】:

    标签: python proof correctness loop-invariant proof-of-correctness


    【解决方案1】:

    这个算法应该计算二叉树中数字的总和。为了证明它的正确性,有两个重要的事实需要证明:首先它确实计算了它访问的节点的总和,其次它访问了每个节点一次。因此,我们需要找到至少两个不变量,一个用于证明这些事实。

    为了更正式地讨论“已访问”或“未访问”节点,让我们在算法中添加几行代码,以跟踪“已访问”节点列表。这些行显然不会改变算法的行为,因为 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 没有定义或者如果它是一个全局变量,那么我们不能保证算法开始时它是空的。

    需要的不变量如下:

    1. res 等于 a.numa in visited 的总和。
    2. 对于所有节点a in visited,以及作为a 后代的所有节点c not in visitedc in s 或存在唯一节点b in s 使得ba 的后代,并且c 的祖先。
    3. root in sroot in visited

    需要第三个不变量来推断visited 包含循环终止时的每个节点,因此res 是每个节点的总和。没有这个,当visited 为空且res 为0 时,其他两个不变量得到满足,但第三个不变量允许我们拒绝这种可能性。

    【讨论】:

      猜你喜欢
      • 2015-05-16
      • 1970-01-01
      • 1970-01-01
      • 2017-12-07
      • 1970-01-01
      • 1970-01-01
      • 2015-01-07
      • 1970-01-01
      • 2011-09-16
      相关资源
      最近更新 更多