go实现平衡二叉树(构建、遍历)
AVL树(自平衡搜索二叉树)的应用场景和特点
AVL 树是一种自平衡二叉搜索树(Self-Balancing Binary Search Tree, SBBST),由 G.M. Adelson-Velsky 和 E.M. Landis 在 1962 年提出。AVL 树的特点是任何节点的两个子树的高度差最多为 1,这保证了树的高度保持在 O(log n),从而确保了查找、插入和删除操作的时间复杂度均为 O(log n)。
特点
-
自平衡:
- AVL 树通过旋转操作来保持平衡。当插入或删除一个节点导致树不平衡时,AVL 树会执行一系列的旋转操作(左旋、右旋、左右旋、右左旋)来恢复平衡。
-
高度平衡:
- 由于每个节点的左右子树高度差不超过 1,AVL 树的高度始终保持在 O(log n),这使得它的操作效率很高。
-
严格的平衡条件:
- 这种严格的平衡条件保证了所有基本操作(如查找、插入、删除)的最坏情况时间复杂度都是 O(log n)。
-
内存开销:
- 每个节点需要额外的空间来存储其高度信息,用于判断是否需要进行平衡操作。
-
插入和删除操作较复杂:
- 相比于普通二叉搜索树,AVL 树的插入和删除操作更复杂,因为需要维护平衡性,这涉及更多的计算和旋转操作。
应用场景
-
数据库索引:
- 在数据库系统中,AVL 树可以用来实现高效的索引结构,特别是在数据量较大且频繁进行查找操作的情况下。
-
实时系统:
- 对于需要快速响应查询的实时系统,AVL 树提供了一种可靠的数据结构选择。
-
符号表:
- 在编译器设计中,AVL 树可以用作符号表,以支持快速的变量查找和更新。
-
集合和映射:
- 在需要高效地管理有序集合或键值对的应用中,AVL 树是一个很好的选择。
-
内存中的数据结构:
- 当需要在内存中维护一个动态的有序集合,并且要求操作具有较高的性能时,AVL 树是一个合适的选择。
总结
AVL 树适合那些需要高效查找、插入和删除操作,并且对数据有序性的应用场景。它通过严格的平衡条件保证了操作的高效性,但同时也带来了更高的实现复杂度。对于需要在数据动态变化的同时保持高效率的应用来说,AVL 树是一个非常强大的工具。然而,在某些情况下,如果不需要如此严格的平衡条件,或者数据集较小,使用其他数据结构(如红黑树)可能更为合适,因为它们在实现上相对简单一些。
代码
package main import "fmt" type TreeNode struct { value int height int left *TreeNode right *TreeNode } type AVLTree struct { root *TreeNode } func (n *TreeNode) Height() int { if n == nil { return 0 } return n.height } func maxHeight(a *TreeNode, b *TreeNode) int { if a.Height() > b.Height() { return a.Height() } return b.Height() } func computedBalanceFactor(n *TreeNode) int { return n.left.Height() - n.right.Height() } func (tree *AVLTree) Insert(value int) { tree.root = tree.insert(tree.root, value) } func (tree *AVLTree) insert(node *TreeNode, value int) *TreeNode { if node == nil { return &TreeNode{value: value, height: 1} } if value < node.value { node.left = tree.insert(node.left, value) } else if value > node.value { node.right = tree.insert(node.right, value) } else { return node } node.height = 1 + maxHeight(node.left, node.right) balanceFactor := computedBalanceFactor(node) // 右右 if balanceFactor < -1 && value > node.right.value { return tree.leftRotate(node) } // 左左 if balanceFactor > 1 && value < node.left.value { return tree.rightRotate(node) } // 右左 if balanceFactor < -1 && value < node.right.value { node.right = tree.rightRotate(node.right) return tree.leftRotate(node) } // 左右 if balanceFactor > 1 && value > node.left.value { node.left = tree.leftRotate(node.left) return tree.rightRotate(node) } return node } func (tree *AVLTree) leftRotate(node *TreeNode) *TreeNode { y := node.right T2 := y.left y.left = node node.right = T2 node.height = 1 + maxHeight(node.left, node.right) y.height = 1 + maxHeight(y.left, y.right) return y } func (tree *AVLTree) rightRotate(node *TreeNode) *TreeNode { x := node.left T2 := x.right x.right = node node.left = T2 node.height = 1 + maxHeight(node.left, node.right) x.height = 1 + maxHeight(x.left, x.right) return x } func (tree *AVLTree) PrintTree() { tree.printTree(tree.root, 0) fmt.Println() } func (tree *AVLTree) printTree(node *TreeNode, level int) { if node != nil { tree.printTree(node.right, level+1) fmt.Println() for i := 0; i < level; i++ { fmt.Print("\t") } fmt.Print(node.value) tree.printTree(node.left, level+1) } } func (tree *AVLTree) PreOrder() { tree.preOrder(tree.root) } func (tree *AVLTree) preOrder(node *TreeNode) { if node == nil { return } if node.left != nil { tree.preOrder(node.left) } fmt.Print(node.value, ", ") if node.right != nil { tree.preOrder(node.right) } } func main() { tree := AVLTree{} values := []int{10, 30, 20, 40, 5, 25} for _, v := range values { tree.Insert(v) } tree.PrintTree() // 前序遍历出来的结果是顺序的,参考快速排序 tree.PreOrder() }
结果
40 30 25 20 10 5 5, 10, 20, 25, 30, 40,
本文作者:jikefan
本文链接:https://www.cnblogs.com/jikefan/articles/18574105
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。