在 Python 中使用迭代而不是递归遍历二叉树
Traversing binary tree using iteration instead of recursion in Python
在下面的二叉树中,只有叶子保持值,没有内部节点保持值。我使用 recursion:
实现了遍历(计算保留值的总和)
class Node:
def new(rep):
if type(rep) is list:
left = Node.new(rep[0])
right = Node.new(rep[1])
return Internal(left, right)
else:
return Leaf(rep)
class Leaf(Node):
def __init__(self, val):
self.val = val
def sum_leaves(self, sum):
return sum + self.val
class Internal(Node):
def __init__(self, left, right):
self.left = left
self.right = right
def sum_leaves(self, sum):
return self.right.sum_leaves(self.left.sum_leaves(sum))
class Tree:
def __init__(self, rep):
self.root = Node.new(rep)
# Traverse the tree and return the sum of all leaves
def sum_leaves(self):
return self.root.sum_leaves(0)
treerep = [[3, [5, -1]], [[1, 7], [2, [3, [11, -9]]]]]
tree = Tree(treerep)
print(tree.sum_leaves())
这种情况下的输出是:
22
如何使用 迭代 而不是 sum_leaves
方法的递归?
您可以使用使用 while 循环的深度优先搜索:
class Tree:
def __init__(self, rep):
self.root = Node.new(rep)
def sum_dfs(self):
sum = 0
stack = [self.root]
while len(stack):
node = stack.pop()
if isinstance(node, Internal):
stack.append(node.left)
stack.append(node.right)
elif isinstance(node, Leaf):
sum += node.val
return sum
集合中的 deque 对象可以非常有效地实现 "manual" 堆栈,并且可以帮助进行这种遍历。我建议定义一个迭代器方法,该方法将使用循环(和双端队列)遍历层次结构,然后使用该方法实现 sum_leaves() 方法。
from collections import deque
def traverse(self,condition=None): # on the Node class
nodes = deque([self])
while nodes:
node = nodes.popleft()
if not condition or condition(node): yield node
if node.isLeaf: continue
if node.left: nodes.append(node.left)
if node.right: nodes.append(node.right)
@property
def isLeaf(self): isinstance(self,Leaf) # on the Node class
def sum_leaves(self): # on the Node class
return sum(n.val for n in self.traverse(lambda n:n.isLeaf))
def sum_leaves(self): # on the Tree class
return self.root.sum_leaves()
我相信如果你不在3个不兼容的类中分离树结构,代码中的异常会少很多。所有节点(包括本身应该是根的树)应该能够有一个左,右和值属性(至少在签名级别)。
你甚至可以尝试技巧。
import re
treerep = [[3, [5, -1]], [[1, 7], [2, [3, [11, -9]]]]]
p = re.compile('(\[|\]|,)')
treerep = p.sub('', str(treerep))
treerep = [int(i) for i in treerep.split()]
sum(treerep)
容易))
在下面的二叉树中,只有叶子保持值,没有内部节点保持值。我使用 recursion:
实现了遍历(计算保留值的总和)class Node:
def new(rep):
if type(rep) is list:
left = Node.new(rep[0])
right = Node.new(rep[1])
return Internal(left, right)
else:
return Leaf(rep)
class Leaf(Node):
def __init__(self, val):
self.val = val
def sum_leaves(self, sum):
return sum + self.val
class Internal(Node):
def __init__(self, left, right):
self.left = left
self.right = right
def sum_leaves(self, sum):
return self.right.sum_leaves(self.left.sum_leaves(sum))
class Tree:
def __init__(self, rep):
self.root = Node.new(rep)
# Traverse the tree and return the sum of all leaves
def sum_leaves(self):
return self.root.sum_leaves(0)
treerep = [[3, [5, -1]], [[1, 7], [2, [3, [11, -9]]]]]
tree = Tree(treerep)
print(tree.sum_leaves())
这种情况下的输出是:
22
如何使用 迭代 而不是 sum_leaves
方法的递归?
您可以使用使用 while 循环的深度优先搜索:
class Tree:
def __init__(self, rep):
self.root = Node.new(rep)
def sum_dfs(self):
sum = 0
stack = [self.root]
while len(stack):
node = stack.pop()
if isinstance(node, Internal):
stack.append(node.left)
stack.append(node.right)
elif isinstance(node, Leaf):
sum += node.val
return sum
集合中的 deque 对象可以非常有效地实现 "manual" 堆栈,并且可以帮助进行这种遍历。我建议定义一个迭代器方法,该方法将使用循环(和双端队列)遍历层次结构,然后使用该方法实现 sum_leaves() 方法。
from collections import deque
def traverse(self,condition=None): # on the Node class
nodes = deque([self])
while nodes:
node = nodes.popleft()
if not condition or condition(node): yield node
if node.isLeaf: continue
if node.left: nodes.append(node.left)
if node.right: nodes.append(node.right)
@property
def isLeaf(self): isinstance(self,Leaf) # on the Node class
def sum_leaves(self): # on the Node class
return sum(n.val for n in self.traverse(lambda n:n.isLeaf))
def sum_leaves(self): # on the Tree class
return self.root.sum_leaves()
我相信如果你不在3个不兼容的类中分离树结构,代码中的异常会少很多。所有节点(包括本身应该是根的树)应该能够有一个左,右和值属性(至少在签名级别)。
你甚至可以尝试技巧。
import re
treerep = [[3, [5, -1]], [[1, 7], [2, [3, [11, -9]]]]]
p = re.compile('(\[|\]|,)')
treerep = p.sub('', str(treerep))
treerep = [int(i) for i in treerep.split()]
sum(treerep)
容易))