红黑树删除的详细介绍

要搞清楚红黑树的删除,一定要结合红黑树的5个性质:

     1.  每个节点或是红的或是黑的

     2.  根节点为黑色

     3.  外部节点是黑色的

     4.  如果一个结点是红色的,那么它的两个儿子都是黑色的  (红红不能相连)

     5.  对每个结点的,从该节点出发到外部结点的所有路径上包含相同个数的黑色结点(黑高相同)

红黑树的删除策略:

       如果待删除的结点y 有两个孩子节点,那么找该树中序遍历中结点y 的直接前驱或者后继,用前驱或者后继的值替换y的值,然后我们要删除的结点就变成了y 的前驱或者后继。而前驱或者后继要么是叶子结点,要么是单分支结点,无非这两种情况!

       也就是说,我们将任意结点的删除都转化为叶子或者单分支结点的删除!

接下来说明具体的删除步骤:

     1.  删除的结点Y 是个红色的节点,那么我们的处理就是将Y 直接删除,理由如下:

               (1)树中各个节点的黑高没有变化

               (2)删除后满足性质4,因为不会出现 红红相连 的情况

               (3)删除的不可能是根节点,因为根节点是黑色的

     2.  删除的结点Y 是个黑色的结点,那么我们需要特殊处理:做法就是直接将Y 删除,然后我们将Y 的黑色作为额外属性给予Y 的孩子结点 X(这么做使得红黑树在逻辑上的"黑高"还是没有变化的);但是这个做法使得结点X 有了双重颜色,这不符合性质一,分为以下两类讨论加解决:

         2.1.  X原来的颜色为红色

                 做法:直接将X的颜色改为黑色;做完后就满足了性质一 和 性质五,同时也是绝对满足其他性质,此时调整结束!

         2.2.  X原来的颜色为黑色

                 结合上述,此时的 X 肯定是一个有双重黑色性质的结点!这个特点在接下来的调整中异常重要,而且我们在接下来的调整过程中一定要保证树的黑高不变

                 2.2.1  X的兄弟节点为红色(此模式也称  case1

                          此模式下,我们结合性质四(红红不能相连)可以得到该模式下的红黑树图示一定为:

                           该模式的变化法则如图所示:

                           该模式的变化有着两个特点: 1. X的兄弟结点变化后一定为黑色; 2. 该变化未解决X为双黑节点的问题

                 2.2.2. X的兄弟结点为黑色

                           case 2:  X的兄弟为黑色,X兄弟的两个孩子都是黑色的

                                         此模式下的红黑树图示如下:

                                        此模式下的变换规则是将X 及其兄弟结点的一个黑色性质上移,如图所示:

                                         此变换的特点:将黑色属性上移,不旋转,并将X上移至其父节点处;然后进行以新的X继续进行调整

                                         而此变换可能导致我们每次循环都是以case2的结束状态作为下一次循环的开始状态。即一直在做                                       case2或者case1+case2;直到X==RBTree.root就不必循环下去,调整结束!因为从跟到每个叶的黑高都相同

                                         但此模式未处理X 额外的黑色性质,却有可能退出调整的循环!!!!!

 

                             case3:  X的兄弟为黑色,X兄弟的内侧结点为红色,X兄弟的外侧孩子为黑色

                                      该模式的说明:当不满足case2,即X的兄弟为黑色,X兄弟的两个孩子不全都是黑色的时;X兄弟的两                                  个孩子可能为双红或者一红一黑:即“内红外黑”,“内黑外红”,“双红色”,如图所示:

                                      但是case3只关注“内红外黑”情况,处理方式如下:

                                     该模式的特点:未处理X的双黑性质,但是将X兄弟节点的外孩子变成了红色

 

                          case 4:   X的兄弟为黑色,X兄弟的外侧孩子为红色

                                 该模式的特点:如果没有命中case2,则有以下几种可能:

                                 图中的情况三一定会被case3处理,而case3的结果就使得 X兄弟的外侧孩子为红色,所以上述的全部情况                              最终都会变成 X兄弟的外侧孩子为红色,即case4;所以说case4的模式图示为:

                          而该模式的变化规则是:X的兄弟节点继承 X父节点的颜色,而X父节点的颜色变为黑色,X兄弟的外孩子变成黑                     色,然后以X的父节点进行左旋(X在父节点哪边就往哪边旋),结果如下:

                         模式特点:未变化之前X兄弟节点的外侧孩子为红色,我们将其改为黑色,这个时候树中多出了一个黑色节点,                       X正好缺一个黑色,只要我们将多出来的这个黑色用来弥补X缺少的,这个  额外黑色  就被消除了,即此时就可以结                     束调整,所有的问题都得到解决!!

 

总结:

        case1是case2,3,4的辅助步骤

        case2具备退出调整循环的能力

        case3的执行结果必定满足case4需要的模式

        case4的执行就可以立马结束整个调整的过程

        整个调整过程最多只需要3次旋转,3次旋转分别出现在:case1,case3,case4

 

调整函数的伪代码:

调整函数的代码:

void RB_DELETE_FIXUP(RBTree &myt, rb_node *_X)
{
	while (_X != myt.head->parent && _X->color == BLACK) //_X非跟结点 且 _X颜色为黑时才会执行循环体
	{
		if (_X == _X->parent->leftchild)
		{
			rb_node *_Y = _X->parent->rightchild;
			if (_Y->color == RED) //case 1
			{
				_Y->color = BLACK;
				_X->parent->color = RED;
				RotateLeft(myt.head, _X->parent);
				_Y = _X->parent->rightchild;
			}

			if (_Y->leftchild->color == BLACK  &&  _Y->rightchild->color == BLACK) //case 2
			{
				_Y->color = RED;
				_X = _X->parent;
			}
			else if (_Y->rightchild->color == BLACK)
			{
				_Y->leftchild->color = BLACK;  //case 3
				_Y->color = RED;
				RotateRight(myt.head, _Y);
				//_Y = _X->parent->rightchild;
			}
			else
			{
				_Y->rightchild->color = BLACK;  //case 4
				_Y->color = _X->parent->color;
				_X->parent->color = BLACK;
				RotateLeft(myt.head, _X->parent);
				_X = myt.head->parent; //_X为根节点,意味着不必再循环了
			}
		}
		else //_X现在在其父节点的右边
		{
			 rb_node *_Y = _X->parent->leftchild;
			 if (_Y->color == RED)
			 {
				 _Y->color = BLACK;
				 _X->parent->color = RED;
				 RotateRight(myt.head, _X->parent);
				 _Y = _X->parent->leftchild;
			 }

			 if (_Y->leftchild->color == BLACK  &&  _Y->rightchild->color == BLACK)
			 {
				 _Y->color = RED;
				 _X = _X->parent;
			 }
			 else if (_Y->leftchild->color == BLACK)
			 {
				 _Y->color = RED;
				 _Y->rightchild->color = BLACK;
				 RotateLeft(myt.head, _Y);
				 //_Y = _X->parent->leftchild;
			 }
			 else //_Y->leftchild->color == RED
			 {
				 _Y->leftchild->color = BLACK;
				 _Y->color = _X->parent->color;
				 _X->parent->color = BLACK;
				 RotateRight(myt.head, _X->parent);
				 _X = myt.head->parent;
			 }
		}
	}

	_X->color = BLACK;
}

上述代码是对伪代码的翻译,具体请自行实现符合自己结构的代码,但逻辑框架可用

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值