
AVL树
AVL 树是最早被发明的自平衡二叉查找树。在 AVL 树中,任意节点对应的两颗子树的最大高度差为 1,因此他也被称为高度平衡树。查找、插入和删除在平均和最坏的情况下的时间复杂度都是 O(log n)。增加和删除元素的操作则节能需要一次或多次树旋转,以实现树的重新平衡。
结构定义
type AVLTreeNode struct {
Left *AVLTreeNode
Right *AVLTreeNode
Val int
Height int // 当前节点深度 (左子树与右子树的差)
}
旋转树节点
// 将树进行左旋
func ll(node *AVLTreeNode) *AVLTreeNode {
nodeR := node.Right
node.Right = nodeR.Left
nodeR.Left = node
node.Height = max(height(node.Left), height(node.Right)) + 1
nodeR.Height = max(height(nodeR.Right), node.Height) + 1
return nodeR
}
// 将树进行右旋
func rr(node *AVLTreeNode) *AVLTreeNode {
nodeL := node.Left
node.Left = nodeL.Right
nodeL.Right = node
node.Height = max(height(node.Left), height(node.Right)) + 1
nodeL.Height = max(height(nodeL.Left), node.Height) + 1
return nodeL
}
// 将树进行右旋后左旋
func lr(node *AVLTreeNode) *AVLTreeNode {
node.Left = ll(node.Left)
return rr(node)
}
// 将树进行左旋后右旋
func rl(node *AVLTreeNode) *AVLTreeNode {
node.Right = rr(node.Right)
return ll(node)
}
// 若树失去平衡性,`进行旋转
func handleBF(node *AVLTreeNode) *AVLTreeNode {
// 左子树失衡
if height(node.Left)-height(node.Right) == 2 {
if height(node.Left.Left)-height(node.Left.Right) > 0 {
node = rr(node) // 左子树的左子树失衡
} else {
node = lr(node) // 左子树的右子树失衡
}
// 右子树失衡
} else if height(node.Right)-height(node.Left) == 2 {
if height(node.Right.Left)-height(node.Right.Right) > 0 {
node = rl(node) // 右子树的左子树失衡
} else {
node = ll(node) // 右子树的右子树失衡
}
}
// 重新计算当前节点深度
node.Height = max(height(node.Left), height(node.Right)) + 1
return node
}
添加元素
func height(t *AVLTreeNode) int {
if t == nil {
return -1
}
return t.Height
}
func max(i, j int) int {
if i < j {
return j
}
return i
}
func insert(node *AVLTreeNode, val int) *AVLTreeNode {
if node == nil {
node = NewAVLTree(val)
} else if val < node.Val {
node.Left = insert(node.Left, val)
node = handleBF(node)
} else if val > node.Val {
node.Right = insert(node.Right, val)
node = handleBF(node)
}
return node
}
删除节点
func delete(node *AVLTreeNode, val int) *AVLTreeNode {
if node == nil {
fmt.Println("没有元素")
return nil
} else if node.Val < val {
node.Right = delete(node.Right, val)
node = handleBF(node)
} else if val < node.Val {
node.Left = delete(node.Left, val)
node = handleBF(node)
} else if val == node.Val {
// 若待删除节点为叶子节点, 直接删除
if node.Left == nil && node.Right == nil {
node = nil
return node
// 若待删除节点有左子树或右子树,左子树或右子树代替被删除节点
} else if node.Left != nil && node.Right == nil {
nodeL := node.Left
node.Left = nil
return handleBF(nodeL)
} else if node.Right != nil && node.Left == nil {
nodeR := node.Right
node.Right = nil
return handleBF(nodeR)
// 若待删除节点有左子树和右子树
} else {
// 找出待删除节点的后继节点和后继节点的父节点
p, n := searchNode(node.Right)
// 若后继节点是待删除节点的子节点,后继节点代替待删除节点
if node.Right == n {
n.Left = node.Left
node = nil
return handleBF(n)
// 若后继节点有右子树,后继节点的父节点的左子树为后继节点的右子树
} else if n.Right != nil {
p.Left = n.Right
n.Left = node.Left
n.Right = node.Right
node = nil
return handleBF(n)
// 若后继节点没有右子树,后继节点代替待删除节点
} else if n.Right == nil {
n.Left = node.Left
n.Right = node.Right
node = nil
p.Left = nil
return handleBF(n)
}
}
}
return node
}
找出后继节点与后继节点的父节点
func searchNode(node *AVLTreeNode) (*AVLTreeNode, *AVLTreeNode) {
if node.Left == nil {
return nil, node
}
for {
if node.Left.Left != nil {
node = node.Left
} else {
return node, node.Left
}
}
}