红黑树是一种特殊的排序二叉树,在知足排序二叉树的条件以后,还要知足如下几个特色:spa
红黑树: 1 根结点是黑色.
2 叶节点都是Nil结点,且为黑色
3 父子节点不能同时为红色
4 从任意结点出发,到其每一个叶结点的路径上都包含相同的黑结点数目.
其中, 3,4 两个特色是关键.3d
红黑树的删除操做blog
1:节点命名约定排序
D表示要被删除的节点。即:取 Delete 的首字母;class
P 表示父节点。即:取 Parent 的首字母;效率
S表示兄弟姐妹节点。即:取 Sibling的首字母; SL表示兄弟节点的左子树,即:左子节点;二叉树
G表示祖父节点。即:取 Grandfather的首字母;搜索
L表示左树。即:取Left的首字母;
R表示右树。即:取Right的首字母;
DR表示要被删除的节点的右子树,即:右子节点; 以此类推.方法
Nil表示叶子节点。即所谓的空节点;注意:红黑树中的叶子节点与其余树中所述说的叶子节点不是同一律念。并且红黑树中的叶子节点(即:Nil节点)永远是被定义为黑色的。im
2:删除操做宏观分析
在红黑树中,被删除的结点, 只有如下四种状况。
状况一:删除的节点的左、右子树都非空;
状况二:删除的节点的左子树为空树,右子树非空;
状况三:删除的节点的右子树为空树,左子树非空;
状况四:删除的节点的左、右子树都为空树;
其中状况一,能够按与普通二叉搜索树的删除方式同样处理。具体方法为:找到D节点的直接后继节点(暂且称为X节点),而后将X的值转移到D节点,最后将X节点做为真正要被删除掉的节点。
查找直接后继点X的方法是: 从D结点转向右,再左转,一直向左前进, 直到左分支的尽头便是X点, 所以 X点是没有左子树的, 与状况二或状况四形同
咱们获得一条很是重要的结论: 红黑树中真正要删除的结点,要么只有单子树,要么是个无子树的单结点.
3:红黑树删除后平衡处理
下面是几个图示说明:
根据红黑树的定义,被删除的节点D(即:上文所述的(Real)D节点)不论如何都必定有一个“右子树”,只是该右子树要不为非空树(即:真正存在的节点,不为Nil节点),要不就必为空树(即:D的两个子节点都为Nil)。下面称D的该右子节点(或称为右子树)为DR。
a) 被删除的D节点为红色。这种状况,则与D相关的颜色以及结构关系必然只有以下一种状况(为何只有这种状况,不明白的请看红黑树的性质):
分析:由于D为红色,因此P必为黑色,同时DR不可能为红色(不然违反性质4)。同时因为性质5,则DR必为Nil,不然就D树来讲,通过DR与不通过DR的路径的黑节点数必不相同。如今要删除D节点,只须要直接将D节点删除,并将DR做为P的左子节点便可。所以删除后,变成上图右侧所示。
b) 被删除的D节点为黑色。此时状况会稍复杂些,具体又分析为:DR为Nil与DR不为Nil。根据性质5,若是DR不为Nil,则DR必为红色,且DR的两个子节点必为Nil。所以,此处先来分析DR不为Nil的状况(由于该状况比较简单)。而DR为Nil的状况,由后面的C)及其后内容再进行具体分析 。
如前所述,若是DR不为Nil,则D、DR必为以下状况:
分析:因为删除的D为黑色,删除后P的左子树的黑节点数必少1,此时恰好DR为黑色,而且删除后DR能够占据D的位置(这样还是一棵二叉搜索树,只是暂时还不是合格的红黑树罢了),而后再将DR的颜色改成黑色,恰好能够填补P左子树所减小的黑节点数。从而P树又平衡了。所以,平衡处理后,最终变成上图右侧的图示。
c) 被删除的D为黑色,且DR为Nil。
若是DR为Nil,则删除D后,P的左子树黑节点数一定少1,纯粹想在P的左子树作文章来平衡P树是绝无可能的了。所以,一定须要其余分支的辅助来最终完成平衡调整。根据红黑树的定义,P会有一个右子节点,称为S子节点。此处又可细节分两种状况:黑S与红S。此处先讨论红S的状况。
说明:若是S为黑,则它必不会为Nil。(不明白的人,再好好想一想为何)。同时根据红黑树的性质,D、S、P、SL、SL的颜色关系必只有以下一种状况(由于此处探讨的是S为红的状况)。
分析:删除前P树的左、右子树的黑节点数平衡,删除后(即:上图右侧所示),通过DR分支的黑节点数将比经过S分支的黑节点数少1。此时,作以下操做:
将P左旋转,再将P由黑色改成红色,将S由红色改成黑色,演变过程以下图示:
通过以上演变后,通过P的路径,左分支黑节点数还是少1,其余分支的黑节点数作仍然保持不变。此时的状况却变成DR的兄弟节点为黑色(再也不是红色的状况了),所以转入此处c)点一开始所说的另外一种状况(S为黑色的状况)的处理。
注意:可能有人会一时想不明白什么要这样转换。由于这样转换后,虽然对于P树的左子树的黑节点数仍然会比右子树的黑节点数少1,但此时DR的兄弟(之前的S节点)如今已经变为SL,即已经由红色变为黑色,而且很是重要的此时的DR的兄弟节点SL的子结点(即:DR的两个侄子节点),要不就是红色节点要不就必为Nil节点,而这种状况正是D为黑色、S也黑色的状况。(注意看注意看注意看必定注意看这点:对于被删除节点D的父节点来讲,D黑S黑的状况下,不管如何D的兄弟节点S的两个儿子节点SL与SR都不多是非Nil的黑节点。不明白的好好想一想为何)。所以咱们有了进一步分析的余地。
d) 被删除的D为黑色,S也为黑色的状况。根据D、P、S、SL、SR的颜色组合状况,原本是有很是多种变换的。但事实上,咱们只须要按以下4种状况作进一步的处理,便可所有涵盖全部的颜色组合状况。
d.1> SL为红,SR颜色任意;(对于该状况的处理,其实咱们不关心P的颜色)
d.2> SR为红,SL颜色任意;(对于该状况的处理,其实咱们不关心P的颜色)
d.3> SL、SR都为黑;P为红。(注意:根据前面c)点的红色文字部分的分析,此时SL与SR一定一定都为Nil节点);
d.4> SL、SR都为黑;P为黑。(注意:根据前面c)点的红色文字部分的分析,此时SL与SR一定一定都为Nil节点);
d.1> SL为红,SR颜色任意状况
分析:P树的左子树黑节点数减小1,所以,要想平衡,必需想办法让左子树的黑结节数增长1,并且同时P的右子树的黑节点数要保持不变。所以,想办法将SL这个红色节点利用起来,让它来填补P的左子树所缺乏的黑节点个数。所以,立马想到旋转,只要有办法转到P的左子树或P位置上,则就有可能填平P左子树的高度。因此具体操做步骤为:
将S右旋转;接着将SL改成P的颜色,P的颜色改成黑色(用这个黑色来填补DR分支的黑节点数);将P左旋转。
d.2> SR为红色,SL颜色任意的状况
分析:思路同d.1>状况相似,都是想办法用红色的SR节点来填补P的左子树的减小的黑节点数。具体步骤为:
将S由黑色改成P的颜色;
将SR由红色改成黑色;
将P的颜色改成黑色(用该黑色来填补DR分支缺失的黑节点数);
将P节点左旋转;
d.3> SL、SR都为黑色(其实都为Nil节点),P为红色的状况
分析:此状况较为简单,直接将红色的P改成黑色,以此为填补DR缺乏的黑节点个数。此时P右子树黑节点数却增多,所以,再将S改成红色便可平衡。
d.4> SL、SR都为黑色(其实都为Nil节点),P为黑色的状况
分析:由于DR、P、S、SL、SR全都为黑色,则不论如何变换,都永远不可能使用P的左右子树的黑节点数达到平衡。而P不平衡的缘由是由于P的右子树黑节点数会比左子树多1个。所以,干脆将S由黑色改成红色,如此一来,P的左、右子树的黑节点个数是平衡的。可是,此时通过P的路径的黑节点个数将会比不通过它的路径少一个。所以,咱们将P做为待平衡的节点(即:此时的P至关于DR的角色)往上继续上溯,直到P为根节点为止。
到此,红黑树的删除操做已所有说明完。从以上的分析来看,红黑树的删除操做将是最为费时的,至少会比插入操做复杂,更耗时的可能性确定会更大。但事实上,红黑树的插入、删除、效率都是很是高的。插入比较简单就不说了。删除操做事实上,就算遇到最坏状况:DR、P、S、SL、SR全为黑的状况下,在上溯过程当中,通常状况下也是会很快就遇到红色的P节点的。除非整棵红黑树的右子树基本上都是黑节点(试想下,这可能性几乎不可能,由于咱们插入时,老是以红色插入的,再加上红黑树的几条性质约束一下),或者原本身红黑树的总体高度就很是浅。