二进制搜索树,逻辑和语法错误

时间:2018-12-15 00:40:42

标签: python algorithm binary-search-tree

我正在尝试实现二叉搜索树,但是我认为我犯了逻辑和语法错误,现在放屁了。

我按照我拥有的伪代码实现了基本操作(我无法重构代码)。到目前为止,我实现的是class find,findMax,Insert,Traverse,但是看起来我在某个地方犯了逻辑错误,有帮助吗?

#!/usr/bin/python3.6

class Node:
  def __init__(self, key=None):
    self.key = key
    self.left = None
    self.right = None

class BST:
  root = Node()

  def find0(self, key):
    x =  self.find(self.root, key)
    return x

  # Recusive
  def find(self, root, key):
    if root is None or key == self.root.key:
      return self.root
    elif key > self.root.key:
      return self.find(self.root.right, key)
    else:
      return self.find(self.root.left, key)

  def findMin0():
    FNode = self.findMin(self.root)
    return FNode

  # Recursive
  def findMin(self, root):
    if self.root.right is None:
      return self.root
    else:
      return findMin(self.root.left)

 def findMax0():
    FNode = findMin(self.root)
    return FNode

  # Recursive
  def findMax(self, root):
    if self.root.right is None:
      return self.root
    else:
      return findMin(self.root.left)

  def insert(self, data):
    self.root = self.insertInTree(self.root, data)

  def insertInTree(self, root, key):
    if root.left is None and root.right is None :
       root = Node(key)
       return root
    elif key < root.key:
       root.left = self.insertInTree(root.left, key)
    elif key > root.key:
       root.right = self.insertInTree(root.right, key)
    return root

  def traverseInOrder0(self):
    self.traverseInOrder(self.root)

  def traverseInOrder(self, root):
    if root.key is not None:
      self.traverseInOrder(root.left)
      self.visit(root)
      self.traverseInOrder(root.right)

  def visit(self, node):
    print (node.key)

  def getRoot():
    return root

def main():
  NewTree = BST()
  NewTree.insert(100)
  NewTree.insert(90)
  NewTree.insert(110)
  NewTree.traverseInOrder0()
  #NewTree.findMin()


if __name__ == "__main__":
  main()

截至目前,我可以看到以下错误

Traceback (most recent call last):  
  File "./bst", line 86, in <module>  
    main()  
  File "./bst", line 81, in main  
    NewTree.traverseInOrder0()  
  File "./bst", line 61, in traverseInOrder0  
    self.traverseInOrder(self.root)  
  File "./bst", line 65, in traverseInOrder  
    self.traverseInOrder(root.left)  
  File "./bst", line 64, in traverseInOrder  
    if root.key is not None:  
AttributeError: 'NoneType' object has no attribute 'key'

3 个答案:

答案 0 :(得分:3)

有几个问题。

此插入函数将始终替换根,而从不实际插入任何新内容:

  def insertInTree(self, root, key):
    if root.left is None and root.right is None :
       root = Node(key)
       return root
    ...

因为一开始,root没有子代,所以采用了这种if条件, 用新节点替换root。 由于新节点没有子节点, 当您再次调用此函数以插入另一个值时, 它将再次发现根没有子, 然后替换root。它总是只替换root, 它永远不会插入任何新内容。

另一个问题是遍历:

  def traverseInOrder(self, root):
    if root.key is not None:
      self.traverseInOrder(root.left)
      self.visit(root)
      self.traverseInOrder(root.right)

key何时None?应该永远不会。节点应始终具有密钥。 另一方面,leftright子级可以是None。 递归调用导致您的问题中出现异常。 例如,当root.leftNone时, 对self.traverseInOrder(root.left)的调用将导致评估if root.key is ..., 但是rootNone,导致您的问题中出现例外情况。

可能还有其他问题, 在这一点上,我停止阅读。 我建议更深入地研究伪代码。

答案 1 :(得分:1)

如果设置了traverseInOrder,则root.left方法无条件地下降到root.rightroot.key中。如果其中任何一个缺少key成员(例如,因为他们是None),那么您将失败。为了避免这种情况,如果traverseInOrderrootNone应该在最顶端终止,或者如果不是None,则只能降入子级。

答案 2 :(得分:1)

一方面,您正在调用类方法,就像它们是独立函数一样。例如:

    def findMax0():
        FNode = findMin(self.root)
        return FNode

应为:

    def findMax0(self):
        FNode = self.findMin(self.root)
        return FNode

由于使用BST和Node这两个类会产生不必要的复杂性,因此很难完全理解您编写的代码。似乎至少导致了一些错误:

    # Recursive
    def findMin(self, root):
        if self.root.right is None:
            return self.root
        else:
            return findMin(self.root.left)

首先,它必须是self.findMin()。其次,您实际上从未引用过 root (仅引用 self.root ),因此递归将不起作用。

您似乎在递归代码中的功能和面向对象方法之间进行切换,这时选择一种样式要简单得多。例如,仅将 find()实现为它可能所属的Node方法:

class Node:
    def __init__(self, key):
        self.key = key
        self.left = None
        self.right = None

    def find(self, key):
        if key == self.key:
            return self
        if key > self.key and self.right:
            return self.right.find(key)
        if key < self.key and self.left:
            return self.left.find(key)

如您所见,使用单个类的优点是它包含的对象也具有 find()方法,因此我们可以在子节点上递归调用。