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

七、总结

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

相关推荐
fanruitian5 小时前
python 机器学习 交叉验证train_test_split 网格搜索GridSearchCV
开发语言·python·机器学习
鬼手点金5 小时前
Skills:领域能力的可组合单元
java·人工智能·笔记·自动化·1024程序员节
dialect_13 小时前
KMP算法
开发语言·c++·算法
captain37613 小时前
MyBatis(入门5)其他查询操作
java·数据库·spring boot·mybatis
reikocao14 小时前
卡尔曼滤波的动态机制:P如何改变融合权重
算法
Novproxy_Z14 小时前
商用代理避坑:如何识别商家拿机房 IP 冒充住宅 IP
java·网络·tcp/ip
漂流瓶jz14 小时前
UVA-1612 猜名次 题解答案代码 算法竞赛入门经典第二版
数据结构·算法·题解·排序·aoapc·算法竞赛入门经典
前端精髓14 小时前
结构化输出with_structured_output(抽卡)
python·langchain
吞下星星的少年·-·15 小时前
Div.2 CF 1130B题(构造,贪心)
算法·贪心·构造
文丑颜不良啊15 小时前
LeetCode1481~1500题目解析
java·leetcode