概述
RBT,RedBlackTree
应用场景
在JDK1.8的HashMap中,为了解决过度哈希冲突带来的长链表,会将链表转为红黑树;Linux底层的CFS进程调度算法中,vruntime利用红黑树来进行存储;多路复用技术的Epoll的核心结构也是红黑树+双向链表。
性质
- 每个节点或是红色的,或是黑色的。
- 根节点是黑色的。
- 每个叶子节点(NIL)是黑色的。
- 如果一个节点是红色的,则它的两个子节点都是黑色的。
- 对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。
引理
一棵有n个内部节点的红黑树的高度至多为
2
lg
?
(
n
+
1
)
2\lg(n+1)
2lg(n+1)
证明
当节点都为黑色时,该树的节点数最少。 若bh(black-height)为黑高,则用归纳法:
x
node
node
NIL
NIL
NIL
NIL
x
node
node
node
node
node
node
NIL
NIL
NIL
NIL
NIL
NIL
NIL
NIL
因此,以x为根的子树至少包含
2
b
h
(
x
)
?
1
2^{bh(x)}-1
2bh(x)?1个内部结点。 设h为树的高度,则根据性质4,从根到叶节点(不包括根节点)的任何一条简单路径上都至少有一半的节点为黑色,所以根的黑高至少为
h
2
\frac h2
2h?,于是有
n
≥
2
h
2
?
1
n\ge2^{\frac h2}-1
n≥22h??1,即
h
≤
2
log
?
2
(
n
+
1
)
h\le2\log_2(n+1)
h≤2log2?(n+1)。
旋转
RIGHT-ROTATE(X) -->
<-- LEFT-ROTATE(Y)
P
X
Y
a
b
c
P
Y
a
X
b
c
插入
设插入节点为C
- 根节点:C涂黑
- 父黑:无操作
- 父红
- 叔红:叔、父涂黑,祖涂红,以祖递归
- LAST
GP
P
C
NIL
U
NIL
NIL
NIL
NIL
- NOW
GP
P
C
NIL
U
NIL
NIL
NIL
NIL
- 叔黑
- 父、C同侧
- 同左:以祖右旋,祖涂红,父涂黑
- LAST
GP
P
C
B (NIL)
U (NIL)
NIL
NIL
- NOW
GP
P
C
B (NIL)
U (NIL)
NIL
NIL
- 同右:以祖左旋,祖涂红,父涂黑
- LAST
GP
U (NIL)
P
B (NIL)
C
NIL
NIL
- NOW
GP
P
C
B (NIL)
U (NIL)
NIL
NIL
- 父、C异侧
- 父左:以父左旋,转至同左侧
- LAST
GP
P
B (NIL)
C
U (NIL)
NIL
NIL
- NOW
GP
P
B (NIL)
C
U (NIL)
NIL
NIL
- 父右:以父右旋,转至同右侧
- LAST
GP
U (NIL)
P
C
B (NIL)
NIL
NIL
- NOW
GP
U (NIL)
NIL
P
C
B (NIL)
NIL
|