C++ RBTree 理论

目录

这个性质可以总结为

红黑树的最短最长路径

红黑树的路径范围

code

结构

搞颜色

插入

插入逻辑

新插入节点

思考:2. 检测新节点插入后,红黑树的性质是否造到破坏?

解决方法

变色

旋转+变色

第三种情况,如果根节点上面还有节点


C++ RBTree 理论_第1张图片C++ RBTree 理论_第2张图片

这个性质可以总结为

1.每个节点不是红色就是黑色

2.根节点是黑色的

3.不能有两个连续的红色节点  ,即可以出现 红黑  黑黑 不能出现红红

4.每条路径上的黑色机节点数量不一样

至于性质5:每个叶子结点都是黑色的,这里的叶子节点并不是真的叶子节点,而是NIL节点,即空节点。如图(a):

C++ RBTree 理论_第3张图片

NIL节点有什么作用?如图(a-2),有多少条路径:C++ RBTree 理论_第4张图片

正确答案是有7条。路径路径的判断规则是:从根节点到NULL。

如果我们把NIL节点标记出来就好找路径了:

C++ RBTree 理论_第5张图片

再比如,图(a-3)是否是红黑树:

C++ RBTree 理论_第6张图片

大致一看好像是,但是把NIL节点标出来之后:

C++ RBTree 理论_第7张图片

 路径(b)只有两个黑色节点,不满足红黑树的性质,不是红黑树。

红黑树的最短最长路径

那么红黑树的最短路径是什么样子的,应该是全黑的最短:

 那最长的路径呢,应该是一黑一红间隔排列的最长:

C++ RBTree 理论_第8张图片根据图(a-1)我们可以看出,最长的路径是最短的路径的2倍。

ps

一个红黑树不一定有最长路径,也不一定有最短路径。

如图(a-2),有最短路径,没有最长路径:C++ RBTree 理论_第9张图片

红黑树的路径范围

而知道了最短路径,最长路径,剩下的路径都在最短路径,最长路径范围内,可以写为

                             [n,2*n]

code

结构

template
 struct	RBTreeNode
{
	 RBTreeNode* _left;
	 RBTreeNode* _right;
	 RBTreeNode* parent;
	 pair;
	Color _col;

	//初始话列表
	RBTreeNode(const pairkv)
		:_left(nullptr)
		,_right(nullptr)
		, _parent(nullptr)
		, pair
		,_col(RED)
	{}
};

搞颜色

enum Color
{
	RED,
    BALACK
};


 template
 class RBTree
 {
	 typedef RBTreenode Node;
 public:

 private:
	 Node* _root = nullptr;


 };

插入

插入逻辑

如果节点为空,就给黑色。如果节点不为空,就插入值。

这个值如果比根节点小,就往左边插入,否则就往右边插入。


	 bool Insert(const pair& kv)
	 {
		 if (_root == nullptr)
		 {
			 _root = new(kv);
			 _root->_col = BALACK;
			 return true;
		 }

		 //初始化父亲节点和根节点
		 Node* parent = nullptr;
		 Node* cur = _root;

		 while (cur)
		 {

			 //key值大,往右走
			 if (cur->kv.first < kv.first)
			 {
				 cur = cur->right;
			 }
			 //key值小,往左走
			 else if (cur->kv.first > kv.first)
			 {
				 cur = -cur->left;
			 }
			 //否则key值和当前节点相等,不插入
			 else
			 {
				 return false;
			 }
		 }


		 //找到了返回true1
		 return true;	 
	 }

新插入节点

思考:2. 检测新节点插入后,红黑树的性质是否造到破坏?

C++ RBTree 理论_第10张图片

如图(b-1),现在要插入一个节点,那么是插入一个黑色节点还是红色节点呢?

如果插入黑色节点,那么该路径就会多一个黑色节点,根据红黑树特性,其他路径都要补一棵黑色节点,

如果插入红色节点,则只会影响父节点

(即

1.如果父节点也会红节点。两个红节点不能紧挨,需调整

2.如果父亲节点是黑色,则不需调整,直接插入。)。

我们看一下怎么调整,如图(b-2),新插入了一个红色节点7:

C++ RBTree 理论_第11张图片

解决方法

能变色先变色,变色完之后还不行再旋转

变色

如图(b-3),先把父节点8变黑:

C++ RBTree 理论_第12张图片

这个时候该路径就多了一个黑色节点,再变图(b-4)把6节点变红:

C++ RBTree 理论_第13张图片这个时候该路径又少了个黑色节点,再变图(b-5) 把5节点变黑:

C++ RBTree 理论_第14张图片

旋转+变色

第二种情况,例如图(b-6):C++ RBTree 理论_第15张图片如果还是把父节点变为黑色,把6节点变为红色,那么其他路径就会多一个黑色节点。

而该路径又没有其他节点可以再变黑色来平衡这种状态,所以靠变色解决不了这个问题。

这个时候就要旋转了。

先右旋为图(c-1):

C++ RBTree 理论_第16张图片再左旋为图(c-2):

C++ RBTree 理论_第17张图片然后再变色为图(c-4):

C++ RBTree 理论_第18张图片

第三种情况,如果根节点上面还有节点

C++ RBTree 理论_第19张图片

如图(d-0),新插入了一个节点cur:

C++ RBTree 理论_第20张图片

cur为红色节点,那就需要调整。

把p节点变为黑色节点,那么为了u节点也要变为黑色节点,那么此时就要把g节点变为红色节点。也就是图(d-1)

为什么要把g节点变为红色节点呢?

假设g节点不变为红色也就是图(d-3):

C++ RBTree 理论_第21张图片

由图(d-1)变为图(d-3)我们发现每条路径凭空多了1个黑色节点。

g节点上面还有节点,那么多了个黑色节点,就会影响上面的路径,所以需要把g节点变红来平衡一下。

如图(d-1):C++ RBTree 理论_第22张图片

这个时候万一g节点的父节点是红色节点,如图(d-4):
C++ RBTree 理论_第23张图片两个红色节点不能连续,还要调整,如果g节点的父亲节点为黑色,如图(d-5),那就不需要再调整:

C++ RBTree 理论_第24张图片

你可能感兴趣的:(c++,开发语言)