堆和棧的區別
阿新 • • 發佈:2020-12-19
技術標籤:資料結構
簡述
二叉搜尋樹的最壞情況下搜尋的時間複雜度可能達到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),這就是相比於紅黑樹來說劣勢的地方了。