简体   繁体   English

python 中的递归 class 定义

[英]recursive class definition in python

Sorry if my English is bad, I speak Korean as mother tongue.对不起,如果我的英语不好,我会说韩语作为母语。
I am implementing binary search tree in Python 3, but I wasn't able to meet my goal.我正在 Python 3 中实现二叉搜索树,但我无法实现我的目标。
Here is code:这是代码:

class Node(object):

    def __init__(self, key=None, data=None):
        self.key = key
        self.data = data

class BinarySearchTree(object):
    keyfunc = None  # Will it be worse when using lambda x: x as default?
    
    def __init__(self, node=None):
        self.root = node
        self.left = None
        self.right = None
        # I don't want default to be NoneType, but don't know how for now.

    def add(self, key, data=None):
        node = Node(key, data)
        if self.root is None:
            self.root = node
            return
        parent = self.root.key
        if self.keyfunc is None:
            if key < parent:
                if self.left is None:
                    self.left = __class__(node)
                else:
                    self.left.add(key, data)
                        
            elif key > parent:
                if self.right is None:
                    self.right = __class__(node)
                else:
                    self.right.add(key, data)
        else:
            if keyfunc(key) < keyfunc(parent):
                if self.left is None:
                    self.left = __class__(node)
                else:
                    self.left.add(key, data)
            elif keyfunc(key) > keyfunc(parent):
                if self.right is None:
                    self.right = __class__(node)
                else:
                    self.right.add(key, data)
    def inorder(self):
        if self.root:
            if self.left:
                self.left.inorder()
            print(self.root.key, end=' ')
            if self.right:
                self.right.inorder()

if __name__ == '__main__':
    bst1 = BinarySearchTree()
    arr = [2,6,4,3,2,7,8,1,9,5]
    for key in arr:
        bst1.add(key)
    bst1.inorder()

It works anyway, but what I want is:无论如何它都有效,但我想要的是:

  • even when root node has no child, I want the type of bst1.left (or bst1.right ) be always BinarySearchTree.即使根节点没有子节点,我也希望bst1.left (或bst1.right )的类型始终为 BinarySearchTree。
    That way, I can allow null tree treated in consistency with other trees, and also can I remove repeating if self.left is None in add().这样,我可以允许 null 树与其他树保持一致,并且if self.left is None ,我也可以删除重复。
  • I don't want to manually do bst1.left = BinarySearchTree(None) after class definition, because it will be required to applied to all of nodes.我不想在 class 定义之后手动执行bst1.left = BinarySearchTree(None) ,因为它需要应用于所有节点。

I tried self.left = BinarySearchTree(None) (of course it resulted bad recursion), and tried to use __new__() method and Metaclasses as answered in other stackoverflow questions, but couldn't come up with solution.我尝试self.left = BinarySearchTree(None) (当然它导致了错误的递归),并尝试使用__new__()方法和 Metaclasses,如其他 stackoverflow 问题中所回答的那样,但无法提出解决方案。
It would very grateful if I can get help.如果我能得到帮助将不胜感激。

Consider replacing NoneType child trees with an empty tree object with a None root.考虑将NoneType子树替换为具有None根的空树 object。 Also, to answer the question in your code comment, I think defaulting keyfunc = lambda x: x is reasonable, and it simplifies your code further.另外,要回答代码注释中的问题,我认为默认keyfunc = lambda x: x是合理的,它进一步简化了您的代码。

class BinarySearchTree:
    def __init__(self, node, keyfunc=lambda x: x):
        self.root = node
        self.keyfunc = keyfunc
        if node is not None:
            self.left = self.new_empty()
            self.right = self.new_empty()

    def new_empty(self):
        """Create a new empty child for this tree"""
        return BinarySearchTree(None, self.keyfunc)
    
    def add(self, key, data=None):
        node = Node(key, data)
        if self.root is None:
            self.root = node
            self.left = self.new_empty()
            self.right = self.new_empty()
        else:
            parent = self.root.key
            if self.keyfunc(key) < self.keyfunc(parent):
                self.left.add(key, data)
            elif self.keyfunc(key) > self.keyfunc(parent):
                self.right.add(key, data)

    def inorder(self):
        if self.root is not None:
            self.left.inorder()
            print(self.root.key, end=' ')
            self.right.inorder()

For ease of use, you may also choose to add a definition like the following:为了便于使用,您还可以选择添加如下定义:

def __bool__(self):
    return self.root is not None

This lets you simplify a test to see if a node is empty by doing something like if self: instead of if self.root is not None: in the inorder method or if self.left: to see if there is a left child tree instead of if self.left.root is not None: .这使您可以通过执行类似if self:而不是if self.root is not None:inorder方法中或if self.left:来查看是否存在左子树来简化测试以查看节点是否为空if self.left.root is not None:

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

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