红黑树

发明红黑树的人是天才!


1 2-3-4 树特性

2-3-4 树是一个由下向上生成的多叉树,又名 4 阶 B 树(Balance Tree),是一种多路查找树。红黑树是一个特殊的 2-3-4 树。

2-3-4 树节点:

  • 2-节点:包含 1 个元素的节点,有 2 个子节点
  • 3-节点:包含 2 个元素的节点,有 3 个子节点
  • 4-节点:包含 3 个元素的节点,有 4 个子节点

2-3-4 树可以大大压缩树的高度,提升查找性能。

2-3-4 树的特性:

  • 元素整体上保持二叉树搜索的性质,即父节点大于左子节点,小于右子节点
  • 节点包含多个元素时,元素的排列顺序必须是从左到右从小到大
  • 所有的叶子节点都在最底层,所有的非叶子节点必须连满
  • 2-3-4 树的形成过程 [可视化工具](B-Tree Visualization (usfca.edu))

2 红黑树的特性

  • 节点分为红色和黑色
  • 树的根节点是黑色
  • 红色节点不可以相邻
  • 黑色节点可以相邻,在红黑树中,叶子节点指的是 null 节点,且认为 null 叶子节点是黑色
  • 从任何一个节点到其任何后代 null 叶子节点的路径都具有相同数量的黑色节点

3 2-3-4 树和红黑树关系

  • 2-3-4 树的查询操作像普通的二叉搜索树一样,但由于其节点元素数不确定,实现起来并不方便,一般使用它的等同变形——红黑树
  • 2-3-4 树的每一个结点都对应红黑树的一种结构,所以每一棵 2-3-4 树也都对应一棵红黑树

3.1 红黑树和 2-3-4 树的等价关系

红黑树起源于 2-3-4 树,本质上就是一颗 2-3-4 树。

  • 一个 2 节点对应的 2-3-4 树节点就是一个红黑树黑色节点
  • 一个 3 节点可以对应两种情况的红黑树节点,一种是左倾,一种是右倾,所以一个 2-3-4 树可以有多个对应的红黑树
  • 一个 4 节点对应的红黑树情况只有一种,中间节点黑色,左右节点红色
  • 裂变状态
    • 当给 4-节点再添加新节点时,新节点为红色,由于不能有两个连续的红色节点,需要将原来节点颜色互换
    • 新升元的红 3 节点作为新节点再向上回溯调整平衡,直至根节点
  • 黑色节点与它的红色子节点融合在一起,形成 1 个 B 树节点
  • 红黑树的黑色节点个数,与 4 阶 B 树的节点总个数相等
  • 在所有的 B 树节点中,永远是黑色节点是父节点,红色节点是子节点,黑色节点在中间,红色节点在两边

4 红黑树添加节点的调整

  • 在 2-节点上添加

    • 在 2-节点上添加意味着父节点一定是黑,可以直接添加
  • 在 3-节点上添加有如下几种情况

    • LL型需要调整:右旋

      LL型
    • RR型需要调整:左旋

    • LR型需要调整:先父节点左旋形成LL型,然后爷节点右旋

    • RL型需要调整:先父节点右旋形成RR型,然后爷节点左旋

    • 两种左中右型的不需要调整

  • 在4-节点上添加右如下情况

    • 4-节点新增一个元素,4-节点中间元素升级为父节点,剩下的两个元素和新增元素合并为一个3节点

    • 在红黑树中,新增节点时:新增的节点是红色,新增节点的父节点和叔叔节点也是红色,爷爷节点是黑色。调整为也爷节点变为红色,父节点和叔叔节点变为黑色,如果爷爷节点是root节点,则把也爷节点调整为黑色。如果爷爷节点的父节点也是红色,还应当递归让爷爷节点以上的节点也调整

总结为:

  • 如果是根节点,变为黑色并返回
  • 如果父节点是黑色:
    • 2-节点添加:不需要调整直接返回
  • 如果父节点是红的,叔节点空或者黑(新添加节点时叔节点一定为空,但往上回溯时叔节点可能为黑)
    • 3-节点添加:LL、LR、RL、RR
  • 如果父节点、叔节点都是红色
    • 4-节点添加:父节点叔节点变黑色,爷节点变红色,如果爷节点的父节点也是红色,则还需要递归调用让爷节点以上的节点继续调整

