简述
二叉搜索树的最坏情况下搜索的时间复杂度可能达到O(n),avl树在普通的二叉搜索树的基础上加入了自动平衡的特性,其左子树与右子树的高度差的绝对值不大于2,且左子树与右子树也是一棵avl树
旋转
avl树进行插入或者删除后,通过旋转来满足平衡性质
总共有4种情况需要旋转
- LL: 左孩子的左子树进行了插入导致了不平衡,此时需要右旋
- RR:右孩子的右子树进行了插入导致了不平衡,此时需要左旋
- LR:左孩子的右子树进行了插入,此时需要先左旋再右旋
- RL:右孩子的左子树进行了插入,此时需要先右旋再左旋
代码实现
package main
import (
"fmt"
"math"
)
type Node struct {
height int
left *Node
right *Node
value int
}
type AVL struct {
root *Node
}
func BalancedFactor(root *Node) int {
if root == nil {
return 0
}
return Height(root.right)-Height(root.left)
}
func Height(node *Node) int{
if node==nil {
return 0
}
return node.height
}
func LeftRotation(root *Node)*Node {
right := root.right
root.right = right.left
right.left=root
// 长度变更
root.height = int(math.Max(float64(Height(root.right)), float64(Height(root.left)))) + 1
return right
}
func RightRotation(root *Node)*Node {
left := root.left
root.left = left.right
left.right=root
root.height = int(math.Max(float64(Height(root.right)), float64(Height(root.left)))) + 1
return left
}
func RightLeftRotation(root *Node)*Node {
root.right=RightRotation(root.right)
return LeftRotation(root)
}
func LeftRightRotation(root *Node)*Node {
root.left=LeftRotation(root.left)
return RightRotation(root)
}
func add(root *Node, node *Node) *Node{
if root == nil {
return node
}
if root.value>node.value {
root.left=add(root.left,node)
} else {
root.right=add(root.right,node)
}
root.height= int(math.Max(float64(Height(root.right)), float64(Height(root.left)))) + 1
if BalancedFactor(root) > 1 && BalancedFactor(root.right) < 0{
return RightLeftRotation(root)
} else if BalancedFactor(root) < -1 && BalancedFactor(root.left) > 0 {
return LeftRightRotation(root)
} else if BalancedFactor(root) > 1 {
return LeftRotation(root)
} else if BalancedFactor(root) < -1 {
return RightRotation(root)
}
return root
}
func delete(root *Node, val int) *Node {
if root == nil {
return nil
}
retRoot := root
if root.value > val {
root.left = delete(root.left, val)
} else if root.value < val {
root.right = delete(root.right, val)
} else {
if root.left == nil {
retRoot = root.right
} else if root.right == nil {
retRoot = root.left
} else {
right := root.right
rightLeft := right.left
for rightLeft != nil {
right = rightLeft
rightLeft = rightLeft.left
}
retRoot = right
// 这里赋值顺序要注意
retRoot.right = delete(root.right, retRoot.value)
retRoot.left = root.left
}
}
if BalancedFactor(retRoot) > 1 && BalancedFactor(retRoot.right) < 0{
return RightLeftRotation(retRoot)
} else if BalancedFactor(retRoot) < -1 && BalancedFactor(retRoot.left) > 0 {
return LeftRightRotation(retRoot)
} else if BalancedFactor(retRoot) > 1 {
return LeftRotation(retRoot)
} else if BalancedFactor(retRoot) < -1 {
return RightRotation(retRoot)
}
return retRoot
}
func (avl *AVL)Add(node *Node) {
if node == nil {
return
}
root := avl.root
avl.root = add(root, node)
}
func (avl *AVL)Delete(val int) {
root := avl.root
avl.root = delete(root, val)
}
func (avl *AVL) LevelPrint() {
root := avl.root
if root == nil {
return
}
nodeList := make([]*Node,0)
nodeList = append(nodeList, root)
for len(nodeList) > 0 {
a := nodeList[0]
fmt.Print(" ", a.value)
nodeList = nodeList[1:]
if a.left != nil {
nodeList = append(nodeList, a.left)
}
if a.right != nil {
nodeList = append(nodeList, a.right)
}
}
}
func IsBalanced(root *Node) bool{
if root == nil {
return true
}
if int(math.Abs(float64(BalancedFactor(root)))) > 1 {
return false
}
return IsBalanced(root.right) && IsBalanced(root.left)
}
func (avl *AVL) Print() {
PrePrint(avl.root)
fmt.Println()
MidPrint(avl.root)
fmt.Println()
}
func PrePrint(node *Node) {
if node == nil {
return
}
fmt.Print(" ", node.value)
PrePrint(node.left)
PrePrint(node.right)
}
func MidPrint(node *Node) {
if node == nil {
return
}
MidPrint(node.left)
fmt.Print(" ", node.value)
MidPrint(node.right)
}
func main() {
avl := &AVL{}
v := []int{6,7,3,2,5,4,8,9,1,0, 44,23,12,65,88,45,13}
for _, i := range v {
avl.Add(&Node{value: i, height: 1})
fmt.Println(IsBalanced(avl.root))
}
avl.Print()
fmt.Println("delete................")
v = []int{0,1,6,5,7,9,8,2,3,4, 13,45,65,12,23,44,88}
for _, i := range v {
avl.Delete(i)
fmt.Println(IsBalanced(avl.root))
}
}
avl树性能
每次进行插入时,avl树只需经过最多一次操作就可以达到平衡。
而进行删除时,可能需要对从一整条路径进行平衡操作,复杂度可达log(n),这就是相比于红黑树来说劣势的地方了。