1. 程式人生 > 實用技巧 >堆和棧的區別

堆和棧的區別

技術標籤:資料結構

簡述

二叉搜尋樹的最壞情況下搜尋的時間複雜度可能達到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),這就是相比於紅黑樹來說劣勢的地方了。