字典的递归工作问题

时间:2021-05-29 08:23:15

标签: python recursion tree binary-tree

我对递归有疑问。请帮助澄清我的疑问。

我有一个数据结构来存储二叉树节点:

 class Node:
        def __init__(self, key, left=None, right=None):
            self.data = key
            self.left = left
            self.right = right
    # Recursive function to print left view of given binary tree
    def printLeftView(root,level=0,leveldic={}):
        if root==None:
            return
        print(root.data,leveldic)
        if level not in leveldic:
            leveldic[level]=root.data
            print(root.data)
        printLeftView(root.left,level+1,leveldic)
        printLeftView(root.right,level+1,leveldic)
    
"""
                      1
                    /    \
                   2       3
                  /      /    \
                4      5      6
                       \       
                        8

"""
if __name__ == '__main__':
    root = Node(1)
    root.left = Node(2)
    root.right = Node(3)
    root.left.right = Node(4)
    root.right.left = Node(5)
    root.right.right = Node(6)
    root.right.left.right = Node(8)
    printLeftView(root)

输出:

> ​1 {}
>     1
>     2 {0: 1}
>     2
>     4 {0: 1, 1: 2}
>     4
>     3 {0: 1, 1: 2, 2: 4}
>     5 {0: 1, 1: 2, 2: 4}
>     8 {0: 1, 1: 2, 2: 4}
>     8
>     6 {0: 1, 1: 2, 2: 4, 3: 8}

怀疑:

为什么字典返回后不回到原来的状态?

即,打印 4 个字典后是

{0: 1, 1: 2, 2: 4}

并且由于它返回并且当回到节点3时,它应该在返回时回到之前的状态

{0: 1, 1: 3}

这没有发生,字典没有得到改变,它与节点 4 相同。

{0: 1, 1: 2, 2: 4}

可能是什么原因?

2 个答案:

答案 0 :(得分:1)

似乎字典参数不是字典的副本,而是在内存中引用它,所以当它应该回到节点 3 时,它使用旧键。你必须复制它。

def printLeftView(root,level=0,oldic={}):
    if root==None:
        return

    leveldic={} #making new dict
    for i in oldic:
        leveldic[i]=oldic[i] #and copying it values, to work on copy
    
    leveldic[level]=root.data
    print(root.data)
    print(root.data,leveldic)

    printLeftView(root.left,level+1,leveldic)
    printLeftView(root.right,level+1,leveldic)

答案 1 :(得分:1)

接受的答案不正确:它会产生错误的输出。

原始代码与算法应该工作的完全一样:所有递归执行上下文共享一个字典,并且它不应该从递归调用。如果你试图“修复”这个问题,你实际上会破坏算法,然后输出通常是错误的。

请注意,当您将字典对象作为参数传递给函数时,它不会被深度复制:函数将在新变量中获取参数,但它仍然是同一个字典。除非为该变量分配一个新值,否则该字典的任何变异都将指向该单个字典实例。

然而,您的代码还有另一个问题:默认参数值 leveldic={} 有问题。这个赋值只发生一次,这是 Python 特有的一种行为。这意味着如果您从主程序再次调用,您将仍然继续使用字典对象,就像上次调用后一样。

如果进行第二次调用,您将需要重置它:

def printLeftView(root, level=0, leveldic=None):
    if leveldic is None:
        leveldic = {}
    if root is None:
        return
    if level not in leveldic:
        leveldic[level] = root.data
        print(root.data)
    printLeftView(root.left, level + 1, leveldic)
    printLeftView(root.right, level + 1, leveldic)
相关问题