红黑树的插入删除
2018-10-14 本文已影响0人
杨小伟的世界
所有偷的懒总是要还的
红黑树作为一个平衡二叉树广泛应用在软件系统中,比如内核的vma结构。
之前偷懒没有彻底理解,这里做一下最近学习的笔记。
插入
按照正常的二叉树插入,并给节点上色为红色后。这么做将可能导致该节点和父节点同为红色,顾需要重新平衡。
如下的伪代码展示了高度抽象了当父节点为爷爷节点左孩子时的三种情况。
RB-INSERT-FIXUP(T, c)
1. while color[p[c]] = RED
2. if p[c] = left[p[p[c]]] // parent is left child of gp
3. then uncle = right[p[p[c]]]
4. if color[uncle] = RED // uncle is RED
5. then <Case 1>
6. else if c = right[p[c]] // child is left
7. then <Case 2>
8. <Case 3>
注释:
- 循环判断条件为父节点是红色
- Case 1表明 c, p, u同时为红色,且因为gp必须为黑色,处理方式是将红色节点上移
- Case 2是一个中间过程,目的是通过旋转变换成Case 3
- Case 3是c, p, gp在同一直线上,且c,p为红色,gp为黑色,通过旋转将这一分支上多余的红色转移到了gp的另一个分支上
- Case 1 是唯一不能确定是否终结的情况,Case 2,3是终结情况

尝试归纳一下插入过程中的平衡步骤:
在父节点是红色的前提下:如果叔叔节点是红色,则父亲和叔叔继承爷爷的黑色,将红色节点上移到爷爷节点;如果叔叔节点是黑色,则通过旋转将父亲上升为爷爷并交换父亲和爷爷的颜色,使红色转移到爷爷节点。
删除
按照正常二叉树删除,然后进行平衡。
RB-DELETE-FIXUP(T, c)
1. while c != root[T] and color[x] = BLACK
2. do if c = left[p[c]] // c is left child
3. then s = right[p[c]]
4. if color[s] = RED // sibling is red
5. then <Case 1>
6. if color[left[s]] = BLACK and color[left[s]] = BLACK
7. then <Case 2> // both nephews are black
8. else if color[right[s]] = BLACK
9. then <Case 3> // right nephew is black
10. <Case 4> // right nephew is red
注释:
- 循环判断条件为自己不是根且颜色是黑色
- Case 1,兄弟为红色,则通过旋转,让兄弟变成黑色
- Case 2,侄子都是黑色,只好上移黑色节点。如果原父节点是红色,则多余的黑色被吸收。否则父节点转化为新节点。
- Case 3,离自己近的侄子是红色,通过旋转将红色转到离自己远的侄子
- Case 4,离自己远的侄子是红色,通过旋转将多余的黑色吸收

尝试归纳一下删除过程的平衡步骤:
删除的平衡操作在自身和兄弟及侄子之间进行:如果兄弟不是黑色,则先把它变黑;如果兄弟是黑色且两个侄子也是黑色,则只能上移多余的黑色;如果兄弟是黑色且其中有一个侄子是红色,则能通过旋转将多余的黑色吸收。