数据结构与算法:红黑树(Red Black Tree)

版权声明:本文为博主原创文章,转载请注明出处,https://blog.csdn.net/u014165620/article/details/82628406

一、简介

红黑树(Red Black Tree)是一棵二叉查找树,在每个节点增加一个属性表示节点颜色,值为红色(Red)或者黑色(Black)。红黑树也是“平衡”树中的一种,通过对任何一条从根到叶子的路径上各个节点的颜色来进行约束,确保没有一条路径会比其他路径长出2倍,因而是“近似平衡”的。对平衡性的要求相较于AVL树更宽松。

二、红黑树性质

一棵红黑树是满足下面5条红黑性质的二叉查找树:

1. 每个节点要么是红色,要么是黑色;
2. 根节点是黑色;
3. 每个叶节点(NIL或者空节点)是黑色;
4. 如果一个节点是红色,则它的两个子节点都是黑色;
5. 对于每个节点,从该节点到其所有后代叶节点的路径上,均包含相同数目的黑色节点。
下图就是一棵红黑树:
这里写图片描述
插入一个新节点或者删除一个节点时,可能会导致违反上述红黑树性质,所以需要通过改变节点颜色旋转来维护这些性质。
旋转直观效果如下:
左旋:
这里写图片描述
右旋:
这里写图片描述
关于旋转的详细介绍,可以参考AVL树的旋转图解,红黑树的旋转与AVL树的旋转类似。

三、插入

因为红黑树也是一棵二叉查找树,所以定位新节点的插入位置与二叉查找树插入操作一样,这里主要介绍插入新节点后维护红黑树性质涉及的调整操作,即改变节点颜色和旋转。
插入新节点时,假设X为新插入节点,维护红黑树性质过程中涉及如下几个节:
这里写图片描述
为了不违反性质5(对于每个节点,从该节点到其所有后代叶节点的路径上,均包含相同数目的黑色节点),新插入的节点都为红色。

插入新节点X后包含以下几种情况:
情况1:原红黑树为空,插入后X为根节点,则根据性质2,直接将节点X涂黑即可;
情况2:X的父节点P为黑色,插入X不会违反红黑树性质,直接插入即可,不需调整;
情况3:X的父节点P为红色
此时违反性质4(如果一个节点是红色,则它的两个子节点都是黑色),需要调整。此时,包含6种情况,按父节点P是祖父节点G的左孩子left或者右孩子right划分,处理方式是对称的,这里以P是G的左孩子left为例进行介绍。其中,包含3种情况:
情况3-1:叔节点U为红色
将P涂为黑色以保持性质4,此时违反性质5,再将G涂为红色,同时U涂为黑色以保持性质5。然后X=G,G作为新节点X,继续维护。
这里写图片描述
情况3-2:叔节点U为黑色,新节点X为其父节点P的右节点right;
情况3-3:叔节点U为黑色,新节点X为其父节点P的右节点left。
这里写图片描述
情况3-2通过一个左旋,变成情况3-3。对于情况3-3,X、P都是红色,违反了性质4,所以将P涂为黑色,此时左边这条路径多了一个黑色节点,违反了性质5,所以将G涂为红色(因为P是红色,所以原来G一定是黑色),这样右边那条路径比以前少了一个黑色节点,同样违反性质5,所以通过右旋,将黑色P向上提。调整结束,无需继续上虑。
情况3对应调整伪代码如下:

while P.color == RED
    if P == G.left
        if U == RED                            //情况3-1
            P.color = BLACK
            U.color = BLACK
            G.color = RED
            X = G
        else if X == P.right                   //情况3-2
            X = X.p // X与P互换位置
            left_rotation()  //左旋
        P.color = BLACK                        //情况3-3
        G.color = Red
        right_rotation()   //右旋
    else
        //与上面3种情况对称
root.color = BLACK

四、删除

红黑树的删除操作,是在二叉查找树删除操作基础上增加部分内容,主要是增加维护红黑树性质的调整操作,与插入操作一样,调整方式包括:改变节点颜色旋转。下面主要对调整操作进行介绍。
假设删除节点为X,维护红黑树性质的调整过程涉及如下几个节点:
这里写图片描述
红黑树删除调整包含8种情况,按照删除节点为其父节点的左孩子left或者右孩子right划分,处理方式是对称的。这里以删除节点X为其父节点P的左孩子left为例进行介绍。其中。包含4种
红黑树删除操作包含以下几种情况:
情况1:删除节点X为红色,不会导致违反5条红黑树性质,无需调整;
情况2:当删除节点为根节点时,直接删除,无需调整;
当删除节点为黑色,且不为根节点时,删除调整包含8种情况,按照删除节点为其父节点的左孩子left或者右孩子right划分,处理方式是对称的。这里以删除节点X为其父节点P的左孩子left为例进行介绍。其中,包含4种情况(3~6),如下图所以,图中无色节点(如情况4中的节点2),既可以是红色节点,也可以是黑色节点:
这里写图片描述
情况3:兄弟节点B是红色;
情况4:兄弟节点B是黑色,且B的两个子节点都是黑色;
情况5:兄弟节点B是黑色,且B的左孩子是红色,右孩子是黑色;
情况6:兄弟节点B是黑色,且B的右孩子是红色。

伪代码如下:

while X != root and X.color == BlACK
    if X == X.p.left
        B = X.p.right
        if B.color == RED
            B.color = BLACK
            X.p.color = RED
            left_rotation(X.p)
            B = X.p.right
        if B.left.color == BLACK and B.right.color == BLACK
            B.color = RED
            x = X.p
        else if B.right.color == BLACK
            B.left.color = BLACK
            B.color = RED
            right_rotation(B)
            B = X.p.right
        B.color = X.p.color
        X.p.color = BLACK
        B.right.color = BLACK
        left_rotation(X.p)
        X = root
    else
        X 为其父节点右孩子,处理方式对称
X.color = BLACK

五、红黑树与AVL树比较

红黑树与AVL树都是“平衡”二叉查找树中的一种,AVL树对平衡性的要求更高,AVL树要求每个节点左右子树高度差不超过1,而红黑树节点的左右子树高度差可能会大于1,是一种“近似平衡”。红黑树通过节点颜色控制,用非严格的平衡来换取增删节点时旋转次数的降低,任何不平衡都会在三次旋转之内解决,而AVL是严格平衡树,因此在增加或者删除节点的时候,根据不同情况,旋转的次数比红黑树要多。因此,AVL树查询效率比红黑树高。但因为平衡性要求更高,每次插入删除会进行更多的平衡调整,所以AVL树插入删除效率相对较慢

个人总结,如有错误,感谢指正!

参考《算法导论》
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值