红黑树:节点插入与删除

红黑树定义

 红黑树是一种二叉查找树,具有如下性质:

  • 1.节点是红色或黑色
  • 2. 根是黑色
  • 3. 所有叶子都是黑色(叶子是NIL节点)
  • 4. 如果一个节点是红的,则它的两个儿子都是黑的
  • 5. 从任一节点到其叶子的所有简单路径都包含相同数目的黑色节点(黑色节点平衡)
  • 6. 新插入节点为红色

红黑树应用 

  • C++的STL,map和set都是用红黑树实现的。
  • 著名的linux进程调度Completely Fair Scheduler,用红黑树管理进程控制块。
  • epoll在内核中的实现,用红黑树管理事件块。
  • nginx用红黑树管理timer等。
  • Java的TreeMap实现。

红黑树操作 

 插入节点

步骤一:插入 

红黑树首先是一棵二叉排序树,根据二叉排序树的插入原则插入到相关位置,并设置成红色。

步骤二:调整

若插入节点的父节点为黑色,满足红黑树的性质,不用调整。

若父节点为红色,分为以下情况讨论:

1.父节点和叔叔节点均为红色

将父节点和叔叔节点均为红色设置为黑色,将爷爷节点从黑色变为红色(根据性质4,爷爷节点一开始肯定为黑色)。此时爷爷节点变成红色,可能其父节点为红色,违反性质4,需要递归调整(将爷爷节点的父节点和叔叔节点设置为黑色……,直到调整到根节点)。如插入和调整步骤图1和图2所示:

                                                                                                     图1 

                                                                                                     图2  

  2.叔叔节点为黑色

 需要分4种情况讨论:

(1)父节点为爷爷节点的右节点、插入节点为父节点的右节点(父右子右)

(2)父节点为爷爷节点的左节点、插入节点为父节点的左节点(父左子左)

(3)父节点为爷爷节点的右节点、插入节点为父节点的左节点(父右子左)

(4)父节点为爷爷节点的左节点、插入节点为父节点的右节点(父左子右)

父右子右:首先将父节点变成黑色子节点变成红色,然后以父节点为中心的左旋,如图3;

父左子左:首先将父节点变成黑色子节点变成红色,然后以父节点为中心的右旋;

父右子左可以通过以插入节点为中心的右旋变成父右子右,如图4;

父左子右可以通过以插入节点为中心的左旋变成父左子左。

                                                                                                     图3  

 

                                                                                                     图4  

  删除节点

对于一棵二叉搜索树来说,删除的节点情况可以分为3种:

1.叶子节点

2.只有左子树或只有右子树的节点

3.既有左子树又有右子树的节点。对于一棵普通二叉树的情况3来说,要删除既有左子树又有右子树的节点,我们首先要找到该节点的直接后继节点,然后用后继节点替换该节点,最后按1或2中的方法删除后继节点即可。

对于红黑树来说,针对待删节点的颜色,需要分两种情况讨论:

(1)待删节点为红色

1.删除红色叶子节点

红色节点的删除不会打破红黑树的平衡,所以可以直接删除。

2.删除红色节点只有左子树或右子树

红色节点的子节点只能为黑色节点,这种情况不存在,违反了性质5(左子节点和右子节点的黑高差1)。

3.删除红色节点既有左子树又有右子树

若后继节点为红色,用该节点替换待删节点,最后按情况1删除后继节点。

若后继节点为黑色,见后续。

(2)待删除节点为黑色

1.删除的黑色节点仅有左子树或者仅有右子树

这两种情况的处理方式是一样的,即用D的孩子(左或右)替换D,并将D孩子的颜色改成黑色即可(因为路径上少了一个黑节点,所已将红节点变成黑节点以保持红黑树的性质)。

             

                                                图5  

2. 删除黑色的叶子节点

2.1黑色叶子节点的兄弟节点为红色

将其转变为兄弟节点为黑色的情况:若待删除黑色节点为左节点则以父节点P为中心左旋;若待删除黑色节点为右节点则以父节点P为中心右旋。

                                                                                    图6  

                                                                                    图7  

2.2黑色叶子节点的兄弟节点为黑色 

 2.2.1兄弟节点为黑色,侄子节点为红色

需要分4种情况讨论:

(1)兄节点为右节点、侄子节点为兄节点的右节点(兄右侄右)

(2)兄节点为左节点、侄子节点为兄节点的左节点(兄左侄左)

(3)兄节点为右节点、侄子节点为兄节点的左节点(兄右侄左)

(4)兄节点为左节点、侄子节点为兄节点的右节点(兄左侄右)

 兄右侄右:以兄节点为中心左旋,兄节点变成父节点的颜色,父节点和侄子节点变黑,删除待删节点

                                                                                    图8  

 兄左侄左:以兄节点为中心右旋,兄节点变成父节点的颜色,父节点和侄子节点变黑,删除待删节点

                                                                                    图9  

兄右侄左:以侄子节点为中心右旋变成兄右侄右

                                                                                    图10  

兄左侄右:以侄子节点为中心左旋变成兄左侄左

                                                                                    图11  

 2.2.2兄弟节点为黑色,侄子节点为黑色

分两种情况:

(1)父节点为红色

(2)父节点为黑色

父节点为红色时,只需将父节点变黑、兄节点变红,然后删除待删节点

                                                                                    图12  

父节点为黑色

方法是将兄弟节点S的颜色改成红色,这样删除D后P的左右两支的黑节点数就相等了,但是经过P的路径上的黑色节点数会少1,这个时候,我们再以P为起始点,继续根据情况进行平衡操作(这句话的意思就是把P当成D(只是不要再删除P了),再看是那种情况,再进行对应的调整,这样一直向上,直到新的起始点为根节点)。结果如图13。

举例:如图14,删除节点5,按2.2.2步骤将15变红,此时节点10之后的分支黑高少了1,所以需要对节点10进行调整。节点10的兄弟节点50为黑色,侄子节点60为红色,可以按照2.2.1以50为中心左旋,同时将节点60涂黑,这样红黑树又平衡了。

                                                                                    图13  

                                                                                    图14 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值