算法基础(七)红黑树

亡梦爱人 提交于 2019-12-02 11:39:59

一、红黑树的特性

一个红黑树的节点node有如下5个属性:

node(parent, left, right, color, key)

红黑树的5条特性,使其接近于一颗近似的“平衡”搜索树:

1、节点的颜色是红色或者黑色

2、根节点是黑色的

3、所有叶子节点是黑色的

4、一个红节点的两个子节点均为黑色

5、从树中任何一个节点到其所有后代叶节点的简单路径上,包含相同数目的黑色节点

二、算法伪代码

1、旋转

以X为支点的左旋操作LEFT-ROTATE(T,x),改变了x的右孩子、父节点,y的左孩子、父节点,以及y的左孩子的父节点,有可能改变父节点的左or右孩以及T.root,参照图示,比较容易写出左旋的伪代码。

 

LEFT-ROTATE(T,x)
y = RIGHT(x)
p = PARENT(x)
RIGHT(x) = LEFT(y)
if(LEFT(y) != T.nil)
	PARENT(LEFT(y)) = x
PARENT(y) = p
if(p == T.nil)
	T.root = y
else
	if (x == LEFT(p))
		LEFT(p) = y
	else
		RIGHT(p) = y
LEFT(y) = x
PARENT(x) = y

2、插入

RB-INSERT(T,z)将节点z插入到红黑树中。首先按照普通的二叉搜索树将节点z插入,并涂成红色。然后再调用一个辅助过程RB-INSERT-FIXUP(T,z)使其恢复红黑树的性质。

RB-INSERT(T,z)
y = T.nil
x = T.root
while(x != T.nil)
    y = x
    if (z.key < x.key)
        x = x.left
    else
        x = x.right
z.parent = y
if (y == T.nil)
    T.root = z
else if (z.key < y.key)
    y.left = z
else
    y.right = z
z.left = T.nil
z.right = T.nil
z.color = red
RB-INSERT-FIXUP(T,z)

3. 辅助插入过程RB-INSERT-FIXUP(T,z)

充分考量RB-INSERT过程破坏红黑树的性质后,可能出现的各种情况,借助旋转操作与重新涂色,恢复红黑树的性质。

RB-INSERT-FIXUP(T,z)
while z.p.color == RED
    if p == z.p.p.left
        y = p.p.right
        //case 1
        if y.color == RED
            y.color = BLACK
            z.p.color = BLACK
            z.p.p.color = RED
            z = z.p.p
        //case 2
        else if z == z.p.right
            z = z.p
            LEFT-ROTATE(T,z)
        //case 3
        else
            z.p.color = BLACK
            z.p.p.color = RED
            RIGHT-ROTATE(T,z.p.p)
    else the same as clause with "right" and "left" swap
        //case 1
        //case 2
        //case 3
T.root.color = BLACK

4、辅助删除过程移植操作RB-TRANSPLANT(T,u,v), 使用v来顶替原来的u的位置。

RB-TRANSPLANT(T,u,v)
if u.p == T.nil
    T.root = v
else if u == u.p.left
    u.p.left = v
else u.p.right = v
v.p = u.p

5、删除操作RB-DELETE(T,z)删除节点z,如果z没有子节点或者只有一个子节点,则做一次简单的移植即可。两个子节点的情况较为复杂,关键点在于删除z后,用哪个节点来替代z的位置。考虑z的左子树都小于z,右子树都大于z,不难发现,应当用z的右子树的后继来替代z的位置。另外,将替代z的节点涂上与z相同的颜色,控制删除造成的影响,最后调用RB-DELETE-FIXUP完成修复。删除算法用y来跟踪替换z的节点,用x跟踪替换y的节点,因为y被重新着色,用y-orignal-color记录y的初始颜色。

RB-DELETE(T,z)
y = z
y-orignal-color = y.color
if z.left == T.nil
    x = z.right
    RB-TRANSPLANT(T, z, z.right)
else if z.right == T.nil
    x = z.left
    RB-TRANSPLANT(T, z, z.left)
else y = RB-MINIMUM(z.right)
    y-orignal-color = y.color
    x = y.right
    if y.p == z
        x.p = z
    else RB-TRANSPLANT(T, y, y.right)
        y.right = z.right
        y.right.p = y
    RB-TRANSPLANT(T, z, y)
    y.left = z.left
    y.left.p = y
    y.color = z.color
if y-orignal-color == BLACK
    RB-DELETE-FIXUP(T,x)    

6、辅助删除过程RB-DELETE-FIXUP(T,x)修复删除操作对红黑树的破坏。考虑如果y的颜色为红色,那么删除与移动不会导致红黑树性质的破坏。否则可能导致包含y的所有简单路径上的黑节点个数少了1。因为x替代了y的位置,可以将x看成双重黑色来弥补。我们所要做的就是跟踪x的轨迹,待其变为红黑色时将其涂成黑色。

RB-DELETE-FIXUP(T,x)
while x != T.root and x.color == BLACK
    if x = x.p.left
        w = x.p.right
        //case 1
        if w.color == RED
            w.color = BLACK
            x.p.color = RED
            LEFT-ROTATE(T, x.p)
            w = x.p.right
        //case 2
        if w.right.color == BLACK and w.left.color == BLCAK
            w.color = RED
            x = x.p
        //case 3
        else if w.right.color == BLACK
            w.left.color = BLACK
            w.color = RED
            RIGHT-ROTATE(T, w)
            w = x.p.right 
        //case 4
        else
            w.color = x.p.color
            x.p.color = BLACK
            w.right.color = BLACK
            LEFT-ROTATE(T, x.p)
            x = T.root
    else the same clause with right and left swap
    ...
x.color = BLACK

 

 

 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!