【问题标题】:how does __contains__ method work in binary search trees Python?__contains__ 方法如何在二叉搜索树 Python 中工作?
【发布时间】:2021-02-19 14:28:16
【问题描述】:

我有两个类,Node() 和 binarySearchTree()。 Node() 具有以下属性:

    self.left= None
    self.right= None
    self.key= key
    self.data = data

并且 binarySearchTree() 具有用于插入、搜索和打印二叉搜索树 (BST) 的方法。我还必须为我的 BST 包含一个 __contains__ 方法,这使我能够编写如下内容:

tree= Bintree()
tree.store("table")
 
if "table" in tree:  <--
    do something     <--

它抱怨最后两个“__contains__”没有定义。但我希望它以递归方式工作。但它不起作用。

    def __contains__(self, key):
        if self.root == None:
            return False
        elif key== self.root.key:
            return True
        elif key < self.root.key:
            return __contains__(self.root.key.left,key)
        elif key > self.root.key:
            return __contains__(self.root.key.right,key)

【问题讨论】:

  • 方法名前需要self.
  • 或者直接使用in而不是直接调用__contains__key in self.root.left
  • self.root 到底是什么? leftright 属性,还是self 本身有这些属性?

标签: python binary-search-tree contains


【解决方案1】:

__contains__ 不是全局变量;它是一个类属性,因此必须通过BinTree 或其实例之一访问。至少,你需要写

def __contains__(self, key):
    if self.root == None:
        return False
    elif key == self.root.key:
        return True
    elif key < self.root.key:
        return BinTree.__contains__(self.root.left, key)
    elif key > self.root.key:
        return BinTree.__contains__(self.root.right, key)

(请注意,第一个参数中不需要key 属性;它是self.root 本身,而不是它的键,具有leftright 属性。

但是,这只是一种调用实例属性的非标准方式,会阻止继承正常工作。如果您更改类的名称而不更新方法的定义以使用新名称,它也会失败。下一个最好的方法是正常调用该方法。

def __contains__(self, key):
    if self.root == None:
        return False
    elif key == self.root.key:
        return True
    elif key < self.root.key:
        return self.root.left.__contains__(key)
    elif key > self.root.key:
        return self.root.right.__contains__(key)

但最好不要直接调用__contains__,而是使用in,它会为你调用__contains__

def __contains__(self, key):
    if self.root == None:
        return False
    elif key == self.root.key:
        return True
    elif key < self.root.key:
        return key in self.root.left
    else:  # key > self.root.key is the only option left
        return key in self.root.right

警告:以上所有内容均假设 self.root.leftself.root.right 存在且不是 None,此假设可能不准确,但如果没有代码显示 BinTree 是如何构造的,则无法确认。

【讨论】:

  • 错了。如果他重命名他的班级,它将无法正常工作。调用 self.contains
  • @LucaSansS 我认为破坏继承是比更改类名更大、更可能出现的问题。不推荐第一种解决方案,但我会明确说明名称更改。
【解决方案2】:

如果您有单独的树和节点类型,则需要两个函数,一个通过节点递归,另一个只是为了让事情顺利进行。

类似这样的:

def __contains__(self, key):
    returns self.node_contains(self.root, key)

def node_contains(self, node, key):
    if node == None:
        return False
    elif key == node.key:
        return True
    elif key < node.key:
        return self.node_contains(node.left, key)
    elif key > node.key:
        return self.node_contains(node.right, key)

或者,您可以在类之间划分工作,这可能看起来像

在树类中:

def __contains__(self, key):
    return self.root and key in self.root

在节点类中:

def __contains__(self, key):
    return self.key == key 
        or (key < self.key and self.left and key in self.left) 
        or (self.right and key in self.right)

【讨论】:

    【解决方案3】:

    简单的修复

         1      def __contains__(self, key):
         2          if self.root == None:
         3              return False
         4          elif key== self.root.key:
         5              return True
         6          elif key < self.root.key:
         7              return self.__contains__(self.root.key.left,key)
         8          elif key > self.root.key:
         9              return self.__contains__(self.root.key.right,key)
    

    只需拨打self.__contains__

    【讨论】:

    • 呃。请不要在另一个对象上使用一个对象的特殊方法。虽然这在这种情况下有效,但它非常脆弱。
    • 感谢您的回答。但是仍然无法正常工作。现在它抱怨我有太多用于方法调用的位置参数,因为 contains__(self,key) 只有一个位置参数。如果我添加另一个位置参数,它会开始抱怨 __contians 只需要一个位置参数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多