平衡二叉树——红黑树

“test.cpp”

<strong><span style="font-size:18px;">#include<iostream>
using namespace std;

enum COLOUR
{
	BLACK,
	RED,
};

template<class K,class V>
struct RBTreeNode
{
	K _key;
	V _value;
	COLOUR _col;
	RBTreeNode<K,V>* _left;
	RBTreeNode<K,V>* _right;
	RBTreeNode<K,V>* _parent;

	RBTreeNode(const K& key,const V& value)
		:_key(key)
		,_value(value)
		,_col(RED)
		,_left(NULL)
		,_right(NULL)
		,_parent(NULL)
	{}
};

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 = NULL;

		while(cur)
		{
			if(cur->_key > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if(cur->_key < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
				return false;
		}

		cur = new Node(key,value);
		if(parent->_key > key)
		{
			parent->_left = cur;
			cur->_parent = parent;
		}
		else
		{
			parent->_right = cur;
			cur->_parent = parent;
		}

		//颜色调整
		while(cur != _root && parent->_col == RED)
		{
			Node* grandfather = parent->_parent;

			if(parent == grandfather->_left)
			{
				Node* uncle = grandfather->_right;
				
				//第一种情况 uncle存在且为红色
				if(uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;

					cur = grandfather;
					parent = cur->_parent;
				}
				//第二种和第三种情况
				//uncle不存在/uncle存在且为黑色
				else
				{
					//先处理第三种情况
					if(cur == parent->_right)
					{
						//针对parent进行左单旋
						_L_Roteta(parent);
						swap(parent,cur);
					}
					//第三种情况处理升级后变成第二种情况
					//和第二种情况一起处理
					_R_Roteta(grandfather);
					grandfather->_col = RED;
					parent->_col = BLACK;

					break;
				}
			}
			else//parent == grandfather->_right
			{
				Node* uncle = grandfather->_left;
				
				//第一种情况 uncle存在且为红
				if(uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;
					
					cur = grandfather;
					parent = cur->_parent;
				}
				//第二种情况和第三种情况
				//uncle不存在/uncle存在且为黑色
				else
				{
					//先处理第三种情况
					if(cur == parent->_left)
					{
						_R_Roteta(parent);
						swap(parent,cur);
					}
					//第三种情况升级为第二种情况
					//统一处理第二种情况
					_L_Roteta(grandfather);
					parent->_col = BLACK;
					grandfather->_col = RED;

					break;
				}
			}
		}
		
		_root->_col = BLACK;
		return true;
	}
	void InOrder()
	{
		_InOrder(_root);
		cout<<endl;
	}
	//判断一棵树是否是红黑树
	bool IsBlance()
	{
		//空树也是一棵红黑树
		if(_root == NULL)
			return true;

		//根节点的颜色是否是黑色
		if(_root->_col != BLACK)
			return false;

		//计算其中一条路径黑色节点的个数
		Node* cur = _root;
		size_t blackcount = 0;
		while(cur)
		{
			if(cur->_col == BLACK)
				++blackcount;
			
			cur = cur->_left;
		}

		size_t k = 0;
		return _IsBlance(_root,k,blackcount);
	}
protected:
	bool _IsBlance(Node* root,size_t k,const size_t blackcount)
	{
		if(root == NULL)
			return true;
		
		//红黑树上不能有连续的两个红节点
		if(root->_col == RED && root->_parent->_col == RED)
		{
			cout<<"连续的两个红节点"<<root->_key<<endl;
			return false;
		}

		//计算当前路径下黑色节点的个数
		if(root->_col == BLACK)
			++k;
		
		//每条路径下黑色节点的数目相同
		if(root->_left == NULL && root->_right == NULL)
		{
			if(k != blackcount)
			{
				cout<<"黑色节点的数目不相同"<<root->_key<<endl;
				return false;
			}
		}
		return _IsBlance(root->_left,k,blackcount)\
			&& _IsBlance(root->_right,k,blackcount);
	}
	void _InOrder(Node* root)
	{
		if(root == NULL)
		{
			return;
		}

		_InOrder(root->_left);
		cout<<root->_key<<"("<<root->_col<<") ";
		_InOrder(root->_right);
	}
	void _L_Roteta(Node* parent)
	{
		Node* ppNode = parent->_parent;
		Node* subR = parent->_right;
		Node* subRL = subR->_left;

		parent->_right = subRL;
		if(subRL)
			subRL->_parent = parent;
		subR->_left = parent;
		parent->_parent = subR;

		if(ppNode)
		{
			if(ppNode->_left == parent)
				ppNode->_left = subR;
			else
				ppNode->_right = subR;

			subR->_parent = ppNode;
		}
		else
		{
			_root = subR;
			subR->_parent = NULL;
		}
	}
	void _R_Roteta(Node* parent)
	{
		Node* ppNode = parent->_parent;
		Node* subL = parent->_left;
		Node* subLR = subL->_right;

		parent->_left = subLR;
		if(subLR)
			subLR->_parent = parent;
		subL->_right = parent;
		parent->_parent = subL;

		if(ppNode)
		{
			if(ppNode->_left == parent)
				ppNode->_left = subL;
			else
				ppNode->_right = subL;

			subL->_parent = ppNode;
		}
		else
		{
			_root = subL;
			subL->_parent = NULL;
		}
	}
	
private:
	Node* _root;
};

void test()
{
	RBTree<int,int> rbt;
	int arr[] = {16,3,7,11,9,26,18,14,15};
	size_t size = sizeof(arr)/sizeof(arr[0]);
	
	for(int i = 0;i < size;i++)
	{
		rbt.Insert(arr[i],i);
		cout<<"Isblance? "<<rbt.IsBlance()<<endl;;
	}
	rbt.InOrder();
}

int main()
{
	test();
	return 0;
}</span></strong>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值