红黑树

红黑树
     红黑树也是二叉搜索树,只是每个结点增加颜色表示。
     红黑树有以下规则:
  1. 每个结点不是red就是black
  2. 根结点为black
  3. 若结点为red,则它的两个子节点为black
  4. 从每一条路径(根到叶)均有相同数目的black
*红黑树保证最长路径不超过最短路径的两倍

二叉树在插入时的几种需要转换的情况:

情况1


情况2


情况3:


由上面的图像解释我们用文字可以这么描述:

新增节点为red:cur=RED,parent=RED,grandfather=BLACK

1、若uncle为RED,则p、u改为BLACK,g改为RED,cur=grandfather继续向上

2、若uncle为BLACK或NULL,p为g的左,cur为p的左,右单旋,p、g变色

3、若uncle为BLACK或NULL,p为g的左,cur为p的右,对p做左单旋;若p为g右,做右单旋

实现

enum color
{
	RED,
	BLACK,
};

template<class K,class V>

struct RBTreeNode
{

	K _key;
	V _value;

	RBTreeNode<K, V> *_left;
	RBTreeNode<K, V> * _right;
	RBTreeNode<K, V> * _parent;
	
	color _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
{
public:
	RBTree()
		:_root(NULL)
	{}
	bool Insert(const K& key, const V& value)
	{
		if (_root == NULL)
		{
			_root = new RBTreeNode<K, V>(key, value);
			_root->_col = BLACK;
			return true;
		}
		RBTreeNode<K, V>* parent = NULL;
		RBTreeNode<K, V>* cur = _root;
		while (cur)//找到要插入的位置
		{
			parent = cur;
			if (key > cur->_key)
			{
				cur = cur->_right;
			}
			else if (key < cur->_key)
			{
				cur = cur->_left;
			}
			else
				return false;
		}
		cur = new RBTreeNode<K, V>(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)//cur!=_root则父节点一定存在,若父节点的颜色为red则一定不是根结点
		{
			RBTreeNode<K, V> *grandfather = parent->_parent;
			if (grandfather->_left == parent)
			{
				RBTreeNode<K, V>*uncle = grandfather->_right;
				if (uncle&&uncle->_col == RED)
				{
					//情况1
					parent->_col = BLACK;
					uncle->_col = BLACK;
					grandfather->_col = RED;
					cur = grandfather;
					parent = cur->_parent;
				}
				else//情况2和情况3
				{
					if (parent->_right==cur)
					{
						_RotateL(parent);
						swap(cur, parent);
					}
					
					parent->_col = BLACK;
					grandfather->_col = RED;
					_RotateR(grandfather);
				}
			}
			else
			{
				RBTreeNode<K, V>*uncle = grandfather->_left;
				if (uncle&&uncle->_col == RED)
				{
					uncle->_col = BLACK;
					parent->_col = BLACK;
					grandfather->_col = RED;
					cur = grandfather;
					parent = cur->_parent;
				}
				else
				{
					if (cur == parent->_left)
					{
						_RotateR(parent);
						parent->_col = BLACK;
						grandfather->_col = RED;
						_RotateL(grandfather);
					}
					_root->_col = BLACK;
					return true;
				}
			}
		}
		_root->_col = BLACK;
		return true;
	}
	void Inorder()
	{
		_Inorder(_root);
		cout << endl;
	}
protected:
	void _Inorder(RBTreeNode<K, V>*root)
	{
		if (root == NULL)
			return;
		_Inorder(root->_left);
		cout << _root->_key << " ";
		_Inorder(_root->_right);
	}
	void _RotateL(RBTreeNode<K, V>*parent)
	{
		RBTreeNode<K, V>*subR = parent->_right;
		RBTreeNode<K, V>*subRL = subR->_left;

		parent->_right = subRL;
		if (subRL != NULL)
			subRL->_parent = parent;

		subR->_left= parent;
		RBTreeNode<K, V>*ppNode = parent->_parent;
		parent->_parent = subR;
		subR->_parent = ppNode;
		if (ppNode == NULL)
		{
			_root = subR;
		}
		else
		{
			if (ppNode->_left == parent)
				ppNode->_left = subR;
			else
				ppNode->_right = subR;
		}
	}
	void _RotateR(RBTreeNode<K, V>*parent)
	{
		RBTreeNode<K, V>*subL = parent->_left;
		RBTreeNode<K, V>*subLR = subL->_right;

		parent->_left = subLR;
		if (subLR != NULL)
			subLR->_parent = parent;

		subL->_right = parent;
		RBTreeNode<K, V>*ppNode = parent->_parent;
		parent->_parent = subL;
		subL->_parent = ppNode;
		if (ppNode == NULL)
			_root = subL;
		else
		{
			if (ppNode->_left == parent)
				ppNode->_left = subL;
			else
				ppNode->_right = subL;
		}
	}
private:
	RBTreeNode<K, V> *_root;

};

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值