完整简单的红黑树算法

Posted 蓝桥云课精选

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了完整简单的红黑树算法相关的知识,希望对你有一定的参考价值。


最近组内定个规矩,每周分享一个算法,上周是第一周,分享的是红黑树,下面是自己学习总结的,感觉网上的都不是特别清楚,要么是写的特别复杂,没有一点条理。


一、红黑树性质



  • 1.每个结点要么是红的要么是黑的

  • 2.根结点是黑的

  • 3.每个叶结点(叶结点即指树尾端NIL指针或NULL结点)都是黑的

  • 4.如果一个结点是红的,那么它的两个儿子都是黑的

  • 5.对于任意结点而言,其到叶结点树尾端NIL指针的每条路径都包含相同数目的黑结点


总结:平衡状态下红黑树要么单支黑-红,要么有两个子节点


二、复杂度



O(lgn)


三、结点插入



将一个节点插入到红黑树中,需要执行哪些步骤呢?

  • 首先,将红黑树当作一颗二叉查找树,将节点插入;

  • 然后,将节点着色为红色;

  • 最后,通过旋转和重新着色等方法来修正该树,使之重新成为一颗红黑树。


1.将插入的节点着色为红色,不会违背"特性(5)"!少违背一条特性,就意味着我们需要处理的情况越少。接下来,就要努力的让这棵树满足其它性质即可;满足了的话,它就又是一颗红黑树了

 

2.对于"特性4",是有可能违背的!


总之:新插入的结点是红色!


3.插入的5种情况:


 (1)如果插入的是根结点,由于原树是空树,此情况只会违反性质2,因此直接把此结点涂为黑色;


 (2) 如果插入的结点的父结点是黑色,由于此不会违反性质2和性质4,红黑树没有被破坏,所以此时什么也不做。


 (3) 如果当前结点的父结点是红色且祖父结点的另一个子结点(叔叔结点)是红色;

       

解决: 将当前节点的父节点和叔叔节点涂黑,祖父结点涂红,把当前结点指向祖父节点,从新的当前节点重新开始算法。


完整简单的红黑树算法


以下(4)(5)都以左孩子为例,右孩子进行对称操作即可

  

(4)当前节点的父节点是红色,叔叔节点是黑色,当前节点是其父节点的左孩子;

      

解决: 父节点变为黑色,祖父节点变为红色,在祖父节点为支点右旋。

 

完整简单的红黑树算法

 

(5)当前节点的父节点是红色,叔叔节点是黑色,当前节点是其父节点的右子;


解决:当前节点的父节点做为新的当前节点,以新当前节点为支点左旋。问题转为(4)


完整简单的红黑树算法


总结:整个过程就是解决以上几个问题,关键是整个过程要更新当前节点是哪个结点

 

四、结点删除



需要执行的操作依次是:首先,将红黑树当作一颗二叉查找树,将该节点从二叉查找树中删除;然后,通过"旋转和重新着色"等一系列来修正该树,使之重新成为一棵红黑树。


待删除的节点按照儿子的个数可以分为三种:


1.删除叶结点(没有子结点) 

 

(1)如果叶结点为红色,直接删除


完整简单的红黑树算法


(2)如果叶结点为黑色,兄弟结点没有子结点


 解决: 兄弟节点B绘为红色,父节点P绘为黑色。


 完整简单的红黑树算法

 

注意:之后操作的结点全为左孩子,右孩子进行对称操作即可

   

(3)叶结点为黑色,兄弟结点有一个孩子不为NIL。若这个孩子为右孩子。

解决:将B的这个右孩子绘为黑色,B绘为其父节点P原来的颜色,P绘为黑色,然后对P进行一次左旋转。

 

完整简单的红黑树算法


(4)叶结点为黑色,兄弟结点有一个孩子不为NIL,若这个孩子为左孩子。

    

解决:将B的这个左孩子绘为黑色,B绘为红色,然后对B进行一次右旋转,问题转化为右孩子的情况。

 

完整简单的红黑树算法


(5)叶结点为黑色,兄弟结点有两个孩子。 若兄弟结点(B)为红色,则B的两个孩子一定为黑色。


解决:将B绘为黑色,B的左孩子绘为红色,然后对P(父结点)进行一次左旋转。

 完整简单的红黑树算法

  

(6)叶结点为黑色,兄弟结点(B)有两个孩子。 若B为黑色,则B的两个孩子一定为红色。


解决:将B的父节点P绘为黑色,B的右孩子绘为黑色,B绘为其父节点P原来的颜色,然后对P进行一次左旋转。


完整简单的红黑树算法


2.删除结点有一个外部结点(有一个子结点, 这个结点C一定是红色节点,否则从D到各个NIL节点的路径上的黑色节点数目就会不同)


解决:交换D(删除结点)和C(子结点)的内容(颜色保持不变),被删除节点变为C,问题转化为被删除节点的两个孩子都为NIL的情况。重新查看树是否满足红黑树。


3.删除结点有两个外部结点(有两个子结点)


解决:按照二叉查找树删除节点的方法找到D的后继节点S,交换D和S的内容(颜色保持不变),被删除节点变为S,如果S有不为NIL的节点,那么继续用S的后继节点替换S(此过程可能是一级一级找,也可能是直接找左子树的最大值,取决于本来要删除的结点和实际删除结点的值的大小,要删除的结点比实际删除的结点小,一级一级找,否则相反),直到被删除节点的两个孩子都为NIL,问题转化为被删除节点D的两个孩子都为NIL的情况。

 

 

其中的左旋右旋其实也很简单,有不清楚的大家上网查查,此处不再详细叙述了。

 

五、应用场景



  • 1.著名的linux进程调度Completely Fair Scheduler,用红黑树管理进程控制块;

  • 2.epoll在内核中的实现,用红黑树管理事件块;

  • 3.nginx中,用红黑树管理timer等;

  • 4.Java的TreeMap实现;

  • 5.广泛用在C++的STL中。map和set都是用红黑树实现的;

 

六、其他



  • 从头到尾的插入和删除操作案例插图:http://blog.csdn.net/v_july_v/article/details/6284050

  • nginx 红黑树的实现(c实现):http://blog.csdn.net/liuxuejiang158blog/article/details/21417145 

  • c的红黑树实现:http://www.cnblogs.com/skywang12345/p/3624177.html#a3

  • php的红黑树实现:http://www.zhangley.com/article/php_rbtree/


文章转载自:博客园

推荐阅读:



以上是关于完整简单的红黑树算法的主要内容,如果未能解决你的问题,请参考以下文章

完整简单的红黑树算法

数据结构和算法(Golang实现)(29)查找算法-2-3树和左倾红黑树

算法红黑树-二叉树-算法

Sedgewick的红黑树

简单聊聊红黑树(Red Black Tree)

手撕hashmap的红黑树