数据结构——红黑树

本文深入介绍了红黑树的概念、性质及其在数据结构中的重要性,特别是插入和删除操作的平衡调整策略。文章详细阐述了红黑树的旋转操作,包括左单旋和右单旋,以及如何在插入和删除后保持树的平衡。此外,还详细分析了删除节点时的六种情况和四种调整平衡的情形,帮助读者理解红黑树的内部工作原理。
摘要由CSDN通过智能技术生成

数据结构——红黑树

前言

红黑树是map,set,mutilmap,mutilset容器的底层数据结构,也是一种非常重要的数据结构,它在效率上对AVL又做了进一步的优化,因为AVL结构在插入,或删除时,无法避免大量的旋转操作,导致效率有所损耗,但是红黑树,就在这一点有了更好的优化,但是牺牲了平衡性,所以是不是一个完全平衡的二叉搜索树。

一、红黑树的概念和性质

概念:

红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。

性质:
1、根节点是黑色的

2、每个节点不是红色的就是黑色的

3、红色节点的子节点一定是黑色的

4、红色节点不能相连

5、从任意节点出发,它每一条路径上的黑色节点数目是相同的

这里有一条总结红黑树的顺口溜:

一头一脚黑,
黑连红不连。
插入看叔伯,
删除看兄弟。

这四句话就概括了红黑树的所有性质,以及插入和删除时应该怎样处理的情况。

二、红黑树节点的定义

#include<iostream>
#include<stack>
#include<vector>
using namespace std;
enum Color{BLACK = 0,RED = 1};  //设置颜色

template<typename Type>    //类的前向声明,不然因为编译器版本原因可能在声明友元类的时候出错
class RBTree;

template<typename Type>
class RBTreeNode
{
	friend class RBTree<Type>;   //成为友元类,可以访问节点私有成员
public:
	RBTreeNode(Type val = Type())
		:_rightChild(nullptr),_leftChild(nullptr),_parent(nullptr),_Val(val),_color(RED)
	{}
	~RBTreeNode()
	{}
private:
	Type _Val;
	RBTreeNode<Type>* _rightChild;
	RBTreeNode<Type>* _leftChild;
	RBTreeNode<Type>* _parent;
	Color _color;
};

template<typename Type>
class RBTree
{
public:
	RBTree():Nul(_BuyNode()),_root(Nul)
	{
		Nul->_leftChild = Nul->_rightChild = Nul->_parent = nullptr;
		Nul->_color = BLACK;
	}
protected:
	RBTreeNode<Type>* _BuyNode(const Type val = Type())  
	{
		RBTreeNode<Type>* s = new RBTreeNode<Type>(val);
		s->_leftChild = s->_rightChild = Nul;
		return s;
	}
private:
	RBTreeNode<Type>* Nul;
	RBTreeNode<Type>* _root;
};

我们有两个类,一个类是我们的红黑树类,另一个类是叶子节点类
红黑树类:
有两个成员,这里就有红黑树的另一个人为的看法,就是所有空节点,都为黑色节点,根一定是黑色节点,所以在初始化的时候我们不能没有根,初始化时一定要有一个黑色节点作为根节点,那么就有了为什么除了 _root以外还有一个节点作为空节点,所有空节点都指向这个节点。

在这里插入图片描述

然后呢,我们为了调整时方便,多使用了一个父指针,指向自己的父节点,因为不用这个的话,未来插入,删除都将变的超级麻烦!后面会有说到。

三、红黑树的旋转

这里我们就不需要再像AVL树一样写四个旋转方法了,因为初学,所以我们需要详细一点,现在我们直接选择同时调用左单旋和右单旋实现双旋转,这样就不需要重复实现了。提高了代码的复用性。

1.右单旋

在这里插入图片描述
因为我们在旋转之前就已经完成了颜色的修改,所以我们只需要进行单纯的旋转即可

