AVL树的python实现
- AVL平衡树确实能够改进BST树的性能,避免退化
- 向AVL树插入一个新key,如何才能保持AVL树的平衡性质
- 作为BST,新key必定以叶节点形式插入到AVL树中
叶节点的平衡因子是0,其本身无需重新平衡
父节点的平衡因子会受到影响
- 作为左子节点插入,则父节点平衡因子会增加1
- 作为右子节点插入,则父节点平衡因子会减少1
这种影响可能随着其父节点到根节点的路径一直传递上去,直到:
- 传递到根节点为止
- 或者某个父节点平衡因子被调整到0,不再影响上层节点的平衡因子为止(无论从-1或者1调整到0,都不会改变子树高度)
_put方法
- 重新定义_put方法
def _put(self, key, val, currentNode):
if key < currentNode.key:
if currentNode.hasLeftChild():
self._put(key, val, currentNode.leftChild)
else:
currentNode.leftChild = TreeNode(key, val, parent=currentNode)
self.updateBalance(currentNode.leftChild) #调整因子
else:
if currentNode.hasRightChild():
self._put(key, val, currentNode.rightChild)
else:
currentNode.rightChild = TreeNode(key, val, parent=currentNode)
self.updateBalance(currentNode.rightChild) #调整因子
UpdateBalance方法
#更新平衡
def updateBalance(self, node):
if node.balanceFactor > 1 or node.balanceFactor < -1:
self.rebalance(node) #重新平衡
return
if node.parent != None: #如果父节点不是空
if node.isLeftChild(): #是左子节点加一
node.parent.balanceFactor += 1
elif node.isRightChild(): #是右子节点加一
node.parent.balanceFactor -= 1
if node.parent.balanceFactor != 0:
self.updateBalance(node.parent) #调整父节点因子
rebalance重新平衡
- 主要手段:将不平衡的子树进行旋转rotation
- 视"左重"或者"右重”进行不同方向的旋转同时更新相关父节点引用,更新旋转后被影响节点的平衡因子
"右重"子树A的左旋转(并保持BST性质)
"左重"子树右旋转
rotateLeft代码
- 图解
def rotateLeft(self, rotRoot):
newRoot = rotRoot.rightChild #新根节点是旧根节点的右子树
rotRoot.rightChild = newRoot.leftChild
if newRoot.leftChild != None:
newRoot.leftChild.parent = rotRoot
newRoot.parent = rotRoot.parent
if rotRoot.isRoot():
self.root = newRoot
else:
if rotRoot.isLeftChild():
rotRoot.parent.leftChild = newRoot
else:
rotRoot.parent.rightChild = newRoot
newRoot.leftChild = rotRoot
rotRoot.parent = newRoot
rotRoot.balanceFactor = rotRoot.balanceFactor + 1 - min(newRoot.balanceFactor, 0)
newRoot.balanceFactor = newRoot.balanceFactor + 1 + max(rotRoot.balanceFactor, 0)
如何调整平衡因子
更复杂的情形