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

七、总结

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

相关推荐
高级程序源9 小时前
django校园寻物通失物招领平台32261-计算机课程设计、毕业设计
vue.js·python·mysql·小程序·django·flask·课程设计
WeiXin_DZbishe9 小时前
基于springboot宠物领养系统-计算机毕设 附源码【课程设计】94217
vue.js·spring boot·python·django·php·课程设计
码爸9 小时前
线性回归算法
算法·机器学习·线性回归
kimnoic9 小时前
Python数据库学习心得:SQLite、MySQL、PostgreSQL优缺点
开发语言·python
snhna9 小时前
向量数据库深度实战:从 HNSW 到 pgvector、Milvus 选型与 RAG 落地
数据库·人工智能·python·postgresql·milvus
Coder-magician9 小时前
《代码随想录》刷题打卡day51:图论-part09(dijistra堆优化,Bellman_ford算法)
算法·图论
Nil2089 小时前
leetcode 763划分字母区间
算法·leetcode·职场和发展
不会就选b10 小时前
算法日常・每日刷题--<动态规划>20
算法·leetcode·动态规划
别动我齐刘海10 小时前
C++ 工程化学习
java·linux·前端·c++·学习·机器学习·机器人
必须得开心呀10 小时前
python编写带界面的软件,需要安装哪些插件
开发语言·python