template<typename Type>
void RBTree<Type>::RotateR(RBTreeNode<Type>*& t, RBTreeNode<Type>* p)
{
	RBTreeNode<Type>* s = p->_leftChild;
	/*判断即将要旋转的位置是否有左子树,有的话就将其挂在未来旋转过来的节点的右子树上
	  其次。如果没有,因为开头说过,所有节点的空节点,都指向了我们自己设置的空节点Nul,
	  所以只需要让p的右子树指向它就好了。*/
	if (s->_rightChild != Nul)
		s->_rightChild->_parent = p;
	p->_leftChild = s->_rightChild;
	s->_parent = p->_parent;
	
	if (p->_parent == Nul)   //被旋转的节点是根节点
		t = s;
	else if (p == p->_parent->_leftChild)  //不是根节点,判断是左子树还是右子树进行连接
		p->_parent->_leftChild = s; 
	else
		p->_parent->_rightChild = s;
		
	s->_rightChild = p;   //将节点的其他指针调整指向
	p->_parent = s;
}

为什么这次不同于AVL树使用引用传需要被旋转的值呢,从代码可以知道,这次直接在旋转的同时完成了连接,具体步骤的意义会标识在代码中,这样看着比较方便。

2.左单旋

void RBTree<Type>::RotateL(RBTreeNode<Type>*& t, RBTreeNode<Type>* p)
{
	RBTreeNode<Type>* s = p->_rightChild;
	/*判断即将要旋转的位置是否有左子树,有的话就将其挂在未来旋转过来的节点的右子树上
	  其次。如果没有,因为开头说过,所有节点的空节点,都指向了我们自己设置的空节点Nul,
	  所以只需要让p的右子树指向它就好了。*/
	if (s->_leftChild != Nul)
		s->_leftChild->_parent = p;
	p->_rightChild = s->_leftChild;
	s->_parent = p->_parent;
	
	if (p->_parent == Nul)  //被旋转的节点是根节点
		t = s;
	else if (p == p->_parent->_leftChild) //不是根节点,判断是左子树还是右子树进行连接
		p->_parent->_leftChild = s;
	else
		p->_parent->_rightChild = s;
		
	s->_leftChild = p;  //将节点的其他指针调整指向
	p->_parent = s;
}

四、红黑树的插入

template<typename Type>
void RBTree<Type>::_Insert(RBTreeNode<Type>* &t, const Type val)
{
	RBTreeNode<Type>* p = t;
	RBTreeNode<Type>* pr = Nul;
	while (p != Nul)    //寻找插入位置
	{
		if (val == p->_Val)  //不接受相同数据
			return;

		pr = p;

		if (val > p->_Val)
			p = p->_rightChild;
		else
			p = p->_leftChild;
	}

	p = _BuyNode(val);
	if (pr == Nul)  // 插入的是第一个根节点
	{
		t = p;
		t->_parent = pr;
	}

	if (val > pr->_Val)
		pr->_rightChild = p;
	else
		pr->_leftChild = p;
	p->_parent = pr;

	/*调整平衡*/
	In_balance(t, p);
}
template<typename Type>
void RBTree<Type>::In_balance(RBTreeNode<Type>*& t, RBTreeNode<Type>*& m)
{
	while (m->_parent->_color == RED)
	{
		RBTreeNode<Type>* u;   //uncle节点
		if (m->_parent == m->_parent->_parent->_leftChild)   //左分支
		{
			u = m->_parent->_parent->_rightChild;
			if (u->_color == RED)     //状况三   uncle为红色节点
			{
				m->_parent->_color = BLACK;
				m->_parent->_parent->_color = RED;
				u->_color = BLACK;
				m = m->_parent->_parent;
			}
			else    //uncle为黑色节点
			{
				if (m == m->_parent->_rightChild)  //状况二  
				{
					m = m->_parent;
					RotateL(t, m);
				}
				m->_parent->_color = BLACK;                  //状况一
				m->_parent->_parent->_color = RED;
				RotateR(t, m->_parent->_parent);
			}
		}
		else   //右分支
		{
			u = m->_parent->_parent->_leftChild;
			if (u->_color == RED)     //uncle为红色节点
			{
				//状况三  
				m->_parent->_color = BLACK;
				m->_parent->_parent->_color = RED;
				u->_color = BLACK;
				m = m->_parent->_parent;
			}
			else      //uncle为黑色节点
			{
				if (m == m->_parent->_leftChild)  //状况二  
				{
					m = m->_parent;
					RotateR(t, m);
				}
				m->_parent->_color = BLACK;                  //状况一
				m->_parent->_parent->_color = RED;
				RotateL(t, m->_parent->_parent);
			}
		}
	}
	t->_color = BLACK;  //不管如何调整,根节点一定是黑色
}

