数据结构:红黑树

1.0 红黑树的特性:

前提:红黑树也是特殊的二叉搜索树

(1) 每个节点或者是黑色,或者是红色。
(2) 根节点是黑色。
(3) 每个叶子节点是黑色。 [ 注意:这里叶子节点,是指为空的叶子节点!]
(4) 如果一个节点是红色的,则它的子节点必须是黑色的。

(5) 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相 同数目的黑色结点(每条路径上黑色结点的数量相等) 。

2.0 主要操作: 节点插入 Insert函数的实现

考虑1:满足上面的颜色约束性质,红黑树能保证最长路径不超过最短路径的两倍?

极限情况:                                                                       

 

  插入黑色节点,不满足特性5

 

插入红色节点,不满足特性4


考虑2:节点构造时,必须有颜色这个成员,默认颜色给什么好?

          

所以,节点默认颜色红色比较好。

左单旋,右单旋请参考:点击打开链接

3.0 插入的具体情况:

         情况1: 树为空,则将插入的节点颜色改为黑色即可(因为默认为红色节点)。

          情况2: 插入节点的双亲节点为黑色,不违反规则,什么都不改。

插入节点的双亲节点为红色时,需要作出变色以及旋转处理:

定义:cur为当前节点,p为其双亲节点,g为其祖父节点,u为其叔叔节点。

         情况3: u存在且为红色,处理过程为下图:

4:

         情况4: u不存在,或者u存在且为黑色,处理过程为下图:  g变为红色,p变为黑色


        情况5: 同情况4,不过cur为parent的右孩子,处理过成如下图:



4.0 实现代码:

RBtree.h

