【问题标题】:Returning value of None objectNone 对象的返回值
【发布时间】:2016-02-04 15:53:19
【问题描述】:

我的 AVL 树实现中有添加方法。

class Node:    
    def __init__(self, data, left = None, right = None, height = -1):
        self.data = data
        self.left = left
        self.right = right
        self.height = height
    def addNode(self, data):
        if self.data > data:
            '''Adding to left subtree'''
            if self.left is None:
                self.left = Node(data)
            else:
                self.left.addNode(data)
                if ( abs(self.right.height - self.left.height) == 2):
                    ''' Then we need to balance a subtree''' 
                    print("Rebalancing after inserting", data)
                    if (data < self.left.data):
                        self.rotateLeft()
                    else:
                        self.doubleRotateLeft()

        elif self.data < data:
            '''Adding to right subtree'''
            if self.right is None:
                self.right = Node(data)
            else:
                self.right.addNode(data)
                if ( abs(self.right.height - self.left.height) == 2):
                    ''' Then we need to balance a subtree'''
                    print("Rebalancing after inserting", data)
                    if (data < self.right.data):
                        self.rotateRight()
                    else:
                        self.doubleRotateRight()

但是当我尝试这样做时

self.right.height

并且self没有得到正确的对象那么它不会返回高度,即使默认值为-1。我该如何解决?我试图在这种方法中尽可能减少重复的代码

【问题讨论】:

    标签: python algorithm oop methods avl-tree


    【解决方案1】:

    如果self.right 设置为None,则不能使用self.right.height,不。如果该表达式必须有效,请不要使用None。改为使用定义该属性的哨兵。

    哨兵可以只是一个没有值和子节点的自定义类。您可以像 None 一样将其设为单例:

    class Sentinel(object):
        value = left = right = None
        height = -1
    
    sentinel = Sentinel()
    
    class Node:    
        def __init__(self, data, left=sentinel, right=sentinel, height=-1):
            # ...
    

    然后在您的代码中测试is sentinel 而不是is None。通过使用sentinel 作为leftright 关键字参数的默认值,self.left.heightself.right.height 将始终有效(假设selfNode 的一个实例)。

    不要忘记在每次创建新节点时增加 height

    您可以通过使用本地引用稍微简化您的 addNone() 方法:

    def addNode(self, data):
        if self.data == data: return
        left = self.data > data
        testnode = self.left if left else self.right
        if testnode is sentinel:
            node = Node(data)
            setattr(self, 'left' if left else 'right', node)
        else:
            testnode.addNode(data)
            if abs(self.right.height - self.left.height) == 2:
                if data < testnode.data:
                    rotation = self.rotateLeft if left else self.rotateRight
                else:
                    rotation = self.doubleRotateLeft if left else self.doubleRotateRight
                rotation()
    

    【讨论】:

    • 谢谢。你能告诉我如何避免重复代码吗?
    • 您是指self.leftself.right 的代码?为什么不在新变量node 中创建一个新节点,将其分配给leftright,然后将所有这些更改应用到那个node 引用?
    • 是的,我的意思是相同的算法适用于左右子树。谢谢,您的解决方案很棒!
    • 我已将其减少到 13 行;您可以使用调度表进行轮换(使用 (bool, bool) 值的元组 leftdata &lt; testnode.data 作为键)来进一步减少它。
    • 好的,你之前提到的增加高度怎么样?这个算法不行吗?
    猜你喜欢
    • 1970-01-01
    • 2016-07-06
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-22
    • 2019-10-13
    相关资源
    最近更新 更多