寻找插入位置就不多说了,仔细看一下就会了,主要说一下调整平衡这里:

调整平衡的两种情况

一、uncle节点为黑色

uncle可能存在也可能不存在,无所谓,不存在的话在我们设置的时候也是指向我们自己设置的黑色空节点Nul

情况一 插入节点在外侧插入(单旋转
在这里插入图片描述

我们只需要先将其父节点改为黑色,祖父节点改为红色,在进行单旋转即可达到平衡

情况二 插入节点在内侧插入(双旋转
在这里插入图片描述

先将其进行一次单旋转,使其变成情况一,再通过情况一着色,旋转,达到平衡,这里有一个小细节,就是我们需要提前将m节点追到m的父节点,因为我们的目标就是要让其成为情况一,仔细看过旋转函数的同学一定都发现了,旋转完之后父节点会转下去,所以我们需要根据旋转函数体现追到父节点,使其旋转过后成为情况一

二、uncle节点为红色

在这里插入图片描述

这时我们的处理比较简单,我们只需要将其father节点和uncle节点的颜色改为黑色,grandfather节点的颜色改为红色,然后继续向上调整即可,这时又会转换成上面的情况一或者情况二,再根据相应的调整方式进行调整即可

五、红黑树的删除

template<class Type>
void RBTree<Type>::_Remove(RBTreeNode<Type>*& t, const Type val)
{
	RBTreeNode<Type>* p = t;
	while (p != Nul)            //寻找要被删除的节点
	{
		if (p->_Val == val)
			break;

		if (val > p->_Val)
			p = p->_rightChild;
		else
			p = p->_leftChild;
	}
	
	RBTreeNode<Type>* q;    

	if (p == Nul)   //被删除节点不存在
		return;
	 
	if (p->_leftChild != Nul && p->_rightChild != Nul)   //被删除节点有左右子树
	{
		q = p->_leftChild;

		while (q->_rightChild != Nul)
			q = q->_rightChild;

		p->_Val = q->_Val;
		p = q;
	}

	if (p->_leftChild != Nul)   //被删除节点只有一个子树
		q = p->_leftChild;
	else
		q = p->_rightChild;
	q->_parent = p->_parent;   //将q节点挂到被删除的节点的父节点的子树上

	if (q->_parent == Nul) // 被删除的是根节点
	{
		t = q;
		t->_color = BLACK;
		delete p;
		return;
	}
	
	if (p == p->_parent->_leftChild)    //父节点在对应的左树或者右树连接p的子树
		p->_parent->_leftChild = q;
	else
		p->_parent->_rightChild = q;
	
	/*调整平衡*/
	if (p->_color == BLACK)
	{
		if (q != Nul)   //组合四: 直接互换颜色,删除p节点即可
			q->_color = BLACK;
		else            //组合二
			Re_balance(t, q);
	}
	delete p;
}
template<class Type>
void RBTree<Type>::Re_balance(RBTreeNode<Type>*& t, RBTreeNode<Type>*& m)
{
	while (m != t)
	{
		RBTreeNode<Type>* b;
		if (m == m->_parent->_leftChild)     //左分支
		{
			b = m->_parent->_rightChild;

			/*———  情形四  ———*/
			if (b->_color == RED)    
			{
				b->_color = BLACK;
				m->_parent->_color = RED;
				RotateL(t, m->_parent);
				b = m->_parent->_rightChild;
			}

			/*———  情形三  ———*/
			if (b->_leftChild->_color != RED && b->_rightChild->_color != RED)  
			{
				b->_color = RED;
				if (m->_parent->_color == RED)
				{
					m->_parent->_color = BLACK;
					m = t;
				}
				else
					m = m->_parent;    //向上回溯,继续判断
			}
			else
			{
				/*———  情形二  ———*/
				if (b->_leftChild->_color == RED)  
				{
					b->_color = RED;
					b->_leftChild->_color = BLACK;
					RotateR(t, b);
					b = b->_parent;
				}
				/*———  情形一  ———*/
				b->_color = m->_parent->_color;
				m->_parent->_color = BLACK;
				b->_rightChild->_color = BLACK;
				RotateL(t, m->_parent);

				m = t;
			}
		}
		else   //右分支
		{
			b = m->_parent->_leftChild;

			/*———  情形四  ———*/
			if (b->_color == RED)
			{
				b->_color = BLACK;
				m->_parent->_color = RED;
				RotateR(t, m->_parent);
				m = m->_parent;
			}

			/*———  情形三  ———*/
			if (b->_leftChild->_color != RED && b->_rightChild->_color != RED)
			{
				b->_color = RED;
				if (m->_parent->_color = RED)
				{
					m->_parent->_color = BLACK;
					m = t;
				}
				else
					m = m->_parent;
			}
			else
			{
				/*———  情形二  ———*/
				if (b->_rightChild->_color == RED)
				{
					b->_color = RED;
					b->_rightChild->_color = BLACK;
					RotateL(t, b);
					b = b->_parent;
				}

				/*———  情形一  ———*/
				b->_color = m->_parent->_color;
				m->_parent->_color = BLACK;
				b->_leftChild->_color = BLACK;
				RotateR(t, m->_parent);

				m = t;
			}
		}
		t->_color = BLACK;
	}
}

如何寻找删除位置以及,被删除节点的子节点的处理,跟AVL树相同,都将其化成至多只有一个子树 或者 没有子树的情况,所以这里就不在多说,主要说一下,删除时,不同颜色,不同位置的节点,如何进行删除。

删除时会遇到的六种情况

情况一:
删除节点为RED节点,并且为叶子节点,那么直接删除即可
在这里插入图片描述

情况二:
删除节点为RED节点,只有一个叶子节点
在这里插入图片描述

解释:
这种情况是不存在的,不然会导致其违背红黑树的性质——每条路径上的黑色节点数目相同;又或者违背红黑树的性质——红色节点不能相连

情况三:
删除节点为BLACK节点,只有一个叶子节点
在这里插入图片描述

解释:
该节点的叶子节点颜色只能为RED,如果是BLACK节点,还是会违背红黑树的性质——每条路径上的黑色节点数目相同,所以,只能是RED叶子节点,那么直接将叶子节点颜色改为BLACK,用叶子节点代替被删除节点的位置,即可达到平衡

情况四、五
被删除节点有两个节点,这里被删除节点可能为RED或者BLACK
在这里插入图片描述解释:
这里的替换寻找都与AVL树相同,这里节点颜色不一定就是这个样子,只是举例而已,所以不在多说,替换之后,情况四、五将转化成情况三 或者 情况六

情况六
删除节点为BLACK节点,且没有子节点。

这种情况下又有四种情形:

情形一:
被删除节点的brother节点有一个于其方向相同的子节点
在这里插入图片描述

解释:
先将father节点和brother节点的颜色互换,然后对father节点进行一次左旋转,然后将mine节点删除,就可以达到平衡。

情形二:
被删除节点的brother节点有一个于其方向相反的子节点
在这里插入图片描述

解释:
首先,先将brother节点与son节点颜色互换,然后对brother节点进行一次右旋转,这时,就变成了情形一,再进行情形一的操作,就可以达到平衡

情形三
brother节点没有红色子节点
在这里插入图片描述

解释:
当father节点为红色时,先将brother颜色改为红色然后将father节点颜色改为黑色,最后将mine节点删除即可达到平衡
在这里插入图片描述

解释:
这里细心的小伙伴可以看到,father节点从圆形变成了黑色,这里叫做“双重黑色”,它是我们假定的黑色,它并不是真实存在的,而是我们自己主观的想象这种情况的出现是mine节点将自己的黑色给了father节点,这样我们就当作它平衡了,它黑色减少了,但是father本来就是黑色,然后现在有多了一重,所以是双重黑色,那么理所当然,我们需要删掉这个多余的黑色,所以需要将brother节点颜色改为红色然后继续向上回溯,继续调整平衡。

情况四
brother节点为红色
在这里插入图片描述

解释:
先将father和brother节点的颜色进行调整,然后对father节点进行左旋,这时,新的brother节点就是son节点,这就转化成brother节点为BLACK的情况,这样就可以转化成上面其他几种情况来进行响应的调整。

六、源代码

#include<iostream>
#include<stack>
#include<vector>
using namespace std;
enum Color { BLACK = 0, RED = 1 };  //设置颜色

template<typename Type>    //类的前向声明,不然因为编译器版本原因可能在声明友元类的时候出错
class RBTree;

template<typename Type>
class RBTreeNode
{
	friend class RBTree<Type>;   //成为友元类,可以访问节点私有成员
public:
	RBTreeNode(Type val = Type())
		:_rightChild(nullptr), _leftChild(nullptr), _parent(nullptr), _Val(val), _color(RED)
	{}
	~RBTreeNode()
	{}
private:
	Type _Val;
	Color _color;
	RBTreeNode<Type>* _rightChild;
	RBTreeNode<Type>* _leftChild;
	RBTreeNode<Type>* _parent;
};

template<typename Type>
class RBTree
{
public:
	RBTree() :Nul(_BuyNode()), _root(Nul)
	{
		Nul->_leftChild = Nul->_rightChild = Nul->_parent = nullptr;
		Nul->_color = BLACK;
	}
public:
	void Insert(Type val = Type())
	{
		_Insert(_root, val);
	}
	void Remove(Type val = Type())
	{
		_Remove(_root, val);
	}
protected:
	void _Insert(RBTreeNode<Type>*& t,const Type val);
	void In_balance(RBTreeNode<Type>*& t, RBTreeNode<Type>*& m);
	void _Remove(RBTreeNode<Type>*& t, const Type val);
	void Re_balance(RBTreeNode<Type>*& t, RBTreeNode<Type>*& m);
	void RotateL(RBTreeNode<Type>*& t, RBTreeNode<Type>* p);
	void RotateR(RBTreeNode<Type>*& t, RBTreeNode<Type>* p);
protected:
	RBTreeNode<Type>* _BuyNode(const Type val = Type())
	{
		RBTreeNode<Type>* s = new RBTreeNode<Type>(val);
		s->_leftChild = s->_rightChild = Nul;
		return s;
	}
private:
	RBTreeNode<Type>* Nul;
	RBTreeNode<Type>* _root;
};

template<typename Type>
void RBTree<Type>::RotateL(RBTreeNode<Type>*& t, RBTreeNode<Type>* p)
{
	RBTreeNode<Type>* s = p->_rightChild;
	if (s->_leftChild != Nul)
		s->_leftChild->_parent = p;
	p->_rightChild = s->_leftChild;
	s->_parent = p->_parent;
	if (p->_parent == Nul)
		t = s;
	else if (p == p->_parent->_leftChild)
		p->_parent->_leftChild = s;
	else
		p->_parent->_rightChild = s;
	s->_leftChild = p;
	p->_parent = s;
}
template<typename Type>
void RBTree<Type>::RotateR(RBTreeNode<Type>*& t, RBTreeNode<Type>* p)
{
	RBTreeNode<Type>* s = p->_leftChild;
	if (s->_rightChild != Nul)
		s->_rightChild->_parent = p;
	p->_leftChild = s->_rightChild;
	s->_parent = p->_parent;
	if (p->_parent == Nul)
		t = s;
	else if (p == p->_parent->_leftChild)
		p->_parent->_leftChild = s;
	else
		p->_parent->_rightChild = s;
	s->_rightChild = p;
	p->_parent = s;
}
template<typename Type>
void RBTree<Type>::_Insert(RBTreeNode<Type>* &t, const Type val)
{
	RBTreeNode<Type>* p = t;
	RBTreeNode<Type>* pr = Nul;
	while (p != Nul)    //寻找插入位置
	{
		if (val == p->_Val)  //不接受相同数据
			return;

		pr = p;

		if (val > p->_Val)
			p = p->_rightChild;
		else
			p = p->_leftChild;
	}

	p = _BuyNode(val);
	if (pr == Nul)  // 插入的是第一个根节点
	{
		t = p;
		t->_parent = pr;
	}

	if (val > pr->_Val)
		pr->_rightChild = p;
	else
		pr->_leftChild = p;
	p->_parent = pr;

	/*调整平衡*/
	In_balance(t, p);
}
template<typename Type>
void RBTree<Type>::In_balance(RBTreeNode<Type>*& t, RBTreeNode<Type>*& m)
{
	while (m->_parent->_color == RED)
	{
		RBTreeNode<Type>* u;   //uncle节点
		if (m->_parent == m->_parent->_parent->_leftChild)   //左分支
		{
			u = m->_parent->_parent->_rightChild;
			if (u->_color == RED)     //状况三   uncle为红色节点
			{
				m->_parent->_color = BLACK;
				m->_parent->_parent->_color = RED;
				u->_color = BLACK;
				m = m->_parent->_parent;
			}
			else    //uncle为黑色节点
			{
				if (m == m->_parent->_rightChild)  //状况二  
				{
					m = m->_parent;
					RotateL(t, m);
				}
				m->_parent->_color = BLACK;                  //状况一
				m->_parent->_parent->_color = RED;
				RotateR(t, m->_parent->_parent);
			}
		}
		else   //右分支
		{
			u = m->_parent->_parent->_leftChild;
			if (u->_color == RED)     //uncle为红色节点
			{
				//状况三  
				m->_parent->_color = BLACK;
				m->_parent->_parent->_color = RED;
				u->_color = BLACK;
				m = m->_parent->_parent;
			}
			else      //uncle为黑色节点
			{
				if (m == m->_parent->_leftChild)  //状况二  
				{
					m = m->_parent;
					RotateR(t, m);
				}
				m->_parent->_color = BLACK;                  //状况一
				m->_parent->_parent->_color = RED;
				RotateL(t, m->_parent->_parent);
			}
		}
	}
	t->_color = BLACK;
}
template<class Type>
void RBTree<Type>::_Remove(RBTreeNode<Type>*& t, const Type val)
{
	RBTreeNode<Type>* p = t;
	while (p != Nul)
	{
		if (p->_Val == val)
			break;

		if (val > p->_Val)
			p = p->_rightChild;
		else
			p = p->_leftChild;
	}
	
	RBTreeNode<Type>* q;    

	if (p == Nul)   //被删除节点不存在
		return;
	 
	if (p->_leftChild != Nul && p->_rightChild != Nul)   //被删除节点有左右子树
	{
		q = p->_leftChild;

		while (q->_rightChild != Nul)
			q = q->_rightChild;

		p->_Val = q->_Val;
		p = q;
	}

	if (p->_leftChild != Nul)   //被删除节点只有一个子树
		q = p->_leftChild;
	else
		q = p->_rightChild;
	q->_parent = p->_parent;   //将q节点挂到被删除的节点的父节点的子树上

	if (q->_parent == Nul) // 被删除的是根节点
	{
		t = q;
		t->_color = BLACK;
		delete p;
		return;
	}
	
	if (p == p->_parent->_leftChild)    //父节点在对应的左树或者右树连接p的子树
		p->_parent->_leftChild = q;
	else
		p->_parent->_rightChild = q;
	
	/*调整平衡*/
	if (p->_color == BLACK)
	{
		if (q != Nul)   //组合四: 直接互换颜色,删除p节点即可
			q->_color = BLACK;
		else            //组合二
			Re_balance(t, q);
	}
	delete p;
}
template<class Type>
void RBTree<Type>::Re_balance(RBTreeNode<Type>*& t, RBTreeNode<Type>*& m)
{
	while (m != t)
	{
		RBTreeNode<Type>* b;
		if (m == m->_parent->_leftChild)     //左分支
		{
			b = m->_parent->_rightChild;

			/*———  情形四  ———*/
			if (b->_color == RED)    
			{
				b->_color = BLACK;
				m->_parent->_color = RED;
				RotateL(t, m->_parent);
				b = m->_parent->_rightChild;
			}

			/*———  情形三  ———*/
			if (b->_leftChild->_color != RED && b->_rightChild->_color != RED)  
			{
				b->_color = RED;
				if (m->_parent->_color == RED)
				{
					m->_parent->_color = BLACK;
					m = t;
				}
				else
					m = m->_parent;    //向上回溯,继续判断
			}
			else
			{
				/*———  情形二  ———*/
				if (b->_leftChild->_color == RED)  
				{
					b->_color = RED;
					b->_leftChild->_color = BLACK;
					RotateR(t, b);
					b = b->_parent;
				}
				/*———  情形一  ———*/
				b->_color = m->_parent->_color;
				m->_parent->_color = BLACK;
				b->_rightChild->_color = BLACK;
				RotateL(t, m->_parent);

				m = t;
			}
		}
		else   //右分支
		{
			b = m->_parent->_leftChild;   //兄弟节点

			/*———  情形四  ———*/
			if (b->_color == RED)
			{
				b->_color = BLACK;
				m->_parent->_color = RED;
				RotateR(t, m->_parent);
				m = m->_parent;
			}

			/*———  情形三  ———*/
			if (b->_leftChild->_color != RED && b->_rightChild->_color != RED)
			{
				b->_color = RED;
				if (m->_parent->_color = RED)
				{
					m->_parent->_color = BLACK;
					m = t;
				}
				else
					m = m->_parent;
			}
			else
			{
				/*———  情形二  ———*/
				if (b->_rightChild->_color == RED)
				{
					b->_color = RED;
					b->_rightChild->_color = BLACK;
					RotateL(t, b);
					b = b->_parent;
				}

				/*———  情形一  ———*/
				b->_color = m->_parent->_color;
				m->_parent->_color = BLACK;
				b->_leftChild->_color = BLACK;
				RotateR(t, m->_parent);

				m = t;
			}
		}
		t->_color = BLACK;
	}
}
int main()
{
	RBTree<int> Rb;
	vector<int> iv = { 10, 7,  8, 15, 5, 6, 11, 13, 12 };
	for (int i = 0; i < iv.size(); ++i)
	{
		Rb.Insert(iv[i]);
	}

	Rb.Remove(11);
	Rb.Remove(13);
	Rb.Remove(8);
	Rb.Remove(12);
	Rb.Remove(6);

	return 0;
}
  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值