AVL Tree:自平衡二叉树¶
AVL-Tree的定义&性质¶
- AVL-Tree:全称Adelson-Velsky and Landis tree, 是由这两位数学家提出的自平衡二叉搜索树(self-balancing binary search tree)
- 性质:
- 满足BST的所有性质
- 树中每个节点的左右子树高度差不能超过1
平衡因子(Balance factor)与高度(height)定义¶
- 平衡因子 = 左子树高度 - 右子树高度
- 在AVL-Tree中,平衡因子只能为-1,0,1
- 一旦超出范围,会发生旋转以恢复平衡
- 高度:从该节点到最远叶子节点经历的边数
失衡(unbalance)检测¶
- 当平衡因子超出了{-1,0,1}的范围时为失衡
- 具体检验过程
- 按照BST方法插入新节点
- 从插入位置向上回溯
- 对每个经过的祖先节点更新高度、计算平衡因子、判断是否失衡
- 当某个节点平衡因子变2或-2,说明该节点失衡,需要旋转
- 失衡有4种结构:LL,LR,RL,RR
旋转(rotation)¶
- 对应4种失衡情况,有四种旋转处理方法
单旋转 - 处理LL和RR型¶
-
左旋 - 处理RR失衡
对z左旋z \ y \ xy / \ z x -
右旋 - 处理LL失衡
对z右旋z / y / xy / \ x z -
完整情况下的左、右旋
-
左旋
对z左旋z / \ T1 y / \ T2 T3P.S.节点T2到z上的原因是AVLtree旋转后仍要保持BST的order,在这里是T1 < z < T2 < y < T3y / \ z T3 / \ T1 T2 -
右旋
对z右旋z / \ y T4 / \ T1 T2y / \ T1 z / \ T2 T4
-
双旋转 - 处理LR和RL型¶
- LR型 - 先左旋再右旋
z / y \ x - 先左旋y,将拐弯变直
z / x / y - 再右旋z,恢复平衡
x / \ y z - RL型 - 先右旋再左旋
z \ y / x - 先右旋y
z \ y \ x - 再左旋z,恢复1平衡
x / \ z y
操作¶
插入¶
- 像BST插入一样,找位置,比current小就往左,比current大就往右,找到空位置插入
- 从新节点的父节点开始网上,更新每个祖先的高度
height(node)=1+max(height(node.left),height(node.right)) - 对经过的每个节点计算平衡因子
balanceFactor=height(left)−height(right) - 失衡时时进行旋转操作
- 旋转完之后继续往上检查失衡节点的祖父节点
删除¶
- 和BST删除基本规则相同,不多赘述
- 删除之后,对路径上的每个节点更新高度
height(node)=1+max(height(node.left),height(node.right)) - 计算平衡因子
balance(node)=height(node.left)−height(node.right) - 按失衡情况旋转
- 由于删除后会有子树变矮,所有修复完之后可能还要继续往上修,一路检查到根
时间复杂度和高度界¶
| Operation | Time Complexity | 原因 |
|---|---|---|
| Search | (O(\log n)) | 最多沿一条根到叶的路径查找,路径长度等于树高,而 AVL 的高度是 (O(\log n)) |
| Insert | (O(\log n)) | 先按 BST 找位置,再向上更新高度并检查失衡;路径长度是 (O(\log n)),旋转是 (O(1)) |
| Delete | (O(\log n)) | 先按 BST 删除,再一路向上更新高度和重新平衡;最多检查到根,路径长度是 (O(\log n)) |
| Left Rotation | (O(1)) | 只修改常数个指针和节点高度 |
| Right Rotation | (O(1)) | 只修改常数个指针和节点高度 |
| Rebalancing at one node | (O(1)) | 对单个失衡节点的修复只涉及一次单旋或一次双旋 |
| Height of AVL Tree | (O(\log n)) | AVL 始终保持平衡,高度不会线性退化 |
- 高度界:\( h \leq 1.44\log_2(n+2) - 1.328 \)
AVL-Tree VS RBT¶
- AVL更严格,高度界更小,结构也更平衡;但是每次更新操作之后,进行平衡操作频繁,开销变大
- RBT平衡条件更宽松,且频繁操作下的调整负担小
- 适用场景
- search为主:AVL
- Insert/Delete操作为主:RBT