【问题标题】:problem with list in recursion for traversing binary tree遍历二叉树的递归列表问题
【发布时间】:2020-05-21 09:26:11
【问题描述】:

我正在尝试使用递归来遍历二叉树。每棵树要么有两个孩子,要么没有孩子(即为孩子保留的字段== None)

我想将每个分支的最终叶子(即,每个节点的两个孩子 == 无)添加到列表中,并返回列表。我正在使用“搜索”功能和助手“search_base”功能来执行此操作。

通过调试器,我看到“搜索”函数中的列表确实包含我想要的元素。但是,当它在 search_base 函数中返回时,结果似乎是一个空列表。

我非常困惑,如果能提供任何帮助,我将不胜感激。谢谢!

class Node:
    def __init__(self, data, pos = None, neg = None):
        self.data = data
        self.positive_child = pos
        self.negative_child = neg   

class Diagnoser:
    def __init__(self, root):
        self.root = root

    def search_base(self):
        leaf_list=[]
        current = self.root
        return self.search(current, leaf_list)

    def search(self, current, leaf_list):
        if(current.positive_child == None):
            leaf_list.append(current)
            return leaf_list
        else:
            self.search(current.positive_child, leaf_list)
            self.search(current.negative_child, leaf_list)


if __name__ == "__main__":

    # Manually build a simple tree.
    #                cough
    #          Yes /       \ No
    #        fever           healthy
    #   Yes /     \ No
    # influenza   cold

    flu_leaf = Node("influenza", None, None)
    cold_leaf = Node("cold", None, None)
    inner_vertex = Node("fever", flu_leaf, cold_leaf)
    healthy_leaf = Node("healthy", None, None)
    root = Node("cough", inner_vertex, healthy_leaf)

    diagnoser = Diagnoser(root)
    leaf_list = diagnoser.search_base()
    print(leaf_list[0].data)

【问题讨论】:

  • 顺便说一句,您应该使用is None 而不是== NoneExplained here.
  • search 并不总是返回一些东西,所以 return self.search(current, leaf_list) 有时会返回 None。

标签: python recursion binary-tree


【解决方案1】:

这是一个更简单且没有副作用的解决方案:

class Node:
    def __init__(self, data, pos=None, neg=None):
        self.data = data
        self.positive_child = pos
        self.negative_child = neg

    def leaves(self):
        if self.positive_child is self.negative_child is None:
            return [self]
        else:
            return (self.positive_child.leaves() +
                    self.negative_child.leaves())


if __name__ == "__main__":
    # Manually build a simple tree.
    #                cough
    #          Yes /       \ No
    #        fever           healthy
    #   Yes /     \ No
    # influenza   cold

    flu_leaf = Node("influenza", None, None)
    cold_leaf = Node("cold", None, None)
    inner_vertex = Node("fever", flu_leaf, cold_leaf)
    healthy_leaf = Node("healthy", None, None)
    root = Node("cough", inner_vertex, healthy_leaf)
    for leaf in root.leaves():
        print(leaf.data)

【讨论】:

    【解决方案2】:

    问题是在

    self.search(current.positive_child, leaf_list)
    self.search(current.negative_child, leaf_list)
    

    这些语句的返回值没有保存或返回,所以这里函数给出None。此外,传递给这两个语句的 leaf_list 是相同的,即它们不会被连接。在递归函数中,最好不要产生副作用以确保其安全。 应该是:

     def search(self, current, leaf_list=[]):
            if(current.positive_child == None):
                return [current]
            else:
                return (self.search(current.positive_child, leaf_list)
                        + self.search(current.negative_child, leaf_list))
    

    【讨论】:

    • "这里的第一行返回,所以第二行永远不会执行。"第一行没有返回。
    • 另外,追加和连接都会导致多个节点重复,至少在 OP 的 search_base 实现中是这样。
    • 是的,我的描述不准确。我试图说明的是,这些值永远不会返回。编辑以反映这一点
    • 不只是描述,代码错误。测试一下。
    • 已修复,if 语句的其他部分不应返回整个列表
    【解决方案3】:

    由于search修改了列表,所以不需要返回任何内容,search_base只返回修改后的列表即可。

    class Diagnoser:
        def __init__(self, root):
            self.root = root
    
        def search_base(self):
            leaf_list = []
            current = self.root
            self.search(current, leaf_list)
            return leaf_list
    
        def search(self, current, leaf_list):
            if current.positive_child is None:
                leaf_list.append(current)
            else:
                self.search(current.positive_child, leaf_list)
                self.search(current.negative_child, leaf_list)
    

    另外,您需要检查两个孩子是否都不见了,即

    if current.positive_child is None and current.negative_child is None:
    

    【讨论】:

    • 这成功了!谢谢!我知道我不需要返回leaf_list。但是,为什么这样做会给我一个错误的答案?
    • @Tova 查看我的其他评论。
    • 我认为在我们的回答中,我们找到了最好的解决方案。当递归函数是“纯函数”即没有副作用并返回值时,函数的退出点会更加清晰。
    猜你喜欢
    • 1970-01-01
    • 2019-08-23
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    • 2013-07-23
    • 2016-05-01
    • 1970-01-01
    相关资源
    最近更新 更多