【问题标题】:getting AttributeError: 'NoneType' object has no attribute 'rightnode' in avl tree获取AttributeError:'NoneType'对象在avl树中没有属性'rightnode'
【发布时间】:2021-12-01 15:52:21
【问题描述】:

我目前正在学习数据结构,但在 AVL 树中遇到了问题

代码:

from myqueue import Queue   #my custom queue implimented by linked list

class AVL:

    def __init__(self,data):
        self.data=data
        self.leftnode=self.rightnode=None
        self.height=1

    def LevelOrderTransversal(self):
        if not self:
            return 
        queue=Queue()
        queue.enqueue(self)
        while not (queue.isempty()):
            root=queue.dequeue()
            print(root.data)
            if root.leftnode is not None:
                queue.enqueue(root.leftnode)
            if root.rightnode is not None:
                queue.enqueue(root.rightnode)

def getheight(rootnode):
    if not rootnode:
        return 0
    return rootnode.height

def getbalance(rootnode):
    if not rootnode:
        return 0
    return getheight(rootnode.leftnode)-getheight(rootnode.rightnode)

def leftrotation(disbalancenode):
    rootnode=disbalancenode.rightnode
    disbalancenode.rightnode=disbalancenode.rightnode.leftnode
    rootnode.leftnode=disbalancenode
    disbalancenode.height=1+max(getheight(disbalancenode.leftnode),getheight(disbalancenode.rightnode))
    rootnode.height=1+max(getheight(rootnode.leftnode),getheight(rootnode.rightnode))
    return rootnode

def rightrotation(disbalancenode):
    rootnode=disbalancenode.leftnode
    disbalancenode.leftnode=disbalancenode.leftnode.rightnode
    rootnode.rightnode=disbalancenode
    disbalancenode.height=1+max(getheight(disbalancenode.leftnode),getheight(disbalancenode.rightnode))
    rootnode.height=1+max(getheight(rootnode.leftnode),getheight(rootnode.rightnode))
    return rootnode

def insertnode(rootnode,nodevalue):
    if rootnode.data is None:
        return AVL(nodevalue)
    elif nodevalue<rootnode.data:
        if rootnode.leftnode is None:
            rootnode.leftnode=AVL(nodevalue)
        else:
            insertnode(rootnode.leftnode,nodevalue)
    else:
        if rootnode.rightnode is None:
            rootnode.rightnode=AVL(nodevalue)
        else:
            insertnode(rootnode.rightnode,nodevalue)

    rootnode.height=1+max(getheight(rootnode.leftnode),getheight(rootnode.rightnode))
    balance=getbalance(rootnode)
    
    if balance>1 and nodevalue<rootnode.leftnode.data:
        return rightrotation(rootnode)
    if balance>1 and nodevalue>rootnode.leftnode.data:
        rootnode.leftnode=leftrotation(rootnode.leftnode)
        return rightrotation(rootnode)
    if balance<-1 and nodevalue<rootnode.rightnode.data:
        return leftrotation(rootnode)
    if balance<-1 and nodevalue>rootnode.rightnode.data:
        rootnode.rightnode=rightrotation(rootnode.rightnode)
        return leftrotation(rootnode)
    return rootnode



A=AVL(5)
A=insertnode(A,10)
A=insertnode(A,15)
A=insertnode(A,20)
A.LevelOrderTransversal()

由于左节点不平衡,所以当我们尝试平衡该节点时,rightrotation() 方法会引发错误

所以错误出现在insertnode()方法中

我得到的错误:

Traceback (most recent call last):
  File "c:\Users\Anurag Dabas\Desktop\python\avl tree\newavl.py", line 84, in <module>     
    A=insertnode(A,15)
  File "c:\Users\Anurag Dabas\Desktop\python\avl tree\newavl.py", line 76, in insertnode   
    rootnode.rightnode=rightrotation(rootnode.rightnode)
  File "c:\Users\Anurag Dabas\Desktop\python\avl tree\newavl.py", line 45, in rightrotation
    disbalancenode.leftnode=disbalancenode.leftnode.rightnode
