我正在尝试为我的二进制搜索树实现一个迭代器。为了实现这一点,我试图对树进行有序遍历并产生每个单独的数据成员。这将允许我遍历树的每个项目。
我的功能:
def __iter__(self):
"""
in-order traversal of a binary search tree
"""
if self.root is not None:
self.check(self.root)
def check(self, cur_node):
if cur_node is not None:
self.check(cur_node.left)
yield cur_node.data #if I were to print this data member, it would be fine
self.check(cur_node.right)
使用
等迭代测试此功能时for i in tree:
我收到此错误:
TypeError: iter() returned non-iterator of type 'NoneType'
答案 0 :(得分:5)
要实现递归生成器,您不能只是“调用”自己,您需要提取元素并产生它们。
Python为此具有特殊的语法:
yield from expr
其中expr
可以迭代,并且可以看作是其中的简写
for x in expr:
yield x
使用此方法,您可以通过以下方式实现对树的有序遍历:
class Node:
def __init__(self, data, left, right):
self.data = data
self.left = left
self.right = right
def __iter__(self):
if self.left:
yield from self.left
yield self.data
if self.right:
yield from self.right
答案 1 :(得分:2)
线索是
iter()返回了...。
因此,您需要返回一个迭代器。您的课程是一个迭代器,所以返回self
def __iter__(self):
"""
in-order traversal of a binary search tree
"""
if self.root is not None:
self.check(self.root)
return self
您可能还应该实现__next__
才能真正产生该值。
所以解决方案可能看起来像
class Tree:
def __init__(...): ...
def __iter__(self):
return self
def __next__(self):
if self.left is not None:
yield from self.left
yield self.data
if self.right is not None:
yield from self.right
您在此处使用yield from
来委托给子节点。参见https://docs.python.org/3/whatsnew/3.3.html#pep-380-syntax-for-delegating-to-a-subgenerator
实际上,您确实需要三个yield语句,因为您需要遍历左右两个子节点,并产生当前节点的值。
答案 2 :(得分:2)
通常,您希望迭代器是与数据结构分离的单独实体,因此您可以在数据上具有多个迭代器,从而可以对数据进行多次迭代。下面,我展示了如何为基本的BST类实现简单的DFS算法。
class Node:
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
def __iter__(self):
return BSTIterator(self)
class BSTIterator:
def __init__(self, root):
self.stack = []
curr = root
while curr:
self.stack.append(curr)
curr = curr.left
def __next__(self):
if not self.stack:
raise StopIteration()
node = self.stack.pop()
val = node.val
node = node.right
while node:
self.stack.append(node)
node = node.left
return val
def __iter__(self):
return self
root = Node(5, Node(3, Node(1), Node(4)), Node(10, (Node(6, None, Node(7)))))
list(root)
# [1, 3, 4, 5, 6, 7, 10]