数据结构之AVL树

张开发
2026/4/12 1:35:32 15 分钟阅读

分享文章

数据结构之AVL树
AVL树详解1. 引言AVL树是一种自平衡的二叉搜索树由G.M. Adelson-Velsky和E.M. Landis在1962年提出因此得名AVL树。它是第一个被发明的自平衡二叉搜索树通过在插入和删除操作后进行旋转操作来保持树的平衡确保树的高度始终保持在O(log n)级别从而保证各种操作的时间复杂度为O(log n)。2. 基本概念2.1 二叉搜索树回顾二叉搜索树BST是一种每个节点最多有两个子节点的树结构满足以下性质左子树的所有节点值小于根节点值右子树的所有节点值大于根节点值左右子树也都是二叉搜索树2.2 平衡因子AVL树的核心概念是平衡因子Balance Factor定义为平衡因子 左子树高度 - 右子树高度在AVL树中每个节点的平衡因子只能是以下三种值之一-1右子树比左子树高10左右子树高度相等1左子树比右子树高1如果任何节点的平衡因子超出这个范围即绝对值大于1则树不平衡需要进行旋转操作来恢复平衡。3. 旋转操作当插入或删除节点导致树不平衡时AVL树通过四种旋转操作来恢复平衡3.1 左旋Left Rotationx y / \ / \ T1 y → x T3 / \ / \ T2 T3 T1 T23.2 右旋Right Rotationy x / \ / \ x T3 → T1 y / \ / \ T1 T2 T2 T33.3 左右旋Left-Right Rotationz z y / \ / \ / \ x T4 → y T4 → x z / \ / \ / \ / \ T1 y x T3 T1 T2 T3 T4 / \ / \ T2 T3 T1 T23.4 右左旋Right-Left Rotationz z y / \ / \ / \ T1 x → T1 y → z x / \ / \ / \ / \ y T4 T2 x T1 T2 T3 T4 / \ / \ T2 T3 T3 T44. 插入操作AVL树的插入操作分为以下步骤按照二叉搜索树的规则找到插入位置插入新节点从插入位置向上回溯更新每个节点的平衡因子如果发现不平衡节点进行相应的旋转操作4.1 插入后的平衡调整根据不平衡节点的位置和子节点的平衡因子选择不同的旋转策略LL情况左子树的左子树导致不平衡进行右旋RR情况右子树的右子树导致不平衡进行左旋LR情况左子树的右子树导致不平衡进行左右旋RL情况右子树的左子树导致不平衡进行右左旋5. 删除操作AVL树的删除操作比插入更复杂步骤如下按照二叉搜索树的规则找到要删除的节点如果节点有两个子节点找到中序后继或前驱节点替换删除节点从删除位置向上回溯更新平衡因子如果发现不平衡进行旋转操作删除操作可能需要多次旋转来恢复平衡因为删除操作可能影响多个祖先节点的平衡状态。6. 时间复杂度分析操作时间复杂度查找O(log n)插入O(log n)删除O(log n)最坏情况高度~1.44 log₂(n2) - 0.33AVL树的最坏情况高度约为1.44 log₂(n)比普通二叉搜索树的O(n)要好得多确保了所有操作的对数时间复杂度。7. 与其他平衡二叉搜索树的比较7.1 与红黑树的比较特性AVL树红黑树平衡条件严格平衡平衡因子∈{-1,0,1}相对平衡红黑性质查找效率更快高度更低稍慢插入/删除效率较慢可能需要更多旋转更快旋转频率更频繁较少适用场景频繁查找较少修改频繁修改较少查找7.2 与普通二叉搜索树的比较特性普通BSTAVL树最坏情况高度O(n)O(log n)查找效率O(n)O(log n)插入效率O(n)O(log n)删除效率O(n)O(log n)空间开销较小较大存储平衡因子8. 实现代码示例以下是一个简单的AVL树Python实现classAVLNode:def__init__(self,key):self.keykey self.leftNoneself.rightNoneself.height1classAVLTree:def__init__(self):self.rootNonedefget_height(self,node):ifnotnode:return0returnnode.heightdefget_balance(self,node):ifnotnode:return0returnself.get_height(node.left)-self.get_height(node.right)defright_rotate(self,y):xy.left T2x.right# 旋转x.righty y.leftT2# 更新高度y.height1max(self.get_height(y.left),self.get_height(y.right))x.height1max(self.get_height(x.left),self.get_height(x.right))returnxdefleft_rotate(self,x):yx.right T2y.left# 旋转y.leftx x.rightT2# 更新高度x.height1max(self.get_height(x.left),self.get_height(x.right))y.height1max(self.get_height(y.left),self.get_height(y.right))returnydefinsert(self,root,key):# 1. 执行标准BST插入ifnotroot:returnAVLNode(key)ifkeyroot.key:root.leftself.insert(root.left,key)elifkeyroot.key:root.rightself.insert(root.right,key)else:# 重复键不插入returnroot# 2. 更新高度root.height1max(self.get_height(root.left),self.get_height(root.right))# 3. 获取平衡因子balanceself.get_balance(root)# 4. 如果不平衡进行四种情况的旋转# LL情况ifbalance1andkeyroot.left.key:returnself.right_rotate(root)# RR情况ifbalance-1andkeyroot.right.key:returnself.left_rotate(root)# LR情况ifbalance1andkeyroot.left.key:root.leftself.left_rotate(root.left)returnself.right_rotate(root)# RL情况ifbalance-1andkeyroot.right.key:root.rightself.right_rotate(root.right)returnself.left_rotate(root)returnrootdefmin_value_node(self,node):currentnodewhilecurrent.left:currentcurrent.leftreturncurrentdefdelete(self,root,key):# 1. 执行标准BST删除ifnotroot:returnrootifkeyroot.key:root.leftself.delete(root.left,key)elifkeyroot.key:root.rightself.delete(root.right,key)else:# 节点只有一个子节点或没有子节点ifnotroot.leftornotroot.right:temproot.leftifroot.leftelseroot.rightifnottemp:# 没有子节点temproot rootNoneelse:# 一个子节点roottempelse:# 节点有两个子节点获取中序后继tempself.min_value_node(root.right)root.keytemp.key root.rightself.delete(root.right,temp.key)# 如果树只有一个节点直接返回ifnotroot:returnroot# 2. 更新高度root.height1max(self.get_height(root.left),self.get_height(root.right))# 3. 获取平衡因子balanceself.get_balance(root)# 4. 如果不平衡进行四种情况的旋转# LL情况ifbalance1andself.get_balance(root.left)0:returnself.right_rotate(root)# LR情况ifbalance1andself.get_balance(root.left)0:root.leftself.left_rotate(root.left)returnself.right_rotate(root)# RR情况ifbalance-1andself.get_balance(root.right)0:returnself.left_rotate(root)# RL情况ifbalance-1andself.get_balance(root.right)0:root.rightself.right_rotate(root.right)returnself.left_rotate(root)returnrootdefpre_order(self,root):ifnotroot:returnprint(f{root.key},end)self.pre_order(root.left)self.pre_order(root.right)9. 应用场景AVL树适用于以下场景需要频繁查找的操作对查找效率要求较高的应用数据相对静态修改操作较少的场景需要保证最坏情况性能的应用10. 优缺点总结10.1 优点严格的平衡性确保最坏情况下的对数时间复杂度查找效率高高度平衡保证了快速的查找操作实现相对简单相比其他平衡树AVL树的实现较为直观空间效率较高相比B树等AVL树在内存中的存储效率更高10.2 缺点插入和删除效率较低需要频繁进行旋转操作旋转操作复杂实现起来比红黑树更复杂适用场景有限对于频繁修改的数据红黑树可能更合适11. 总结AVL树是计算机科学中重要的数据结构通过严格的平衡条件保证了高效的操作性能。虽然现代应用中红黑树更为常见但AVL树在需要极致查找效率的场景中仍然具有重要价值。理解AVL树的工作原理有助于深入掌握平衡二叉搜索树的概念为学习更复杂的树结构奠定基础。AVL树的自平衡机制体现了计算机科学中空间换时间的思想通过维护额外的平衡信息来保证操作的效率是数据结构设计中的经典范例。

更多文章