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 树 或哈希表

七、总结

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

相关推荐
用户3126874877201 小时前
ConcurrentHashMap 怎么保证线程安全?从分段锁到 CAS+synchronized
java
vipxieliang1 小时前
ValidX vs Apache Commons Validator:功能与性能对比
java·spring boot
SimonKing1 小时前
升级Spring Boot 4后,从 Jackson 2 到 3,到底有哪些变化
java·后端·程序员
ikun_文2 小时前
Django框架路由Router的使用
python·pycharm·django
IvanCodes2 小时前
Python 基础语法(二):字符串与常用操作
python
昭昭日月明2 小时前
LangChain 生态:从链到代理,开发者需要掌握的三大核心
python·langchain·agent
Csvn2 小时前
🐍 Day 8:面向对象编程
后端·python
程序员天天困2 小时前
向量检索不准怎么办:混合检索与 Rerank 重排序召回优化实战
后端·python·ai编程
吃饱了得干活2 小时前
一篇讲清楚Spring Boot:自动装配、启动器、过滤器、拦截器、设计模式
java·spring boot·后端
alphaTao3 小时前
LeetCode 每日一题 2026/8/24-2026/8/30
python·算法·leetcode