红黑树,作为一个为了二叉树平衡性而提出的一种二叉树结果,他是STL中的set和map的基础数据结构;
那么对于一个红黑树,规则如下:
- 性质1:每个节点要么是黑色,要么是红色。
- 性质2:根节点是黑色。
- 性质3:每个叶子节点(NIL)是黑色。
- 性质4:每个红色结点的两个子结点一定都是黑色。
- 性质5:任意一结点到每个叶子结点的路径都包含数量相同的黑结点。
那么依据这个规则,以及红黑树在插入叶节点后引起的红黑树失衡情况,进行不同的节点处理,调整节点颜色,就有了以下内容:
节点键值获取方法:
通过树节点头获取到树节点,然后根据键值提取函数对象将树节点中的键值提取出来;
树节点插入过程:
先是基于键值将树节点进行插入,最终插入位置一定位于叶节点位置,而后进行红黑平衡,根据性质5,新插入树节点先设置为红色;
基于键值的树节点插入:
红黑树是个二叉搜索树,即对于任何一个节点,他的左子树中的任意节点键值都小于该节点键值,右子树任意节点键值都大于该节点键值,因此,对于一个待插入节点,只需要从根节点开始,比当前节点大的就向右子节点移动,比当前节点小的就向左子节点移动直到最后到达叶节点位置,该叶节点就是待插入节点的父节点,根据大小关系判定该节点应该是左子节点还是右子节点;
红黑平衡:
首先,为了保证插入节点颜色影响尽可能小,插入节点颜色设置为红色,然后依据性质3不能有父子节点同时为红色节点,按照一定的规则可以进行节点颜色转换以及节点移动且维持二叉搜索树的结构,最终二叉树完成平衡;那么首先,对于一个已经达到红黑平衡的红黑树,要向红黑树中插入一个节点的时候,插入的位置一定是在叶节点位置;这样就有了以下情况:
一种情况是父节点是黑色的,那么不用进行红黑平衡;
另外一种情况是父节点是红色节点,此时由于红色节点不能相连的规则,需要进行红黑平衡:
对于插入节点的父节点P和P的父节点PP,此时P已知是红色,那么PP一定为黑色,特化情况到P为PP的左子节点情况(P为PP右子节点一样);此时P为PL,那么有以下情况:
1.PR存在,且为红色节点,那么将PP变红,PL和PR变黑,然后进行上溯,此时PP为红色,针对该节点进行处理;
2.PR不存在或者为黑色节点:此时则以PP为旋转节点进行右旋,然后PL变黑,PP变红即可完成红黑平衡;另外,如果新插入节点为右子节点,那么首先要以PL为旋转节点进行一次左旋,这样是由于在上面对PP进行右旋的时候,PL的右子节点会挂载到PP上,而PP染红,会造成父子节点都是红色的情况;
当要删除一个节点的时候:首先就是寻找一个替换节点,也就是真正会被删除的节点y,这个节点寻找的标准只有一个,就是他最多拥有一个子节点,这样在替换并且删除了该节点后,该节点的子节点A链接到该节点的父节点后,对于整棵树红黑平衡影响就是A节点的子树:如果y节点是个红色节点,那么替换后y被删除也无所谓,对红黑性质没有任何影响,但是当y是个黑色节点,此时由于y被删除,而A节点由于y节点的移动进行重新链接后,造成A子树相对整棵树而言缺少一个黑色节点,他需要经过一系列处理增加一个黑色节点,那么此时如果A节点是红色,那么直接染黑即可;但是当A节点原本就是黑色,此时就要依据以下图片(算法导论第三版截取过来的,如果要求删除请联系一下)进行一些循环操作:
此时,针对只有x为黑色节点的情况,根据其兄弟节点的不同情况进行节点操作,最终即可完成整棵树的重新平衡:
那么首先对于第一种情况:如果D节点为红色节点,那么B节点必定为黑色节点,此时对B节点左旋即可将其转换为下面的三种情况,这里具体操作可以看算法导论的解释,还是比较简单的,比网络上其他的一长串要好理解的多;其实对于一个NULL节点,在红黑树中认为他也是一个节点,且是一个黑色节点,因此这里需要提一下的就是对于x是NULL节点的时候,直接认为他是一个黑色节点套用在上面这个操作中也是成立的:
对于第二种情况,C、D、E都是黑色节点,这时直接将D节点染成红色,这样对于B点子树,这个子树内部就是满足红黑属性的,但是B子树整体对于整个红黑树是少了一个黑色节点,这时的B节点就是开始的x节点,进行循环操作;
对于第三种情况,C是红色节点,D、E是黑色节点,这种情况下对D进行右旋可转变为情况4;
对于第4种情况,对B进行左旋,然后设置E为黑色弥补对应树缺一个黑色节点的情况,这样x的子树整体多了一个黑色节点,整体就平衡了;