【问题标题】:Binary Search Tree, Logical and Syntax Error二叉搜索树,逻辑和语法错误
【发布时间】:2018-12-15 00:40:42
【问题描述】:

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

我按照我拥有的伪代码实现了基本操作(我无法重构代码)。到目前为止我已经实现的是类 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'

【问题讨论】:

  • 如果你想知道那是递归设计的
  • 您没有用于初始化self.rootBST 构造函数。
  • @Barmar 从技术上讲,第一次调用insert 将初始化它(在调用之前,self.root 将是类级别的Node,其成员都是None)。跨度>

标签: python algorithm binary-search-tree


【解决方案1】:

有几个问题。

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

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

因为,一开始,root没有孩子,所以取这个if条件, 用新节点替换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,导致您的问题出现异常。

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

【讨论】:

  • 这应该被标记为正确答案。很好的解释!
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

        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() 方法,因此我们可以在子节点上递归调用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-23
      • 1970-01-01
      • 2017-06-12
      • 1970-01-01
      • 1970-01-01
      • 2019-04-15
      • 2016-12-04
      相关资源
      最近更新 更多