#pragma once
#include<iostream>
using namespace std;
enum COLOR {RED,BLACK};
template <class k,class v >
struct RBTreeNode
{
	RBTreeNode(k key,v value,COLOR color=RED)
		: _left(NULL)
		, _right(NULL)
		, _parent(NULL)
		, _value(key,value)
		, _color(color)
	{}
	RBTreeNode* _left;
	RBTreeNode* _right;
	RBTreeNode* _parent;
	pair<k, v>  _value;
	COLOR _color;
};
template <class k, class v >
class RBTree
{
	typedef RBTreeNode<k, v> Node;
	typedef  Node* PNode;
public:
	//构造函数
	RBTree()
		:_root(NULL)
	{}
	bool InsertUnique(const pair<k, v>& value)
	{
		return _InsertUnique(value, _root);
	}
	void InOrder()
	{
		_InOrder(_root);
	}
	bool IsRBtree()
	{
		if (NULL == _root)        //空树也是红黑树
			return true;
		if (_root->_color == RED) //不满足性质2
		{
			cout <<"根节点为红色违反性质2"<< endl;
			return false;
		}
		//统计一条路径上的黑色节点个数(用count计数)
		PNode PCur = _root;
		size_t count = 0;
		while (PCur)
		{
			if (PCur->_color == BLACK)
				count++;
			PCur = PCur->_left;
		}
		size_t i = 0;    
		return _IsRBtree(_root, count,i);  //传参i的原因:递归实现需要记录黑色节点个数
	}                                     //而返回至该层时,期望i还是该层的值所以传值
protected:
	bool _InsertUnique(const pair<k, v>& value, PNode& _root)
	{
		if (NULL == _root)
		{
			_root = new Node(value.first, value.second, BLACK);
			return true;
		}
		//找待插入节点的位置	

		PNode PCur = _root;
		PNode parent = PCur;
		while (PCur)
		{
			parent = PCur;
			if (value.first > PCur->_value.first)
				PCur = PCur->_right;
			else if (value.first < PCur->_value.first)
				PCur = PCur->_left;
			else
				return false;
		}
		//插入新节点  PCur==NULL
		PCur = new Node(value.first, value.second);
		if (value.first > parent->_value.first)
		{
			parent->_right = PCur;
		}
		else
		{
			parent->_left = PCur;
		}
		PCur->_parent = parent;
		//更新节点颜色(红红相连不满足特性3)
		while (parent && parent->_color == RED)
		{
			PNode grandfather = parent->_parent;
			if (grandfather->_left == parent) //总的两种(1.parent,PCur均在grandfather的左侧)
			{
				PNode uncle = grandfather->_right;
				if (uncle && uncle->_color == RED)  //情况3
				{
					uncle->_color = BLACK;
					parent->_color = BLACK;
					grandfather->_color = RED;
					//向上更新PCur和parent
					PCur = grandfather;
					parent = PCur->_parent;
				}
				else     //uncle不存在或者uncle->_color == BLACK
				{
					if (PCur == parent->_right)  //情况5
					{
						RotateL(parent);
						swap(PCur, parent);  //交换指针指向之后才和情况4完全一致
					}
					parent->_color = BLACK;  //情况4,5的共同代码
					grandfather->_color = RED;
					RotateR(grandfather);
				}
			}
			else                               // 2.parent,PCur均在grandfathe的右侧
			{
				PNode uncle = grandfather->_left;
				if (uncle && uncle->_color == RED)  //情况3
				{
					uncle->_color = BLACK;
					parent->_color = BLACK;
					grandfather->_color = RED;
					//向上更新PCur和parent
					PCur = grandfather;
					parent = PCur->_parent;
				}
				else     //uncle不存在或者uncle->_color == BLACK
				{
					if (PCur == parent->_left)  //情况5
					{
						RotateR(parent);
						swap(PCur, parent); //交换指针指向之后才和情况4完全一致
					}
					parent->_color = BLACK;  //情况4,5的共同代码
					grandfather->_color = RED;
					RotateL(grandfather);
				}
			}
		}
		_root->_color = BLACK;             //循环外统一将_root->_color=BLACK
		return true;
	}
	void RotateL(PNode parent)
	{
		PNode PSubR = parent->_right;
		PNode PSubRL = PSubR->_left;
		parent->_right = PSubRL;
		if (PSubRL)
			PSubRL->_parent = parent;
		PSubR->_left = parent;
		PNode pparent = parent->_parent;
		PSubR->_parent = pparent;
		parent->_parent = PSubR;
		if (NULL == pparent)
			_root = PSubR;
		else
		{
			if (pparent->_left == parent)
				pparent->_left = PSubR;
			else
				pparent->_right = PSubR;
		}
	}
	void RotateR(PNode parent)
	{
		PNode PSubL = parent->_left;
		PNode PSubLR = PSubL->_right;
		parent->_left = PSubLR;
		if (PSubLR)
			PSubLR->_parent = parent;
		PSubL->_right = parent;
		PNode pparent = parent->_parent;
		PSubL->_parent = pparent;
		parent->_parent = PSubL;
		if (NULL == pparent)
			_root = PSubL;
		else
		{
			if (pparent->_left == parent)
				pparent->_left = PSubL;
			else
				pparent->_right = PSubL;
		}
	}
	void _InOrder(PNode _root)
	{
		if (_root)
		{
			_InOrder(_root->_left);
			cout << _root->_value.first << "," << _root->_value.second << "  ";
			_InOrder(_root->_right);
		}
	}
	bool _IsRBtree(PNode _root,size_t count,size_t i)
	{
		if (NULL == _root)        //空树也是红黑树
			return true;
		if (_root->_color == BLACK)
			i++;
		PNode parent = _root->_parent;
		if (parent&&_root->_color == RED&&parent->_color == RED)
		{
			cout <<"红红相连违反性质3"<< endl;
			return false;
		}
		if (NULL == _root->_left&&NULL == _root->_right)  //叶子结点
		{
			if (i != count)
			{
				cout << "路径中黑色节点的个数不相等违反性质4" << endl;
				return false;
			}
		}
		return _IsRBtree( _root->_left,count,i )&&_IsRBtree( _root->_right, count,i );
	}
private:
	PNode _root;
};
void RBtreeTest()
{
	int a[] = { 10, 7, 8, 15, 5, 6, 11, 13, 12 };
	int size = sizeof(a) / sizeof(a[0]);
	RBTree<int, int> rbt;
	for (int i = 0; i < size; ++i)
		rbt.InsertUnique(pair<int, int>(a[i],i));
	  //rbt.InsertUnique(make_pair(a[i], i)); 等价
	rbt.InOrder();
	cout << endl;
	cout<<rbt.IsRBtree();
}


main.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include"RBtree.h"
#include<iostream>
using namespace std;
int main()
{
	RBtreeTest();
	system("pause");
	return 0;
}
结果:




猜你喜欢

转载自blog.csdn.net/WhiskyCocktail/article/details/79793540