红黑树插入与调整详解
一、红黑树的五大性质
红黑树是一种自平衡的二叉搜索树(BST),其核心特性如下:
- 颜色属性:每个节点非红即黑
- 根属性:根节点必须为黑色
- 叶子属性:所有的
NIL
叶子节点都是黑色 - 红节点约束:红色节点的子节点必须为黑色(即无连续红节点)
- 黑高平衡:从任一节点到其所有后代叶子节点的路径中,黑色节点数量相等
二、插入操作流程
阶段 1:标准 BST 插入
- 从根节点开始查找插入位置
- 新节点总是红色
- 按照 BST 规则插入
阶段 2:平衡修复(重点)
当插入后新节点的父节点是红色时,需要进行结构调整。核心考量因素:
- 父节点是祖父的左孩子还是右孩子
- 叔叔节点的颜色
- 新节点的插入方向(左/右)
三、调整情况详解
情况分类表
父节点位置 | 叔叔颜色 | 插入方向 | 操作类型 | 案例编号 |
---|---|---|---|---|
左子树 | 红 | - | 重新着色 | Case 1 |
左子树 | 黑 | 右孩子 | 左旋 | Case 2 |
左子树 | 黑 | 左孩子 | 右旋 + 变色 | Case 3 |
右子树 | 红 | - | 重新着色 | Case 1’ |
右子树 | 黑 | 左孩子 | 右旋 | Case 2’ |
右子树 | 黑 | 右孩子 | 左旋 + 变色 | Case 3’ |
详细调整步骤(以父节点为左孩子为例)
Case 1:叔叔为红色
- 父节点、叔叔设为黑色
- 祖父节点设为红色
- 将祖父节点作为新节点,递归向上调整
Case 2:叔叔为黑且新节点是右孩子
- 以父节点为支点进行左旋
- 转换为 Case 3 处理
Case 3:叔叔为黑且新节点是左孩子
- 父节点设为黑色
- 祖父节点设为红色
- 以祖父节点为支点进行右旋
父节点为右孩子的情况完全对称。
四、记忆技巧与口诀
三步判断法
- 看颜色:父节点为红色才需要调整
- 查叔叔:查看叔叔节点颜色
- 辨方向:判断新节点是左插还是右插
核心口诀
红叔变色向上传,
黑叔旋转看方向;
先左后右调平衡,
黑高不变记心上。
颜色标记法
- 红色节点:可能引发冲突
- 黑色节点:安全、稳定
- 新插入节点:总是红色
五、代码实现框架
def insert_fixup(tree, z):while z.parent.color == RED:if z.parent == z.parent.parent.left:uncle = z.parent.parent.rightif uncle.color == RED: # Case 1z.parent.color = BLACKuncle.color = BLACKz.parent.parent.color = REDz = z.parent.parentelse:if z == z.parent.right: # Case 2z = z.parentleft_rotate(tree, z)# Case 3z.parent.color = BLACKz.parent.parent.color = REDright_rotate(tree, z.parent.parent)else:# 对称处理:父节点为右孩子uncle = z.parent.parent.leftif uncle.color == RED: # Case 1'z.parent.color = BLACKuncle.color = BLACKz.parent.parent.color = REDz = z.parent.parentelse:if z == z.parent.left: # Case 2'z = z.parentright_rotate(tree, z)# Case 3'z.parent.color = BLACKz.parent.parent.color = REDleft_rotate(tree, z.parent.parent)tree.root.color = BLACK