AttributeError: 'NoneType' object has no attribute 'rightnode'

我尝试调试但找不到任何东西

这是我的myqueue.py 文件:https://paste-bin.xyz/18851

任何帮助或线索将不胜感激

谢谢

编辑:

目前我的树看起来像:

  5
   \
   10
     \  
      15
       \
        20
 #as you can see it's clearly unbalance so we need leftrotation since it's RR condition

所以左旋转后的结果是这样的:

    10
   /  \  
  5    15
        \
         20

【问题讨论】:

  • 您正在尝试访问disbalancenode.leftnode.rightnode,但disbalancenode.leftnodeNone
  • @JohnGordon 是的,先生,那么如何解决这个问题(我猜轮换的逻辑是正确的,调用轮换的条件也是正确的)
  • 如何解决它是不要那样做!如果 disbalancenode.leftnode 为 None,则不要尝试访问 disbalancenode.leftnode.rightnode。
  • @JohnGordon 谢谢先生,我将disbalancenode.leftnode.rightnode 更改为rootnode.leftnode,它正在工作:)
  • 您在问题底部添加的示例不现实:您一开始就无法到达那棵树,因为它甚至在到达那里之前就已经旋转了。

标签: python data-structures tree avl-tree


【解决方案1】:

您收到此错误的原因实际上有几个:

  • 平衡因子的计算方式与通常的计算方式相反:当树的左子树较高时,您的平衡因子为正,右子树较高时为负。这让我很困惑。

  • 您可能也有同样的困惑,因为多个if 条件中的比较运算符(例如:nodevalue&lt;rootnode.leftnode.data)的含义错误,因此您的代码最终执行了错误的轮换,从而导致了异常。

  • 当您进行双重旋转时,旋转方向应相反。在一种情况下,您有两个连续的leftrotation 呼叫。这是错误的。

因此,在不更改余额计算的情况下,您可以通过以下方式进行更正:

    rootnode.height=1+max(getheight(rootnode.leftnode),getheight(rootnode.rightnode))
    balance=getbalance(rootnode)
    if balance>1 and nodevalue<rootnode.leftnode.data:
        return rightrotation(rootnode)
    if balance>1 and nodevalue>rootnode.leftnode.data:
        rootnode.leftnode=leftrotation(rootnode.leftnode)
        return rightrotation(rootnode)  # <-- corrected
    if balance<-1 and nodevalue>rootnode.rightnode.data:
        return leftrotation(rootnode)
    if balance<-1 and nodevalue<rootnode.rightnode.data:
        rootnode.rightnode=rightrotation(rootnode.rightnode)
        return leftrotation(rootnode)
    return rootnode

【讨论】:

  • 感谢先生您提到的答案,我尝试调用leftrotation(),但它仍然抛出错误以及先生如何保护这两个函数不被引用:(
  • 你在纸上画了这个过程吗?你能展示你的分析吗?我们也期待您的努力。确保在所有场景中执行正确的旋转。因为这不是唯一一个错误。
  • 此外,您的代码有很多地方可以访问leftnoderightnode 的属性,但不能确保它们不是None
  • 仔细查看您的代码,我发现您的余额计算与通常的做法相反。更新了我的答案。
  • 快速浏览了一下,但并不是一篇好文章。通常,平衡因子在图像中的符号错误。例如,“单个 RR(右右)旋转”下方、“LR(左-右)旋转”下方和“RL(右-左)旋转”下方的图像就是这种情况。我会寻找更好的资源。维基百科的文章很好。
猜你喜欢
  • 2013-11-06
  • 1970-01-01
  • 2022-07-21
  • 2019-11-07
  • 1970-01-01
  • 1970-01-01
  • 2019-01-01
  • 2021-12-26
  • 2019-07-23
相关资源
最近更新 更多