RBTree----红黑树

1.概念:

        红黑树是一颗二叉搜索树,它在每一个节点上增加了一个存储位来表示节点的颜色(红/黑)。红黑树保证最长路径不超过最短路径的2倍,因而近似于平衡。

2.性质:

        (1)每一个节点,不是红色就是黑色。

        (2)根节点是黑色的。

        (3)不能有连续的红节点。

        (4)对于每个节点,从该节点到其所有后代叶子节点的路径上,黑节点的数目相等。

       (5)每一个NIL(空节点)节点是黑色的。

3.插入的情况

cur为当前节点/p为父节点/pp为祖先/u为叔叔节点

(1)cur为红,p为红,pp为黑,u存在且为红。

思路:将p,u改为黑,pp改为红,然后pp当cur,继续向上调整。

          

调整前的图


调整后的图

(2)cur为红,p为红,pp为黑,u不存在/为黑.

 思路:进行单旋转

            进行右单旋:


旋转前的图


旋转后的图

        左单旋也是类似的

(3)cur为红,p为红,pp为黑,u不存在/为黑.

思路:进行双旋转

          进行左右旋转


旋转前的图


旋转后的图

     右左旋转也是类似的。

4.判断平衡:根据它的性质来判定它是否平衡。

5.代码:

#pragma once 
enum Colour
{
	RED,
	BLACK,
};
template<class K,class V>
struct RBTreeNode
{
	RBTreeNode<K,V>* _left;
	RBTreeNode<K,V>* _right; 
	RBTreeNode<K,V>* _parent; 
	K _key;
	V _value;
	Colour _col;
	RBTreeNode(const K& key,const V& value)
		:_key(key)
		,_value(value)
		,_left(NULL)
		,_right(NULL)
		,_parent(NULL)
		,_col(RED)
	{}
};
template<class K,class V>
class RBTree
{
	typedef RBTreeNode<K,V> Node;
public:
	RBTree()
		:_root(NULL)
	{}
	bool Insert(const K& key,const V& value)
	{
		if(_root==NULL)
		{
			_root=new Node(key,value);
			_root->_col =BLACK;
			return true;
		}
		Node* cur=_root;
		Node* parent=cur;
		while(cur)
		{
			if(cur->_key <key)
			{
				parent=cur;
				cur=cur->_right ;
			}
			else if(cur->_key >key)
			{
				parent=cur;
				cur=cur->_left ;
			}
			else 
				return false;
		}
		cur=new Node(key,value);
		if(parent->_key <key)
		{
			parent->_right =cur;
			cur->_parent =parent;
		}
		else
		{
			parent->_left =cur;
			cur->_parent =parent;
		}
		//调整RB节点
		while(cur!=_root&&parent->_col ==RED)      //祖先肯定存在并且为黑
		{
			Node* ppNode=parent->_parent ;
			Node* uncle=NULL;
			if(ppNode->_left ==parent)
				uncle=ppNode->_right ;
			else
				uncle=ppNode->_left ;
			//第一种情况   
			if(uncle&&uncle->_col ==RED)  
			{
				uncle->_col =BLACK;
				parent->_col =BLACK;
				ppNode->_col =RED;
				cur=ppNode;
				parent=ppNode->_parent ;
			}
			//第二种情况
			else if((uncle==NULL)||(uncle->_col =BLACK))
			{
				if(ppNode->_left ==parent&&parent->_left ==cur)
				{
					RotateR(ppNode);
					break;
				}
				else if(ppNode->_right ==parent&&parent->_right ==cur)
				{
					RotateL(ppNode);
					break;
				}
				//第三种情况
				else if(ppNode->_left ==parent&&parent->_right ==cur)
				{
					RotateLR(ppNode);
					break;
				}
				else if(ppNode->_right ==parent&&parent->_left ==cur)
				{
					RotateRL(ppNode);
					break;
				}
			}
		}
		_root->_col =BLACK;
		return true;
	}
	bool IsBlance()
	{
		if(_root==NULL)
			return true;
		if(_root->_col ==RED)  //根节点必须是黑色
			return false;
		//统计任意一条路径上黑节点的个数
		int count=0;
		Node* cur=_root;
		while(cur)
		{
			if(cur->_col ==BLACK)
				count++;
			cur=cur->_left ;
		}
		int num=0;
		return _IsBlance(_root,num,count);
	}
	void InOrder()
	{
		_InOrder(_root);
	}
	~RBTree()
	{
		_Destory(_root);
	}
protected:
	void _Destory(Node* root)
	{
		if(_root==NULL)
			return;
		_Destory(root->_left );
		_Destory(root->_right );
		delete root;
	}
	bool _IsBlance(Node* root,int num,const int& count)
	{
		if(root==NULL)   //访问到叶子节点了
			return num==count;
		if(root->_col ==RED&&root->_parent ->_col ==RED)  //不能有相连的红节点
			return false;
		if(root->_col ==BLACK)
			num++;
		return _IsBlance(root->_left ,num,count)&&_IsBlance(root->_right ,num,count);
	}
	void _InOrder(Node* root)
	{
		if(root==NULL)
			return;
		_InOrder(root->_left );
		cout<<root->_key <<" "<<root->_col <<endl;
		_InOrder(root->_right );
	}
	void RotateLR(Node* ppNode)
	{
		RotateL(ppNode->_left );
		RotateR(ppNode);
	}
	void RotateRL(Node* ppNode)
	{
		RotateR(ppNode->_right );
		RotateL(ppNode);
	}
	void RotateR(Node* ppNode)
	{
		Node* parent=ppNode->_left ;
		Node* subR=parent->_right ;
		ppNode->_left =subR;
		if(subR)
			subR->_parent =ppNode;
		Node* pppNode=ppNode->_parent ;
		if(pppNode==NULL)
		{
			_root=parent;
			parent->_parent =NULL;
		}
		else
		{
			if(pppNode->_left ==ppNode)
				pppNode->_left =parent;
			else
				pppNode->_right =parent;
			parent->_parent =pppNode;
		}
		parent->_right =ppNode;
		ppNode->_parent =parent;

		parent->_col =BLACK;
		ppNode->_col =RED;
	}
	void RotateL(Node* ppNode)
	{
		Node* parent=ppNode->_right ;
		Node* subL=parent->_left ;
		ppNode->_right =subL;
		if(subL)
			subL->_parent =ppNode;
		Node* pppNode=ppNode->_parent ;
		if(pppNode==NULL)
		{
			_root=parent;
			parent->_parent =NULL;
		}
		else
		{
			if(pppNode->_left ==ppNode)
				pppNode->_left =parent;
			else
				pppNode->_right =parent;
			parent->_parent =pppNode;
		}
		parent->_left =ppNode;
		ppNode->_parent =parent;

		parent->_col =BLACK;
		ppNode->_col =RED;
	}
private:
	Node* _root;
};
void TestRBTree()
{
	RBTree<int,int> t;
	//int a[]={4,3,8,2,10,9};
	int a[]={16,3,7,9,11,26,18,14}; 
	//int a[]={16,3,7,9,11,26,18}; 
	for(int i=0;i<sizeof(a)/sizeof(a[0]);++i)
	{
		t.Insert (a[i],i);
	}
	t.InOrder ();  //红 0 黑 1
	cout<<t.IsBlance ()<<endl; 
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值