数据结构(混合式)23-24-1 AVL树 复习笔记
本资料由 @BlockLune 整理,课本为《数据结构(C 语言)第 2 版 慕课版》2020 年 2 月第 2 版,2022 年 12 月第 11 次印刷。
注意:
- 本资料知识点来自于对应的复习 PPT,但具体实现更多参考自 Princeton Algs4、GeeksforGeeks 的内容。这导致文中的实现并不一定与课本实现完全一致。
- 本资料免费分享于 NJUPTFreeExams,请勿商业使用!如有错别字等错误,请在 Issues 中提出,感谢!
什么是 AVL 树
AVL 树是一种自平衡的二叉搜索树(BST),对于其中的每个结点,它的左子树和右子树的高度差均不会超过 1。
为什么需要 AVL 树
大多数对 BST 进行的操作操作(如搜索、最大值、最小值、插入、删除…等)都需要 时间,其中 h 是 BST 的高度。对于倾斜的二叉树,这些操作的成本可能会变成 。如果我们确保在每次插入和删除后,树的高度都保持 ,那么我们就能保证所有这些操作的上限都是 。AVL 树就确保了这一点,使对它进行的操作能在 的复杂度下进行。
插入操作
我们必须确保插入新节点后的 AVL 树仍然是平衡的,即“左节点 < 根节点 < 右节点”。这是通过两种操作来实现的:
- 左旋(Left Rotation)
- 右旋(Right Rotation)
插入操作的参考步骤
- 记新插入的节点为
w
,将w
照常插入 BST。 - 从
w
开始向根遍历,找到第一个非平衡节点,记为z
。记在从w
到z
的路径上的z
的儿子为y
,孙子为x
。 - 对四种可能的情形,通过旋转操作,重新平衡以
z
为根的子树。
四种可能的情形
下边符号表示中,T1、T2、T3 和 T4 都是子树。
左左
左左情形:y
是 z
的左孩子,x
是 y
的左孩子
左右
左右情形:y
是 z
的左孩子,x
是 y
的右孩子
右右
右右情形:y
是 z
的右孩子,x
是 y
的右孩子
右左
右左情形:y
是 z
的右孩子,x
是 y
的左孩子
删除操作
类似于插入操作,我们仍然需要借助旋转操作来让 AVL 树保持平衡。
删除操作的参考步骤
- 记需要删除的节点为
w
,将w
照常从 BST 中删除。 - 从
w
开始向根遍历,找到第一个非平衡节点,记为z
。将z
的较高的孩子记为y
, 将y
的较高的孩子记为x
。(注意此处的记法与插入操作不同) - 对四种可能的情形,通过旋转操作,重新平衡以
z
为根的子树。四种可能情形及调整方法与插入操作中的完全相同。 - 注意:与插入操作不同,调整完以
z
为根的子树的平衡性后,可能需要继续向上遍历调整以z
的祖先为根的子树的平衡性,直到调整完整棵树的平衡性。
各操作的复杂度
操作 | 时间复杂度 | 空间复杂度 |
---|---|---|
查找元素 | ||
插入元素 | ||
删除元素 | ||
查找最小元素 | ||
查找最大元素 | ||
查找前驱元素 | ||
查找后继元素 | ||
旋转操作(左旋和右旋) | ||
平衡因子更新 |