Files
Data-Structure/BinaryTree/BalanceTree/Red-Black Tree
2025-08-25 16:26:11 +08:00
..
2025-08-25 16:26:11 +08:00
2025-08-25 16:26:11 +08:00
2025-08-25 16:26:11 +08:00
2025-08-25 16:26:11 +08:00

[TOC]

红黑树插入思路

好的,我们把 红黑树插入的完整逻辑整理一下,分步骤、分情况讲,保证清晰易懂:


🔹 红黑树插入逻辑

1 基本步骤

  1. 普通 BST 插入

    • 按二叉搜索树的规则,把新节点 x 插入到合适位置。
    • 新节点初始化为 红色(因为插入红色节点更容易维持黑高)。
  2. 判断是否需要修复

插入新节点 z (红色)
|
+-- 父是黑色  OK,直接插入
|
+-- 父是红色
     |
     +-- 叔叔是红色  父黑叔黑,祖红,上移到祖父,继续检查
     |
     +-- 叔叔是黑色
          |
          +-- z 在父的同向(左左或右右)  Case 3,旋转 + 颜色交换
          +-- z 在父的异向(左右或右左)  Case 2,先旋转父,再变为同向,继续 Case 3
  • 如果父节点是黑色 → 红黑性质不破坏,不需要 fix。
  • 如果父节点是红色 → 违反“红色节点不能有红色子节点”,需要修复。
  • 考虑叔叔是不是红的
  • ->叔叔是红的就 一起变黑,祖父变红
  • ->叔叔不是红的,考虑旋转+变色

2 fixinsert 修复逻辑

设:

  • x = 当前插入节点
  • p = 父节点
  • u = 叔叔节点(父节点的兄弟)
  • g = 祖父节点

情况 1叔叔节点是红色

  • 条件p 是红色,u 是红色

  • 处理

    1. 父节点 p 染黑
    2. 叔叔节点 u 染黑
    3. 祖父节点 g 染红
    4. x 上移到祖父节点 g,继续循环判断
  • 原因:通过重新染色,把红红冲突上移,保持黑高不变


情况 2叔叔节点是黑色

  • 条件p 是红色,u 是黑色
  • 子情况(根据 x 在父节点的左右位置):
  1. 左-左LL

    • xp 的左孩子,pg 的左孩子

    • 处理

      1. 父节点染黑,祖父染红
      2. 右旋祖父
  2. 左-右LR

    • xp 的右孩子,pg 的左孩子

    • 处理

      1. 左旋父节点(将 LR 转化为 LL
      2. 再执行 LL 情况的右旋 + 染色
  3. 右-右RR

    • 对称 LL右孩子的右孩子插入
    • 左旋祖父 + 调整颜色
  4. 右-左RL

    • 对称 LR右孩子的左孩子插入
    • 右旋父节点 → 变成 RR → 左旋祖父 + 调整颜色

3 循环终止

  • 当父节点是黑色,或者到达根节点,循环结束
  • 最后 根节点必须染黑

🔹 总结关键点

  1. 新节点红色 → 保持黑高不变

  2. 红红冲突 → 根据叔叔颜色分两类处理:

    • 红色叔叔 → 上移染色
    • 黑色叔叔 → 旋转 + 染色
  3. 旋转 + 染色 → 只改变局部结构,保持整体 BST 和红黑性质

  4. 根节点保持黑色 → 保证树的黑高一致


如果你需要,我可以帮你画一张 红黑树插入示意图,把 LL/LR/RR/RL 四种旋转场景和颜色变化可视化,看起来非常直观。

你想让我画吗?

红黑树删除思路

好,我给你梳理一下 红黑树删除的整体思路,只讲逻辑,不贴代码:


1 找到要删除的节点

  • 首先按照普通二叉搜索树BST查找待删除节点 z
  • 如果节点不存在,就结束。

2 分情况处理节点

红黑树删除跟 BST 删除类似,分三种情况:

  1. 节点没有子节点(叶子)

    • 直接把它从父节点断开。
    • 如果节点是黑色,删除会破坏黑高,需要修复。
  2. 节点只有一个孩子

    • 用唯一的孩子替代该节点挂到父节点上。
    • 如果删除的是黑色节点,也可能破坏红黑性质,需要修复。
  3. 节点有两个孩子

    • 找该节点的 中序后继(右子树最左的节点)替代它。
    • 删除后继节点(后继最多有一个右孩子),这一步退化为情况 1 或 2。
    • 然后把被删除节点的左右孩子接到后继上,继承颜色。
    • 如果后继原本是黑色,也需要修复。

3 修复红黑树性质

  • 删除黑色节点或用黑色节点替代时,会破坏 黑高红黑性质

  • 修复核心思路:

    1. 兄弟节点红色 → 旋转并调整颜色,使兄弟变黑。
    2. 兄弟黑色,兄弟的孩子都是黑色 → 兄弟染红,把“双重黑”向上传递。
    3. 兄弟黑色,有红色侄子 → 旋转 + 染色,直接消除双重黑。
  • 修复循环一直执行,直到双重黑消除或者到达根节点。


4 特别注意

  • 根节点始终要保持黑色。
  • 删除过程尽量使用 哨兵节点 nul 替代空指针,避免每次判断 nullptr
  • 删除逻辑主要是 BST 替换 + fixdelete 修复 两步结合。

简单总结一句话就是:

“先按 BST 删除节点,再根据被删节点颜色决定是否修复,用旋转和染色处理双重黑。”

好,我们把 红黑树删除后修复的核心步骤细化讲解一下,把每种情况的逻辑和原因都拆开看。假设删除后出现的节点 x 带有 “双重黑”double black,这是修复的触发条件。


🔹 修复红黑树性质Double Black 处理)

