Java随笔-红黑树

红黑树(Red-Black Tree)

红黑树是一种自平衡二叉搜索树(Self-balancing Binary Search Tree) ,由 Rudolf Bayer 于 1972 年发明。它通过在节点上增加一个"颜色"属性(红或黑),并在插入和删除时遵循特定规则,确保树始终保持近似平衡,从而保证查找、插入、删除操作的时间复杂度都是 O(log n)。

一、五条核心性质(必须同时满足)

复制代码
性质1:每个节点要么是红色,要么是黑色
性质2:根节点必须是黑色
性质3:所有叶子节点(NIL/空节点)都是黑色
性质4:红色节点的两个子节点必须是黑色(不能有两个连续的红节点)
性质5:从任一节点到其每个叶子节点的所有简单路径上,黑色节点数量相同(黑高相同)

性质5 是红黑树的灵魂------它保证了最长路径不超过最短路径的 2 倍,从而确保树不会严重倾斜。

二、为什么需要红黑树

普通二叉搜索树的问题

复制代码
        10              10
       /                  \
      5                    15
     /                       \
    3                         20
   /                            \
  1                              25
                                 /
                                22
                                
左图:平衡BST,查找 O(log n)      右图:退化成链表,查找 O(n)

如果按 1, 3, 5, 10, 15, 20, 25 顺序插入,普通 BST 会退化成链表,查找效率变成 O(n)。

红黑树的平衡效果

红黑树通过旋转 + 变色 在插入/删除时自动调整,始终保持近似平衡

复制代码
        [10B]                    [10B]
       /     \                  /     \
     [5R]    [15R]           [5B]     [20B]
    /   \    /    \          /   \    /    \
  [3B] [7B][13B] [20B]    [3R] [7R][15R] [25R]

三、自平衡机制

1. 插入操作

新节点总是以红色 插入(如果插黑色会破坏性质5的黑高平衡)。

插入后可能违反性质4(出现连续红节点),需要修复:

情况 修复方式
叔叔节点是红色 父、叔变黑,祖父变红,向上递归
叔叔是黑色,且新节点是"内侧" 对父节点旋转,转化为外侧情况
叔叔是黑色,且新节点是"外侧" 对祖父节点旋转,父、祖父变色

示例:插入 4 到以下树中

复制代码
    [7B]              [7B]              [7B]              [5B]
   /    \            /    \            /    \            /    \
 [3B]  [10B]  →   [3R]  [10B]  →   [5B]  [10B]  →   [3R]  [7R]
 /                /   \            /   \              /
[1B]            [1B] [4R]       [3B] [4R]          [1B]

2. 删除操作

删除更复杂,核心思路是:

  • 如果删除的是红节点,直接删,不影响黑高
  • 如果删除的是黑节点,会导致该路径黑高减1,需要通过旋转 + 变色 + 兄弟节点借调来恢复平衡

四、时间复杂度

操作 平均 最坏
查找 O(log n) O(log n)
插入 O(log n) O(log n)
删除 O(log n) O(log n)

为什么最坏也是 O(log n)?

由性质5可知:从根到叶子的最短路径全是黑节点,最长路径是红黑交替。

如果树高为 h,最短路径黑节点数 ≥ h/2。

设黑高为 bh,则 n ≥ 2^bh - 1,因此 h ≤ 2log(n+1)。

所以树高最多是 2log(n),查找最多走 2log(n) 步。

五、实际应用场景

红黑树是许多系统核心数据结构的基石:

应用 说明
Java TreeMap / TreeSet 基于红黑树实现的有序映射/集合
Java HashMap(JDK 8+) 链表长度 > 8 时转为红黑树,优化哈希冲突
Linux 内核 完全公平调度器(CFS)使用红黑树管理进程
C++ std::map / std::set 大多数实现(如 GCC)使用红黑树
Epoll / Nginx 管理大量文件描述符的事件
数据库索引 部分内存数据库使用红黑树作为索引结构

六、红黑树 vs AVL 树

对比项 红黑树 AVL 树
平衡度 近似平衡(高度 ≤ 2log n) 严格平衡(高度 ≤ 1.44log n)
查找速度 稍慢(树更高) 更快(树更矮)
插入/删除调整 旋转次数少(O(1) 次旋转) 旋转次数多(O(log n) 次旋转)
适用场景 插入删除频繁 查找频繁、数据静态
实现复杂度 较复杂 更复杂

选型建议

  • 数据变动频繁(如任务调度、实时系统)→ 红黑树
  • 数据基本不变,查询极多(如字典、配置表)→ AVL 树 或哈希表

七、总结

红黑树是一种通过"红节点不能相邻"和"黑高相同"两条规则来约束树高的自平衡二叉搜索树。它牺牲了一定的绝对平衡性,换取了更少的旋转次数,使得插入和删除操作更高效,成为工程实践中应用最广泛的平衡树。

相关推荐
weixin199701080161 天前
《二手ERP对接闲鱼API:聚石塔强制入塔后的架构重构实录》(附Python源码)
python
小白快快跑哦1 天前
python-字符串全解(六):正则表达式-转义与非转义
python·正则表达式·转义与非转义
智慧物业老杨1 天前
物业日常巡查的数智化重构:从“打卡式巡检“到“闭环式风控“
android·java·人工智能·系统架构·rxjava
晴天的雨.9921 天前
【C++算法】和为s的两个数
开发语言·数据结构·c++·算法
IvanCodes1 天前
Python 数据处理(十三):JSON、CSV 与数据序列化
开发语言·python
Patrick在香港1 天前
Claude 工具调用返回空:8 次失败里只有 1 次状态码不对,其余全带 200
爬虫·python·api·claude·香港
步行cgn1 天前
Spring c 命名空间注入详解
java·后端·spring
Web3&Basketball1 天前
CRM Agent 后训练实战:3 倍更少错误
python·架构·大模型·agent·推理
明月_清风1 天前
Maven 到底是什么?一篇文章搞懂 Java 项目构建与依赖管理
java·后端·maven
aramae1 天前
MySQL复合查询(8)
java·c语言·开发语言·后端·算法