红黑树

106 阅读3分钟

红黑树是一种高效的自平衡二叉搜索树,能够在插入、删除等操作后通过特定规则保持近似平衡,从而保证最坏情况下 (O(\log n)) 的时间复杂度。以下是其核心要点详解:


一、红黑树的五大性质

  1. 节点颜色:每个节点是红色或黑色。
  2. 根节点:根必须是黑色。
  3. 叶子节点:所有叶子(NIL节点,空节点)均为黑色。
  4. 红色节点规则:红色节点的子节点必须是黑色(不存在连续红色节点)。
  5. 黑高一致性:从任意节点到其所有叶子节点的路径中,黑色节点数量(黑高)相同。

二、红黑树的设计目标

  • 通过约束节点颜色和路径黑高,确保最长路径不超过最短路径的2倍,避免极端不平衡。
  • 平衡调整代价低于AVL树,适合频繁插入/删除的场景(如Linux进程调度、Java TreeMap、C++ std::map)。

三、红黑树的核心操作

1. 旋转(Rotation)

  • 左旋:以某节点为支点,将其右子节点提升为父节点。
  • 右旋:以某节点为支点,将其左子节点提升为父节点。
  • 作用:调整子树高度,不破坏二叉搜索树性质。

2. 插入(Insertion)

  • 步骤

    1. 按二叉搜索树规则插入新节点(初始颜色为红色)。
    2. 若破坏红黑树规则,通过变色和旋转修复。
  • 修复策略(根据父节点、叔节点颜色):

    • 叔节点为红色:变色(父、叔变黑,祖父变红),向上递归处理。
    • 叔节点为黑:旋转(左/右旋)后调整颜色。

3. 删除(Deletion)

  • 步骤

    1. 找到待删除节点,若有两个非叶子子节点,用后继节点替换。
    2. 删除节点后,若破坏规则(如黑高变化),通过旋转和变色修复。
  • 修复策略(关注兄弟节点颜色和子节点情况):

    • 兄弟节点为红色:旋转后调整颜色。
    • 兄弟节点为黑色且其子节点为黑:变色并向上递归。
    • 兄弟节点为黑且存在红色子节点:旋转并调整颜色。

四、时间复杂度

  • 插入/删除/查找:均 (O(\log n))。
  • 调整操作:插入最多2次旋转,删除最多3次旋转。

五、红黑树 vs AVL树

特性红黑树AVL树
平衡严格度近似平衡(最长路径≤2倍最短)严格平衡(高度差≤1)
插入/删除效率更高(调整次数少)较低(频繁旋转)
查找效率稍低(高度略高)更高(高度最小化)
典型应用频繁修改的场景(如Map)频繁查询的场景(如数据库)

六、应用场景

  1. 关联容器:C++ std::map、Java TreeMap
  2. 内核调度:Linux虚拟内存管理、进程调度。
  3. 数据库索引:部分数据库的索引结构。

七、红黑树示例(插入修复)

假设插入节点为红色,导致父节点也为红色:

  1. Case 1:叔节点为红

    • 父、叔变黑,祖父变红,递归处理祖父节点。
  2. Case 2:叔节点为黑,且插入节点在父节点的异侧

    • 先旋转父节点,转化为Case 3。
  3. Case 3:叔节点为黑,且插入节点在父节点的同侧

    • 旋转祖父节点,交换父和祖父颜色。

八、总结

红黑树通过颜色标记和旋转策略,在保证高效查询的同时,降低了插入/删除的调整代价,是工程中广泛使用的平衡树结构。理解其核心规则与调整策略是掌握红黑树的关键。