情景概念

  • 删除或替代节点是黑色 → 破坏了红黑树的黑高。
  • 我们用 x 表示替代节点(可能是哨兵 nul)。
  • w 表示 x 的兄弟节点。

情况 1兄弟节点红色

条件w->color == RED

处理逻辑

  1. 把兄弟染黑,父节点染红。
  2. 对父节点做旋转(左旋或右旋,视 x 在左还是右)。
  3. 转换成“兄弟是黑色”的情况,进入下一轮循环处理。

原因

  • 红色兄弟意味着父节点必然是黑色(红黑性质),旋转后可以让黑高平衡,同时把问题转化为更容易处理的兄弟黑色情况。

情况 2兄弟是黑色且兄弟两个孩子都是黑色

条件w->color == BLACK && w->left->color == BLACK && w->right->color == BLACK

处理逻辑

  1. 把兄弟染红。
  2. 把 x 的双重黑向父节点传递:x = x->parent,循环继续。

原因

  • 黑高减少发生在 x 所在的路径上。
  • 兄弟的两个子节点都是黑色 → 黑高没法补偿,只能把多余的黑色“向上递归”。

情况 3兄弟是黑色且有红色侄子

条件w->color == BLACK 且至少有一个子节点红色

处理逻辑

  1. 如果 x 是左孩子:

    • case RL先对兄弟右旋让红色侄子转到右侧。
    • case RR父亲左旋同时调整父亲、兄弟和红色侄子的颜色。
  2. 对称地,如果 x 是右孩子:

    • case LR先左旋兄弟
    • case LL父亲右旋 + 染色

原因

  • 红色侄子可以“补偿”被删除黑色节点造成的黑高缺失。
  • 通过旋转和染色,双重黑立即消除,红黑树性质恢复。

🔹 循环结束条件

  • 双重黑消除x 被重新染黑或者到达根节点)。
  • 根节点必须保持黑色 → 最后再显式设置 root->color = BLACK

💡 直观理解

  1. 红兄弟 → 转化问题
  2. 黑兄弟+黑侄子 → 往上递
  3. 黑兄弟+红侄子 → 补偿黑高,立即解决

如果你想,我可以画一张 删除修复流程图,用节点颜色标注每一步的旋转和染色,直观展示三种情况。

你希望我画吗?