1. 红黑树基础概念解析
红黑树是一种自平衡的二叉搜索树,它在1972年由鲁道夫·拜尔发明,最初被称为"对称二叉B树"。这种数据结构之所以被称为"红黑树",是因为每个节点都被标记为红色或黑色,这些颜色标记用于维护树的平衡性。
红黑树必须满足以下五个核心性质:
- 每个节点要么是红色,要么是黑色
- 根节点必须是黑色
- 所有叶子节点(NIL节点)都是黑色
- 红色节点的两个子节点都必须是黑色(即不能有两个连续的红色节点)
- 从任一节点到其每个叶子节点的所有路径都包含相同数目的黑色节点
这些性质确保了红黑树的关键特性:从根到最远叶子节点的路径长度不会超过从根到最近叶子节点路径长度的两倍。这种平衡性使得红黑树在最坏情况下仍然能保持O(log n)的时间复杂度。
提示:NIL节点在实现中通常表示为特殊的哨兵节点,它们不存储实际数据,仅作为叶子节点的占位符存在。
与AVL树相比,红黑树的平衡条件更为宽松,这使得它在插入和删除操作时需要更少的旋转操作。虽然红黑树的查找效率略低于AVL树(因为可能没有AVL树那么平衡),但在频繁修改的场景下,红黑树的整体性能更优。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 红黑树的核心操作原理
2.1 插入操作的平衡维护
红黑树的插入操作开始与普通二叉搜索树类似:首先找到适当的插入位置,然后将新节点作为红色节点插入。插入红色节点比插入黑色节点更容易满足红黑树的性质,因为它不会立即违反性质5(黑高相同)。
插入后可能出现以下三种违反红黑树性质的情况,需要通过旋转和重新着色来解决:
-
新节点的父节点是黑色:这种情况下不需要任何调整,所有性质仍然满足。
-
新节点的父节点是红色,且叔节点也是红色:
- 将父节点和叔节点变为黑色
- 将祖父节点变为红色
- 将祖父节点作为新的当前节点继续向上调整
-
新节点的父节点是红色,但叔节点是黑色或不存在:
- 如果新节点是父节点的右子且父节点是祖父节点的左子(或对称情况),先对父节点进行左旋
- 将父节点变为黑色,祖父节点变为红色
- 对祖父节点进行右旋
python复制def insert_fixup(tree, z):
while z.parent.color == RED:
if z.parent == z.parent.parent.left:
y = z.parent.parent.right
if y.color == RED:
z.parent.color = BLACK
y.color = BLACK
z.parent.parent.color = RED
z = z.parent.parent
else:
if z == z.parent.right:
z = z.parent
left_rotate(tree, z)
z.parent.color = BLACK
z.parent.parent.color = RED
right_rotate(tree, z.parent.parent)
else:
# 对称情况,将left和right互换
pass
tree.root.color = BLACK
2.2 删除操作的平衡维护
红黑树的删除操作比插入更为复杂。删除节点后,如果被删除的节点是黑色的,就会破坏红黑树的性质5(黑高相同),需要通过旋转和重新着色来恢复平衡。
删除操作的主要步骤如下:
- 执行标准BST删除:找到要删除的节点,处理其子节点数量不同的情况
- 如果被删除的节点是红色的,不需要调整
- 如果被删除的节点是黑色的,需要通过以下情况处理:
情况1:当前节点的兄弟节点是红色
- 将兄弟节点变为黑色
- 将父节点变为红色
- 对父节点进行左旋
- 更新兄弟节点
情况2:兄弟节点是黑色且其两个子节点都是黑色
- 将兄弟节点变为红色
- 将当前节点指向其父节点
情况3:兄弟节点是黑色,兄弟的左子节点是红色,右子节点是黑色
- 将兄弟的左子节点变为黑色
- 将兄弟节点变为红色
- 对兄弟节点进行右旋
- 更新兄弟节点
情况4:兄弟节点是黑色且兄弟的右子节点是红色
- 将兄弟节点的颜色设为父节点的颜色
- 将父节点设为黑色
- 将兄弟的右子节点设为黑色
- 对父节点进行左旋
- 将当前节点设为根节点
python复制def delete_fixup(tree, x):
while x != tree.root and x.color == BLACK:
if x == x.parent.left:
w = x.parent.right
if w.color == RED:
w.color = BLACK
