首页 > 代码库 > 红黑树 节点的删除
红黑树 节点的删除
接上一篇。
红黑树的插入操作!
红黑树的删除继续分各种情况进行考虑。
首先考虑红黑树的单支情况,即只有父节点只有一个子节点,另外一个为NULL,这样的话,只有一种情况,即父节点为黑色,子节点为红色,因为其他情况都会是孩子为黑色,因为孩子为红色父为红色,则与红父黑子矛盾。而当孩子是黑色时,另一个孩子是黑色的NULL,则必定使左右路径上黑色节点数量不等。所以单支只能为黑父红子。
这里的单支情况,是对任意一点的,若其只有一个孩子,则其必为黑色,孩子必为红色,且孩子为叶子节点。孩子为红色,如果有孙子,其孙子必为黑色,则路径黑子数量不等,不平衡。
情况一:
单支,删除红色节点,则不会影响其他路径情况,不影响平衡,直接删除即可。
情况二:
单支,删除黑节点
若s节点为黑色,则用单支下的红色孩子替代自己,然后删除黑色节点,这样路径上少了一个黑色节点,影响平衡,需要进行调整。
情况三:
删除节点有两个非空孩子,这时候又用到向下旋转的思路,寻找删除节点p的中序遍历的后继节点s,即正常排序后位于p之后的数字,而且s节点必定最多有一颗子树,即s最多有一颗右子树,或者没有。若s节点有一颗右子树,则必为单支情况,其孩子为红色,且无孙子,则这就是情况二,转到情况二。若s节点为叶子节点,则其可为红色或黑色,红色为情况一。
这种情况将p与s的数据交换,但颜色不换,则情况转换为删除s点,而删除之前树还是平衡的。
或者这样分析:
若s节点为红色,则其必定不是单支,则其为叶子节点,则是情况一,直接删除即可。
若s节点为黑色,则用s的孩子null或者单支下的红色孩子替代自己,然后删除黑色节点,这样路径上少了一个黑色节点,影响平衡,需要进行调整。(这里又要注意,如果是孩子为NULL,替代后,如何找到s节点的父节点。没有哨兵节点,这个地方麻烦了。。。。好吧,调用的递归调整函数的参数加一个父节点指针)
然后如同插入一样设置一个递归的调整函数,调整有4种情况:
首先以删除判断节点为x,为黑色,父节点为p,兄弟节点为w。以x为根的子树的黑色节点树减一,则需要进行平衡操作。
一般是有一下4种情况,但,还有一个特殊情况,即x为根节点时,跟插入时判断相同,如果x为根节点,且现在为红色, 则将其改为黑色。对于以下情况2,可能转换到这种情况。第二次被别人的博客坑,等会写完了再测试有没有其他错误。
情况1:w为红色。
则w的孩子都为黑色,p为黑色。改变w和p的颜色,即w改为黑色,p改为红色,然后以p为支点进行左旋,或右旋,根据x位于p的位置决定,若x为左孩子,左旋,右孩子右旋。更新后x获得了新的兄弟节点,然后继续对x进行判断调节。
情况2:w为黑色,且w的孩子都为黑色。这里由于之前是在x所在子树上删除了一个黑色的节点,则w所在子树上必定有一个黑色节点,即w必定不为NULL。
将w置为红色,使w所在子树上黑色数量减一,则p所在子树上黑色节点数量也减一,则需要以p节点作为当前节点,即新的x节点。如果新的x为红,则将其置为黑色,则整个树平衡,结束,如果为黑,则继续判断新的x节点的情况。
情况3:w为黑色。
如果x为p的左孩子, w的左孩子为红色,右孩子为黑色。
则将w置为红色,左孩子为黑色,然后以w节点为支点右旋。
如果x为p的右孩子, w的右孩子为红色,左孩子为黑色、
则将w为红,右孩子为黑,然后以w节点左旋。
获得新的兄弟节点,进入情况4. 这里进行情况3的旋转不会对改变任何子树的平衡性。
情况4:w为黑色。
如果x为p的左孩子,w的右孩子为红色,左孩子可以为红色或黑色或NULL。
则交换w和p的颜色,因为之后w要成为新的父节点,所以要获得原来p的颜色,防止与p的父节点冲突。
将w的右孩子设置为黑色,这样w的右子树黑色节点树+1,
再以p节点为支点左旋,这样w的颜色黑色会移动到左子树,使其节点树 -1 + 1 =0,而右子树减少了一个黑节点 +1 -1 = 0;且新的p节点为原来的颜色,整个树是平衡的。结束、
如果x为p的右孩子,w的左孩子是红色。同理、
交换w和p的颜色,将w的做孩子改为黑色,以p为节点右旋。结束判断。
最终调整完成。这里也有一个很重要的地方,在左旋和右旋时交换父节点p与其对应左右孩子c的颜色,导致旋转后得到的新父节点p颜色未变,则不用再向上检测。
中间测试的时候有出错了,尝试画了一些图并找出了错误,只画了一张图,其他都是看别人的博客思考的。
删除其实也不是特别复杂,尝试写出代码:
template <typename T> void RBTree<T>::GetParentLinked(RBNode<T> *a,RBNode<T> *b){ if(a == root){ root = b; if(b) b->parent = 0; return; } if(a->parent->left == a){ a->parent->left = b; if(b) b->parent = a->parent; }else{ a->parent->right = b; if(b) b->parent = a->parent; } } template <typename T> bool RBTree<T>::Delete(const T &x){ RBNode<T> *p = root ,*s,*fa; if(!root)return false; while(p){ if(p->value =http://www.mamicode.com/= x)break;>
我的红黑树代码!
红黑树 节点的删除