Python 如何实现AVL树旋转?

Python 如何实现AVL树旋转?,python,recursion,avl-tree,Python,Recursion,Avl Tree,我已经编写了一个AVL树,我的旋转逻辑是正确的,但我仍然无法让它正常工作。对于根节点上的旋转,“我的旋转”工作正常,但如果旋转在树的更下方,则父节点不会指向已旋转到位的新节点,而是继续指向旋转前已就位的节点。我很确定问题出在我的insert方法上,但我不确定在发生旋转时如何让父节点指向新节点。我知道你可以添加一个父变量来解决这个问题,但我想知道是否有一种方法可以不用它 For example 10

我已经编写了一个AVL树,我的旋转逻辑是正确的,但我仍然无法让它正常工作。对于根节点上的旋转,“我的旋转”工作正常,但如果旋转在树的更下方,则父节点不会指向已旋转到位的新节点,而是继续指向旋转前已就位的节点。我很确定问题出在我的insert方法上,但我不确定在发生旋转时如何让父节点指向新节点。我知道你可以添加一个父变量来解决这个问题,但我想知道是否有一种方法可以不用它

For example
               10                                     10                                10
            /      \                                /   \           instead of         /    \
           8        12     Rotates to ->            8    12                          6      12
          /          \                                    \                         / \      \
         6            14                                    14                     4   8       14
         /                                        4 and 6 are lost
        4

在您的代码中,
insert
方法在插入完成并进行任何必要的旋转之后返回子树的新根。您的问题是,在一个子节点上递归调用
insert
时,没有使用该返回值

            if data < self.data:
                if self.left is None:
                    self.left = MyAVL(data)                   
                else:
                    self.left = self.left.insert(data)     # update self.left here
            elif data >= self.data:
                if self.right is None:
                    self.right = MyAVL(data)                        
                else:
                    self.right = self.right.insert(data)   # and self.right here
如果数据=self.data:
如果self.right为无:
self.right=MyAVL(数据)
其他:
self.right=self.right.在此处插入(数据)#和self.right

需要说明的是,
类MyAVL():
表示树的一个节点,而不是整个树,是吗?无论如何,您是否检查了树是否紧跟在
insert
的实际插入部分之后,但在旋转之前?另外:请仔细考虑在开始旋转时哪个节点是
self
。如果你有
parent
指针,你会谈论如何解决这个问题,出于优雅的原因,你想避免使用这些指针;你能想出另一种方法来知道递归算法中的父项是什么吗?(提示:递归调用从何而来?该节点是否能提供帮助?我至少可以想出两种方法在调用之间传递必要的信息:in和out。)请提供预期的结果。显示中间结果与预期结果的偏差。我们应该能够将单个代码块粘贴到文件中,运行它,并重现您的问题。这也让我们可以在您的上下文中测试任何建议。您发布的代码定义了一个类,并在不做任何事情的情况下退出。我们期待这个问题的一个工作示例,包括跟踪内部操作的适当代码。此外,考虑以更有用的方式设计围绕旋转的接口。您只需检查节点以查看是否需要旋转,对吗?因此,与其将“找出节点是否不平衡”与“插入,然后在必要时平衡”进行分组,更合理的分组是“必要时平衡(其中“必要”需要检查)”与“插入”(这需要调用balance,因为我们应该在每次修改树时恢复平衡)”.@KarlKnechtel在本例中,当调用旋转时,self是节点8,旋转方法返回节点6。关于如何更新父节点的左子节点,我仍然是一片空白。
#This example works properly
test = AVL(10)
test= test.insert(12)
test = test.insert(8)
print(test.data) #outputs 8
print(test.left.data) #outputs 7
print(test.right.data) #outputs 10

#In this case the rotation occurs but the parent node does not update its left child to the new node and still points to 8
test2 = AVL(10)
test2 = test2.insert(12)
test2 = test2.insert(8)
test2 = test2.insert(14)
test2 = test2.insert(6)
test2 = test2.insert(4)
print(test2.data)#outputs 10
print(test2.left.data)#outputs 8 but should be 6
#4 and 6 can no longer be accessed because they are lost
            if data < self.data:
                if self.left is None:
                    self.left = MyAVL(data)                   
                else:
                    self.left = self.left.insert(data)     # update self.left here
            elif data >= self.data:
                if self.right is None:
                    self.right = MyAVL(data)                        
                else:
                    self.right = self.right.insert(data)   # and self.right here