简体   繁体   English

Python:不使用条件语句的二叉树遍历迭代器

[英]Python: binary tree traversal iterators without using conditionals

I am trying to create a module in python for iterating over a binary tree using the 4 standard tree traversals (inorder, preorder, postorder and levelorder) without using conditionals and only using polymorphic method dispatch or iterators. 我试图在python中创建一个模块,以使用4个标准树遍历(有序,前序,后序和级别顺序)遍历二叉树,而不使用条件,而仅使用多态方法分派或迭代器。 The following examples should work. 以下示例应该起作用。

for e in t.preorder():
  print(e)
for e in t.postorder():
  print(e)
for e in t.inorder():
  print(e)
for e in t.levelorder():
  print(e)

So far I have come up with the following 到目前为止,我已经提出了以下建议

def build_tree(preord, inord):
  tree = BinaryTree()
  tree.root = buildTreeHelper(preord, inord)
  return tree

def buildTreeHelper(preorder, inorder):
  if len(inorder) == 0:
    return None

  elem = preorder[0]
  elemInorderIndex = inorder.find(elem)

  if elemInorderIndex > -1:
    leftPreorder = preorder[1:elemInorderIndex + 1]
    rightPreorder = preorder[elemInorderIndex + 1:]
    leftInorder = inorder[0:elemInorderIndex]
    rightInorder = inorder[elemInorderIndex + 1:]
    left = buildTreeHelper(leftPreorder, leftInorder)
    right = buildTreeHelper(rightPreorder, rightInorder)
    return BinaryTreeNode(elem, left, right)
  else:
    return "No valid tree for the given args"

class BinaryTree:
    def __init__(self):
        self.root = None
    def preorder(self):
        return self.root.preorder()
    def inorder(self):
        return self.root.inorder()
    def postoder(self):
        return self.root.postorder()

class BinaryTreeNode:
    def __init__(self, element, left=None, right=None):
        self.element = element
        self.left = left
        self.right = right
    def preorder(self):
        yield self.element
        for e in self.left.preorder():
            yield e
        for e in self.right.preorder():
            yield e
    def inorder(self):
        for e in self.left.inorder():
            yield e
        yield self.element
        for e in self.right.inorder():
            yield e
    def postorder(self):
        for e in self.left.postorder():
            yield e
        for e in self.right.postorder():
            yield e
        yield self.element

if __name__ == "__main__":
    t = build_tree("BAC", "ABC")
    for e in t.inorder():
        print(e)

When I try to run one of the iterators like at the bottom of the code I get an AttributeError: 'NoneType' object has no attribute 'inorder' error message. 当我尝试运行代码底部的迭代器之一时,出现AttributeError:'NoneType'对象没有属性'inorder'错误消息。 I think this is because I never raise StopIteration. 我认为这是因为我从未提出StopIteration。 Any ideas on how to fix this and start implementing levelorder? 关于如何解决此问题并开始实施levelorder的任何想法?

You said you wanted to use polymorphism, but you don't actually seem to have done so. 您说过您想使用多态性,但实际上似乎没有这样做。 Replace all occurrences of 'None' in your code with a special object that supports your methods but returns an empty sequence and it will all work. 用支持您的方法但返回空序列的特殊对象替换代码中所有出现的“ None”,并且一切正常。

Also you should take more care of the indentation when posting Python questions. 另外,在发布Python问题时,您应该更加注意缩进。 The code you posted won't run as is. 您发布的代码无法按原样运行。

def build_tree(preord, inord):
    tree = BinaryTree()
    tree.root = buildTreeHelper(preord, inord)
    return tree

def buildTreeHelper(preorder, inorder):
    if len(inorder) == 0:
        return empty

    elem = preorder[0]
    elemInorderIndex = inorder.find(elem)

    if elemInorderIndex > -1:
        leftPreorder = preorder[1:elemInorderIndex + 1]
        rightPreorder = preorder[elemInorderIndex + 1:]
        leftInorder = inorder[0:elemInorderIndex]
        rightInorder = inorder[elemInorderIndex + 1:]
        left = buildTreeHelper(leftPreorder, leftInorder)
        right = buildTreeHelper(rightPreorder, rightInorder)
        return BinaryTreeNode(elem, left, right)
    else:
        return "No valid tree for the given args"

class BinaryTree:
    def __init__(self):
        self.root = empty
    def preorder(self):
        return self.root.preorder()
    def inorder(self):
        return self.root.inorder()
    def postorder(self):
        return self.root.postorder()

class EmptyNode:
    def preorder(self):
        return ()
    inorder = postorder = preorder
empty = EmptyNode()

class BinaryTreeNode:
    def __init__(self, element, left=empty, right=empty):
        self.element = element
        self.left = left
        self.right = right
    def preorder(self):
        yield self.element
        for e in self.left.preorder():
            yield e
        for e in self.right.preorder():
            yield e
    def inorder(self):
        for e in self.left.inorder():
            yield e
        yield self.element
        for e in self.right.inorder():
            yield e
    def postorder(self):
        for e in self.left.postorder():
            yield e
        for e in self.right.postorder():
            yield e
        yield self.element

if __name__ == "__main__":
    t = build_tree("BAC", "ABC")
    for e in t.inorder():
        print(e)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM