如何实现AVL树旋转?
How to implement AVL tree rotation?
我编写了一个 AVL 树,我的旋转逻辑是正确的,但我仍然无法让它正常工作。对于根节点上的旋转,我的旋转工作正常,但如果旋转在树的更下方,则父节点不会指向已旋转到位的新节点,而是继续指向旋转之前就位的节点.我很确定问题出在我的插入方法上,但我不确定如何在发生旋转时让父节点指向新节点。我知道你可以添加一个父变量来解决这个问题,但我想知道是否有没有办法做到这一点。
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
class AVL():
def __init__(self, data):
self.data = data
self.left = None
self.right = None
self.height = 0
self.balf = 0
def getData(self):
return self.data
def getHeight(self):
return self.height
def heightCalc(self,node):
if node is None:
return -1
else:
return max(self.heightCalc(node.left), self.heightCalc(node.right)) + 1
def getBalanceFactor(self):
return self.balf
def balCheck(self, node):
if node is None:
return -1
else:
return self.heightCalc(node.left) - self.heightCalc(node.right)
def insert(self, data):
if data is not None:
if self.data is None:
self.data = data
else:
if data < self.data:
if self.left is None:
self.left = AVL(data)
else:
self.left.insert(data)
elif data >= self.data:
if self.right is None:
self.right = AVL(data)
else:
self.right.insert(data)
self.height=self.heightCalc(self)
self.balf = self.balCheck(self)
if self.balf > 1:
if self.left.getBalanceFactor() < 0:
self.left = self.left.leftRotate()
return self.rightRotate()
else:
return self.rightRotate()
elif self.balf < -1:
if self.right.getBalanceFactor() > 0:
self.right = self.right.rightRotate()
return self.leftRotate()
else:
return self.leftRotate()
return self
def leftRotate(self):
temp = self.right
temp2 = self.right.left
self.right.left = self
self.right = temp2
self.height = self.heightCalc(self)
temp.height = self.heightCalc(temp)
self.balf = self.balCheck(self)
temp.balf = self.balCheck(temp)
return temp
def rightRotate(self):
tmp = self.left
tmp1 = self.left.right
self.left.right = self
self.left = tmp1
self.height = self.heightCalc(self)
tmp.height = self.heightCalc(tmp)
self.balf = self.balCheck(self)
tmp.balf = self.balCheck(tmp)
return tmp
#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
在您的代码中,insert
方法 return 是子树的新根,在插入完成并发生任何需要的旋转之后。您的问题是,当您在其中一个子节点上递归调用 insert
时,您没有使用该 return 值。
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
我编写了一个 AVL 树,我的旋转逻辑是正确的,但我仍然无法让它正常工作。对于根节点上的旋转,我的旋转工作正常,但如果旋转在树的更下方,则父节点不会指向已旋转到位的新节点,而是继续指向旋转之前就位的节点.我很确定问题出在我的插入方法上,但我不确定如何在发生旋转时让父节点指向新节点。我知道你可以添加一个父变量来解决这个问题,但我想知道是否有没有办法做到这一点。
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
class AVL():
def __init__(self, data):
self.data = data
self.left = None
self.right = None
self.height = 0
self.balf = 0
def getData(self):
return self.data
def getHeight(self):
return self.height
def heightCalc(self,node):
if node is None:
return -1
else:
return max(self.heightCalc(node.left), self.heightCalc(node.right)) + 1
def getBalanceFactor(self):
return self.balf
def balCheck(self, node):
if node is None:
return -1
else:
return self.heightCalc(node.left) - self.heightCalc(node.right)
def insert(self, data):
if data is not None:
if self.data is None:
self.data = data
else:
if data < self.data:
if self.left is None:
self.left = AVL(data)
else:
self.left.insert(data)
elif data >= self.data:
if self.right is None:
self.right = AVL(data)
else:
self.right.insert(data)
self.height=self.heightCalc(self)
self.balf = self.balCheck(self)
if self.balf > 1:
if self.left.getBalanceFactor() < 0:
self.left = self.left.leftRotate()
return self.rightRotate()
else:
return self.rightRotate()
elif self.balf < -1:
if self.right.getBalanceFactor() > 0:
self.right = self.right.rightRotate()
return self.leftRotate()
else:
return self.leftRotate()
return self
def leftRotate(self):
temp = self.right
temp2 = self.right.left
self.right.left = self
self.right = temp2
self.height = self.heightCalc(self)
temp.height = self.heightCalc(temp)
self.balf = self.balCheck(self)
temp.balf = self.balCheck(temp)
return temp
def rightRotate(self):
tmp = self.left
tmp1 = self.left.right
self.left.right = self
self.left = tmp1
self.height = self.heightCalc(self)
tmp.height = self.heightCalc(tmp)
self.balf = self.balCheck(self)
tmp.balf = self.balCheck(tmp)
return tmp
#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
在您的代码中,insert
方法 return 是子树的新根,在插入完成并发生任何需要的旋转之后。您的问题是,当您在其中一个子节点上递归调用 insert
时,您没有使用该 return 值。
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