1. 简介
AVL 树在删除节点之后可能需要多达 O ( log n ) O(\log n) O(logn) 次的旋转才能够使整棵树恢复平衡,但也因此导致了全树拓扑结构频繁地发生大幅度的变化。
红黑树主要是针对上述不足所做的改进,它也是一棵平衡二叉搜索树,且可以保证每次插入、删除操作之后的重平衡过程中,全树拓扑结构的更新仅涉及常数个节点。
红黑树的搜索、插入和删除操作的时间复杂度也为 O ( log n ) O(\log n) O(logn)。
2. 约束
红黑树具有如下约束:
(1)每个节点要么为红色,要么为黑色;
(2)树根始终为黑色;
(3)若一个节点为红色,则其左右孩子必为黑色;
(4)从任一节点通往其任一后代叶节点的路径中,黑色节点的总数(称为黑高度)必定相等。
设节点总数为 n n n,则红黑树的高度为 O ( log n ) O(\log n) O(logn)。但相比于 AVL 树而言,红黑树无法做到 AVL 树那样严格的适度平衡。
3. 插入
(1)首先和普通的二叉搜索树一样插入新节点
x
x
x,并将其染为红色;
(2)如果
x
x
x 为树根,则将其染为黑色,然后成功返回;否则,
(3)如果
x
x
x 的父节点为黑色,则成功返回;否则即出现“双红”现象(节点
x
x
x 及其父节点均为红色),
(4)设
x
x
x 的父节点为
p
p
p(红色),
p
p
p 的父节点为
g
g
g(黑色),
p
p
p 的兄弟节点为
u
u
u;
根据 u u u 的颜色的不同(定义空节点的颜色为黑色)可分为两种情况进行处理。
RR-1:节点 u u u 为黑色的情况
根据 g , p , x g,p,x g,p,x 的方向又可以分为四种情况,下图中的(a)和(b)即为对应的两种情况,另外两种与(a)、(b)对称。
情况(a):以 g g g 为轴进行一次 zig 旋转,然后将 p p p 染为黑色,将 g g g 染为红色(因为 u u u 为黑色,所以没事)。(此时, a = x , b = p , c = g a=x,b=p,c=g a=x,b=p,c=g)
情况(b):先以 p p p 为轴进行一次 zag 旋转,然后以 g g g 为轴进行一次 zig 旋转,然后将 x x x 染为黑色,将 g g g 染为红色(因为 u u u 为黑色,所以没事)。(此时, a = p , b = x , c = g a=p,b=x,c=g a=p,b=x,c=g)
RR-2:节点 u u u 为红色的情况
根据
g
,
p
,
x
g,p,x
g,p,x 的方向又可以分为四种情况,下图中的(a)和(b)即为对应的两种情况,另外两种与(a)、(b)对称。
此时只需将
p
,
u
p,u
p,u 染为黑色,将
g
g
g 染为红色即可。但此时又可能会导致
g
g
g 及其父节点发生“双红”现象,所以此时需要递归向上判断、处理双红现象。
由上可见,只有在 RR-1 情况中才需要进行旋转操作(改变树的拓扑结构),而且旋转过后,重平衡过程即宣告完毕。所以,红黑树的插入操作仅涉及到常数次的拓扑调整。
4. 删除
设 x x x 的接替者为 r r r, x x x 的父节点为 p p p。
(1)首先根据普通的二叉搜索树的删除过程删除节点
x
x
x,并使用
r
r
r 替换
x
x
x;
(2)若
x
x
x 为红色,则成功返回;否则,
(3)若
x
x
x 为黑色,且
r
r
r 为红色,则只需将
r
r
r 染为黑色即可成功返回;否则,
(4)若
x
,
r
x,r
x,r 均为黑色,则出现“双黑”现象;此时,将
x
x
x 的兄弟节点记为
s
s
s(非空,否则违背约束(4));
根据 s , p s,p s,p 颜色的不同,具体可分为四种情况进行处理。
BB-1: s s s 为黑色,且至少有一个红色子节点, p p p 的颜色不定
将 s s s 的红色子节点记为 t t t,则一种可能情况如下图中的(a)所示:
其他情况类似或与此对称。
此时,对 t , s , p t,s,p t,s,p 进行单旋或双旋(也可以进行“3+4”重构),然后将 t , p t,p t,p 染为黑色,令 s s s 继承 p p p 原来的颜色即可。
BB-2: s s s 为黑色,且无红色子节点, p p p 为红色
一种可能情况如下图中的(a)所示,另一种情况与此对称:
此时只需将 s s s 染为红色,将 p p p 染为黑色即可。
BB-3: s s s 为黑色,且无红色子节点, p p p 为黑色
一种可能情况如下图中的(a)所示,另一种情况与此对称:
此时可将
s
s
s 染为红色,保证局部子树满足约束,但就全局来看,约束(4)不一定成立,因为子树
p
p
p 的黑高度减少了一。
为此,可以等效地看做又发生了一次删除操作:节点 p p p (等价于原来的 r r r)的一个黑色父节点(等价于原来的 x x x)刚被删除,因此可以递归地解决“双黑”现象。
BB-4: s s s 为红色
此时 p p p 必为黑色, s s s 的子节点必为黑色。
一种可能情况如下图中的(a)所示,另一种情况与此对称:
此时可以 p p p 为轴进行一次 zig 旋转,然后将 p p p 染为红色,将 s s s 染为黑色。
上述操作并没有直接解决“双黑”现象,相反,它只是将其转换为 BB-1 或 BB-2 情况(此处的 s ′ s' s′ 对应原来的 s s s)。
综上所述,红黑树的删除操作最多也只需常数次的旋转(调整全树拓扑结构)。