平衡树

搜索二叉树

概念

术语 说明
节点含有的子树的个数称为该节点的度
树的度 最大的节点度称为树的度
叶节点 度为零的节点
深度 对于任意节点 nn 的深度为从根到 n 的唯一路径长,根的深度为 0
高度 对于任意节点 nn 的高度为从 n 到一片树叶的最长路径长,所有树叶的高度为 0
森林 由 m(m>=0) 棵互不相交的树的集合称为森林
堂兄弟节点 同层的节点互为堂兄弟节点
兄弟节点 相同父节点的节点互称为兄弟节点
节点的祖先 从根到该节点所经分支上的所有节点
根据父节点被遍历输出的顺序 可以分为先序遍历,中序遍历,后序遍历
红黑树的路径 从根节点到空节点被成为一条路径

二叉搜索(排序)树

构成条件:

  • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值。

  • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值。

  • 左右子树也分别为二叉搜索树。

性质

  • 当在二叉搜索树当中搜索数据的时候,最多搜索高度次——O(n),此时退化为单支,当二叉树平衡时,使用O(logn)时间

注意

  • 不允许存在重复节点

  • 在代码实现时,需要记录其父节点。

  • 中序遍历有序,并且由于优先遍历当前最小节点,所以也是升序的。

删除节点

  1. 当需要删除的节点为叶节点,直接删除即可。
  2. 当要删除的节点只有一个子节点,将待删除节点替换为其子节点即可
  3. 当待删除节点的度为2时:
    • 找到待删除节点在“中序遍历序列”中的下一个节点,记为 tmp 。
    • 用 tmp 的值覆盖待删除节点的值,并在树中递归删除节点 tmp 即可——删除叶子节点。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/* 删除节点 */
void remove(int num) {
// 若树为空,直接提前返回
if (root == nullptr)
return;
TreeNode *cur = root, *pre = nullptr;
// 循环查找,越过叶节点后跳出
while (cur != nullptr) {
// 找到待删除节点,跳出循环
if (cur->val == num)
break;
pre = cur;
// 待删除节点在 cur 的右子树中
if (cur->val < num)
cur = cur->right;
// 待删除节点在 cur 的左子树中
else
cur = cur->left;
}
// 若无待删除节点,则直接返回
if (cur == nullptr)
return;
// 子节点数量 = 0 or 1
if (cur->left == nullptr || cur->right == nullptr) {
// 当子节点数量 = 0 / 1 时, child = nullptr / 该子节点
TreeNode *child = cur->left != nullptr ? cur->left : cur->right;
// 删除节点 cur
if (cur != root) {
if (pre->left == cur)
pre->left = child;
else
pre->right = child;
} else {
// 若删除节点为根节点,则重新指定根节点
root = child;
}
// 释放内存
delete cur;
}
// 子节点数量 = 2
else {
// 获取中序遍历中 cur 的下一个节点
TreeNode *tmp = cur->right;
while (tmp->left != nullptr) {
tmp = tmp->left;
}
int tmpVal = tmp->val;
// 递归删除节点 tmp
remove(tmp->val);
// 用 tmp 覆盖 cur
cur->val = tmpVal;
}
}

AVL树(作者命名)

AVL 树既是二叉搜索树,也是平衡二叉树

构成条件

  • 它的左右子树都是AVL树。
  • 左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1),从而可以防止二叉搜索树的退化。

注意

  1. AVL 树的相关操作需要获取节点高度
  2. 节点高度”是指从该节点到它的最远叶节点的距离
  3. 叶节点的高度为0,而而空节点的高度为 -1

平衡因子

节点平衡因子 = 左子树高度 - 右子树高度

对于一棵 AVL 树的任意节点的平衡因子始终保持在[-1,-1]区间。

AVL 树旋转

平衡因子绝对值大于1时,对应的节点就被称为“失衡节点”。根据失衡情况的不同,又有不同的平衡方式:

  • 左旋转:将失衡节点旋转到右子节点的左子节点位置。——LL

  • 右旋转:将失衡节点旋转到左子节点的右子节点位置。——RR

对于左旋来说,如果它的右子树存在,那么:

  • 右子树会代替失衡节点的位置,并且将失衡节点作为自身的左子树

  • 右子树本身的左子树,将会被嫁接到失衡节点的右子树位置

左旋

右旋则是以上操作的镜像

  • 先左(右)旋后右(左)旋——LR(RL)

需要旋转两次,旋转方向和顺序与类型名称相同,也就是 LR 先左旋后右旋,RL 先右旋后左旋

  • 步骤一:将新增节点的父节点,安插在根节点和根节点的左子节点之间。(谋权)

  • 步骤二:然后将根节点变为它的空侧的子节点(篡位),然后将原新增的节点(就是被抛弃的子节点),变换原来的方向,嫁接在新根节点的子节点上(变节)

调整后的子树的根节点一定是新增节点的父节点,所以称之为谋权篡位

先左旋再右旋

如何选择平衡?

  • LL:插入一个新节点到根节点的左子树(Left)的左子树(Left),导致根节点的平衡因子由 1 变为 2。

  • RR:插入一个新节点到根节点的右子树(Right)的右子树(Right),导致根节点的平衡因子由 -1 变为 -2。

  • LR:插入一个新节点到根节点的左子树(Left)的右子树(Right),导致根节点的平衡因子由 1 变为 2。

  • RL:插入一个新节点到根节点的右子树(Right)的左子树(Left),导致根节点的平衡因子由 -1 变为 -2。

例题验证

例题

运用场景

由于AVL树需要旋转来保持平衡,而旋转是非常耗时的。因此:

  • 适合用于插入 删除次数比较少,但查找多的情况。

红黑树(颜色命名)

红黑树平衡变换

通过对任何一条从根到叶子的路径上各个节点着色的方式的限制。

性质

  1. 红黑树中,NIL节点(空叶子节点)为黑色

  2. 节点为红色或黑色,且一个节点是红色的,那它的孩子必须是黑的。 —— 任何路径没有连续的红色节点。

  3. 根节点必须是黑色

  4. 红黑树确保最长路径不会超过最短路径的两倍,且红黑树不是严格平衡。 —— 高效的关键

  5. 每条路径,均包含相同数目的黑色节点

  6. 任何不平衡都会在三次旋转之内调整完毕

插入

  • 插入红色节点而不是黑色节点,因为插入黑色节点会影响性质 5,对其它路径产生影响。

  • 而且,如果当插入的节点的父节点是黑色的时候,那么就是完全正确的插入。但如果父节点是红色,那么会违反性质2,此时要进行调整)

如何平衡,旋转?详情——红黑树平衡变换

使用场景:

红黑树多用于搜索、插入、删除操作多的情况。


平衡树
https://weihehe.top/2024/07/01/二叉树-1/
作者
weihehe
发布于
2024年7月1日
许可协议