5 红黑树删除节点的调整

5.1 删除节点的情况

  • 删除非null的叶子节点
    • 如果该叶子节点是红色,可以直接删除
    • 如果该叶子节点是黑色,删除后会导致黑高失衡,需要进行平衡调整
  • 删除只有一个叶子节点的节点
    • 此时该目标删除节点一定是黑色,其叶子节点一定是红色,否则无法满足红黑树性质
    • 删除时将红色叶子节点的值复制到目标删除节点中,将删除节点转换为删除红色叶子节点
  • 删除有两个子节点的节点
    • 使用前驱或后继节点作为删除节点的替代节点,转换为1或2的情况

5.2 删除节点的辅助方法

在删除有两个子节点的节点时,需要寻找前驱和后继节点。获得替代节点的目的是减少调整次数。

  • 先找前驱节点,如果前驱节点满足以下任意一种情况,则直接返回前驱节点
    • 前驱节点是红色叶子节点
    • 前驱节点是有一个红色叶子节点的黑节点
  • 否则返回后继节点

5.3 删除节点的步骤

  1. 没找到删除节点则直接返回
  2. 如果删除节点是唯一一个节点,则root置为null
  3. 删除有两个子节点的节点
    1. 使用前驱或后继节点作为替换的删除节点
    2. 将delNode指向替换节点,转换为4或5处理
  4. 删除只有一个子节点的节点时,删除节点只能是黑色,其子节点为红色
    1. 将红色叶子节点的值复制到目标删除节点
    2. 将目标删除节点转换为删除红色叶子节点
  5. 删除叶子节点
    1. 对要删除的黑色叶子节点进行调整
    2. 删除红黑两种叶子节点

5.4 删除节点后调整平衡

D-删除节点;P-父节点;B-兄弟节点;NL-左侄子节点;NR-右侄子节点;G-爷爷节点;U-叔叔节点;紫色表示可能是红也可能是黑

  • 删除黑色叶子节点

    • 如果这是树中唯一一个节点,直接删除

    • 兄弟节点是红色

      • 删除右子节点需要右旋

      • 兄弟和右侄颜色互换

  • 兄弟节点是黑色

    • 兄弟有红色子节点

      • 兄弟有红色左子节点

        • LL型:父节点右旋
        • 变色:恢复删除前各位置的颜色:爷孙变黑,兄变父色
      • 兄弟有红色右子节点

        • LR型,先左旋后右旋
        • 变色:恢复删除前各位置的颜色 - 侄变父色,父变黑色
        兄弟有红色子节点
    • 兄弟无红色子节点

      • 父节点是红色:父变黑,兄变红

      • 父节点是黑色:将兄弟染红,然后以父节点为基准(新删除节点)向上递归调整,直至遇到红色父节点并将其染黑或者遇到根节点

5.5 删除节点后的旋转类型

  • 旋转类型看兄弟节点(黑色)及其红色子节点的位置

  • 因为要兼顾到向上回溯调用调整,所以相关类型定义如下

5.6 总结

  • 删除黑色节点调整

    • 兄弟黑
      • 兄弟有子
        • LL、LR、RR、RL
      • 兄弟无子
        • 父是黑
        • 父是红
    • 兄弟红
      • 删左子
      • 删右子
  • 口诀

    • 是根节点:直接染黑即可
    • 兄弟黑色
      • 兄弟有子:黑不够,侄来凑
        • 根据LL、LR、RL、RR类型旋转来调整
      • 兄弟无子:兄无后,父红头
        • 父节点是红色:父变黑,兄变红
        • 父节点是黑色:父作为新的删除(调整)节点向上递归调整
    • 兄弟红色
      • 兄弟红,旋黑中;随父侄,黑变红
        • 兄弟是左子树:右旋-右侄变红
        • 兄弟是右子树:左旋-左侄变红

作者

苏维埃不喝可乐

发布于

2024-11-19

更新于

2024-11-19

许可协议