🌳 1、简述
红黑树是一种自平衡二叉查找树(Self-Balancing Binary Search Tree),被广泛应用于操作系统调度、Java集合、数据库索引等核心模块中。本文将从 基本原理 入手,结合 实际应用场景与代码实例,带你全面理解红黑树的精髓。
代码样例:https://gitee.com/lhdxhl/algorithm-example.git
📘 2、什么是红黑树?
红黑树是一种特殊的二叉查找树(BST),其核心目的是通过维护“颜色约束”来实现平衡,从而提高插入、查找和删除操作的效率。
红黑树的每个节点除了值和左右指针外,还会包含一个颜色字段(红
或 黑
)。
🎯 红黑树的五大性质
- 每个节点不是红色就是黑色。
- 根节点是黑色。
- 所有叶子节点(NIL)都是黑色的(虚拟叶子节点)。
- 若一个节点是红色,则其子节点必须是黑色(红色节点不能相邻)。
- 从任一节点到其叶子节点的所有路径上,黑色节点数量相同。
✅ 这些性质共同确保了树的“近似平衡”,从而使红黑树操作的时间复杂度保持在:
- 查找:O(log n)
- 插入:O(log n)
- 删除:O(log n)
🔧 3、红黑树的操作(核心逻辑)
📥 插入操作流程
- 插入节点为红色,作为 BST 插入。
- 若父节点为黑色,插入完成。
- 若父节点为红色,需通过旋转(左旋/右旋)+变色保持平衡。
- 最终保持根节点为黑色。
📤 删除操作流程
删除较复杂,需要考虑:
- 替代节点颜色是否影响黑平衡;
- 是否需要旋转或变色修复结构;
- 若删除的是黑节点,需额外修复。
🧪 3、实践样例
用 Java 手写简化版红黑树:
public class RedBlackTree<K extends Comparable<K>, V> {
private static final boolean RED = true;
private static final boolean BLACK = false;
private class Node {
K key;
V value;
Node left, right;
boolean color;
Node(K key, V value, boolean color) {
this.key = key;
this.value = value;
this.color = color;
}
}
private Node root;
// 判断节点是否为红色
private boolean isRed(Node node) {
return node != null && node.color == RED;
}
// 左旋
private Node rotateLeft(Node h) {
Node x = h.right;
h.right = x.left;
x.left = h;
x.color = h.color;
h.color = RED;
return x;
}
// 右旋
private Node rotateRight(Node h) {
Node x = h.left;
h.left = x.right;
x.right = h;
x.color = h.color;
h.color = RED;
return x;
}
// 颜色翻转
private void flipColors(Node h) {
h.color = RED;
h.left.color = BLACK;
h.right.color = BLACK;
}
// 插入
public void put(K key, V value) {
root = put(root, key, value);
root.color = BLACK;
}
private Node put(Node h, K key, V value) {
if (h == null) return new Node(key, value, RED);
int cmp = key.compareTo(h.key);
if (cmp < 0) h.left = put(h.left, key, value);
else if (cmp > 0) h.right = put(h.right, key, value);
else h.value = value;
if (isRed(h.right) && !isRed(h.left)) h = rotateLeft(h);
if (isRed(h.left) && isRed(h.left.left)) h = rotateRight(h);
if (isRed(h.left) && isRed(h.right)) flipColors(h);
return h;
}
public V get(K key) {
Node x = root;
while (x != null) {
int cmp = key.compareTo(x.key);
if (cmp < 0) x = x.left;
else if (cmp > 0) x = x.right;
else return x.value;
}
return null;
}
}
下面是基于上面实现的 RedBlackTree 类的使用样例,帮助你理解红黑树在 Java 中的基本操作与实际应用场景:
public class RedBlackTreeExample {
public static void main(String[] args) {
RedBlackTree<Integer, String> tree = new RedBlackTree<>();
// 插入元素
tree.put(10, "十");
tree.put(5, "五");
tree.put(15, "十五");
tree.put(1, "一");
tree.put(7, "七");
// 查询元素
System.out.println("key=7 -> " + tree.get(7)); // 输出: 七
System.out.println("key=10 -> " + tree.get(10)); // 输出: 十
System.out.println("key=20 -> " + tree.get(20)); // 输出: null(不存在)
}
}
💡 4、应用场景
应用场景 | 使用说明 |
---|---|
🔠 Java 的 TreeMap / TreeSet | 使用红黑树实现有序键值对集合 |
🧠 Linux CFS(完全公平调度器) | 使用红黑树调度任务时间片 |
🗂 数据库索引(如 PostgreSQL) | 作为内存结构实现 B-Tree 之前的数据排序 |
🧬 内核内存管理 | 设备地址映射、区域管理等 |
🔍 红黑树 vs 其它平衡树对比
数据结构 | 插入复杂度 | 是否自平衡 | 应用代表 |
---|---|---|---|
AVL树 | O(log n) | 是 | 少见、用于内存索引 |
红黑树 | O(log n) | 是(弱平衡) | TreeMap、Linux |
B+ 树 | O(log n) | 是 | 数据库索引 |
跳表(SkipList) | O(log n) | 是(概率) | Redis |
🧭 5、总结
红黑树的最大优点就是在保持结构平衡的同时,又能保证高效的增删查性能,是大规模数据结构的核心基石。
✨ 学完你可以掌握:
- 红黑树的原理与五大性质
- 插入操作过程中的旋转与变色
- 实际代码实现简化版红黑树
- 常见业务中红黑树的落地应用
📂 附:可选扩展方向
- 实现红黑树删除操作
- 结合
java.util.TreeMap
调试源码 - 使用红黑树管理区间(如IP段、时间段)
如果你对红黑树的图解可视化、动画讲解或 C++ 实现也感兴趣,我可以为你定制进一步内容!
是否需要将该博客生成 PDF、Markdown 或部署在 Hugo/Hexo 博客模板中?我可以帮你一键生成。
评论区