python-产生二叉树的所有从根到叶的分支

前端之家收集整理的这篇文章主要介绍了python-产生二叉树的所有从根到叶的分支 前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

抱歉,这是一个常见问题,但是我没有针对我的特定问题找到合适的答案.我正在尝试实现一种walk方法,该方法将二叉树从其根节点移动到其每个叶节点,并在到达叶节点时产生从根到叶的路径.例如,遍历由以下表示的二叉树:

  1. __a__
  2. / \
  3. b d
  4. / \ / \
  5. - c - -

将产生:

  1. ['a','b','c']
  2. ['a','d']

我的想法是BinaryTree.walk在根节点上调用Node.traverse,而后者又递归地调用每个子节点的traverse方法. BinaryTree.walk还创建一个空列表,该列表随每个遍历调用一起传递,附加每个节点的数据,一旦到达叶节点就产生该列表,并在访问每个节点后将每个元素从列表中弹出.

在某些时候,尽管出了点问题.这是我的代码

  1. class Node:
  2. def __init__(self,data=None,left=None,right=None):
  3. self.data = data
  4. self.left = left
  5. self.right = right
  6. def __repr__(self):
  7. return f"{self.__class__.__name__}({self.data})"
  8. @property
  9. def children(self):
  10. return self.left,self.right
  11. def traverse(self,branch):
  12. print('ON NODE:',self)
  13. branch.append(self.data)
  14. if self.left is None and self.right is None:
  15. yield branch
  16. else:
  17. for child in self.children:
  18. if child is not None:
  19. print('ENTERING CHILD:',child)
  20. child.traverse(branch=branch)
  21. print('EXITING CHILD:',child)
  22. branch.pop()
  23. class BinaryTree:
  24. def __init__(self,root=Node()):
  25. if not isinstance(root,Node):
  26. raise ValueError(f"Tree root must be Node,not {type(root)}")
  27. self.root = root
  28. def __repr__(self):
  29. return f"{self.__class__.__name__}({self.root})"
  30. def walk(self):
  31. node = self.root
  32. branch = []
  33. yield from node.traverse(branch=branch)
  34. if __name__ == '__main__':
  35. # create root node
  36. n0 = Node('A')
  37. # create binary tree with root node
  38. tree = BinaryTree(root=n0)
  39. # create others nodes
  40. n1 = Node(data='B')
  41. n2 = Node(data='C')
  42. n3 = Node(data='D')
  43. # connect nodes
  44. n0.left = n1
  45. n0.right = n3
  46. n1.right = n2
  47. # walk tree and yield branches
  48. for branch in tree.walk():
  49. print(branch)

预期产量:

  1. ON NODE: Node(A)
  2. ENTERING CHILD: Node(B)
  3. ON NODE: Node(B)
  4. ENTERING CHILD: Node(C)
  5. ON NODE: Node(C)
  6. ['A','B','C'] # yielded branch
  7. EXITING CHILD: Node(C)
  8. EXITING CHILD: Node(B)
  9. ENTERING CHILD: Node(D)
  10. ON NODE: Node(D)
  11. ['A','D'] # yielded branch
  12. EXITING CHILD: Node(D)

实际输出

  1. ON NODE: Node(A)
  2. ENTERING CHILD: Node(B)
  3. EXITING CHILD: Node(B)
  4. ENTERING CHILD: Node(D)
  5. EXITING CHILD: Node(D)
  6. IndexError: pop from empty list

我知道我对列表做错了,因为它在空时尝试弹出,但是我不明白它是怎么做到的.它应该为每个追加调用调用一次pop.

我也无法弄清楚为什么要输入和退出节点,但是没有显示ON NODE:消息…就像我的代码以某种方式跳过child.traverse(branch = branch)行一样?

谁能帮助我了解我在哪里搞砸了?

在此先感谢您的帮助!

最佳答案
这是您的代码修改后的变体.

code.py:

  1. #!/usr/bin/env python3
  2. import sys
  3. class Node:
  4. def __init__(self,right=None):
  5. self.data = data
  6. self.left = left
  7. self.right = right
  8. def __repr__(self):
  9. return f"{self.__class__.__name__}({self.data})"
  10. @property
  11. def children(self):
  12. if self.left:
  13. yield self.left
  14. if self.right:
  15. yield self.right
  16. @property
  17. def is_leaf(self):
  18. return self.left is None and self.right is None
  19. def traverse_preord(self,accumulator=list()):
  20. print(" On node:",self)
  21. accumulator.append(self.data)
  22. if self.is_leaf:
  23. yield accumulator
  24. else:
  25. for child in self.children:
  26. print(" Entering child:",child)
  27. yield from child.traverse_preord(accumulator=accumulator)
  28. accumulator.pop()
  29. print(" Exiting child:",child)
  30. def main():
  31. root = Node(data="A",left=Node(data="B",right=Node(data="C")
  32. ),right=Node(data="D",#left=Node(data="E"),#right=Node(data="F"),)
  33. )
  34. for path in root.traverse_preord():
  35. print("Found path:",path)
  36. if __name__ == "__main__":
  37. print("Python {:s} on {:s}\n".format(sys.version,sys.platform))
  38. main()

笔记:

>我对代码进行了一些重构(简化,更改了一些标识符名称,文本和其他无关紧要的更改)
>儿童财产:

>节点的left或right属性为None,表示该节点没有子节点,因此在返回的结果中没有将其包括在内的任何点
>由于问题涉及产量,因此我将其变成了生成器(而不是返回元组或列表,…).结果,我必须添加is_leaf,因为生成器的结果不会为False(即使为空)

输出

06001

您的代码有什么问题?

这是遍历重复调用(child.traverse(branch = branch)).它创建了一个生成器,但是由于没有在任何地方使用(迭代)该生成器,因此该函数实际上并未调用自身,从而导致尝试删除的元素多于添加的元素(只有1:这是根节点).因此,事实证明您已经快到了.您所要做的就是在其前面添加一个产量:).有关[Python]: PEP 380 — Syntax for Delegating to a Subgenerator的更多详细信息.

猜你在找的Python相关文章