在二叉搜索树中产生数据成员

时间:2019-03-01 15:40:38

标签: python binary-search-tree

我正在尝试为我的二进制搜索树实现一个迭代器。为了实现这一点,我试图对树进行有序遍历并产生每个单独的数据成员。这将允许我遍历树的每个项目。

我的功能:

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'

3 个答案:

答案 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]