数据结构之红黑树

1.红黑树的性质

红黑树是一个最长的分支不大于最短分支2倍的一颗平衡搜索数

为了满足这个目标有如下特性:

a.根节点必须是黑色

b.红色结点的双亲必须是黑色结点

c.每条路径上的黑色结点数量相同

d.nil是黑色结点

如图:


2. 红黑数的插入

首先由于1中的特性c的存在,如果我们将新插入的结点的颜色设置为黑色的话会给我们带来很大的麻烦。所以我们要选择红色作为新插入结点的颜色。

我们将新插入的结点叫做cur,cur的父亲结点叫做parent,parent的父亲结点叫做grandfather,grandfather另一个儿子叫做uncle。

插入情况1:(uncle是红色)

 此时我们只需要改变parent grandfather uncle的颜色就可以实现调整

插入情况2:(uncle是空或者黑色)

a.当cur parent grandfather 呈现 / 形时对g右旋转,同时将parent grandfather变色

   当cur parent grandfather 呈现 \ 形时对g左旋转,同时将parent grandfather变色

 b.当cur parent grandfather 呈现 < 形时,先对p左旋转,在对g右旋转,同时将cur grandfather变色。

     当cur parent grandfather 呈现 > 形时,先对p右旋转,在对g左旋转,同时cur grandfather变色。


3.代码

using namespace std;
enum colour
{
	Red,
	Black
};
template<class k,class v>
class RBNode
{
public:
	RBNode(const pair<k,v>& kv)
		:_left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
		,_kv(kv)
		{}

public:
	pair<k, v> _kv;
	RBNode<k, v>* _left;
	RBNode<k, v>* _right;
	RBNode<k, v>* _parent;
	colour _col;
};
template<class k,class v>
class RBTree
{
	typedef RBNode<k,v> Node;
public:
	bool Insert(const pair<k, v>& kv)
	{
		Node* cur = _root;	Node* parent = nullptr;
		if (_root == nullptr)
		{
			_root = new Node(kv);
			_root->_col = Black;
			return true;
		}
		while (cur)
		{
			if (kv.first < cur->_kv.first)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (kv.first > cur->_kv.first)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
				return false;
		}
        //找到位置
		cur = new Node(kv);
		cur->_col = Red; // 设置颜色为红色
		if (kv.first < parent->_kv.first)
			parent->_left = cur;
		else
			parent->_right = cur;
		cur->_parent = parent;
        
        //如果parent的颜色是黑色就不需要继续处理
		while (parent && parent->_col == Red)
		{
			Node* grandfather = parent->_parent;
			assert(grandfather);
			assert(grandfather->_col == Black);
			Node* uncle = nullptr;
			if (grandfather->_left == parent)
				uncle = grandfather->_right;
			else
				uncle = grandfather->_left;
            //情况1 只需要变色
			if (uncle && uncle->_col == Red)
			{
				parent->_col = Black;
				uncle->_col = Black;
				grandfather->_col = Red;
				cur = grandfather;
				parent = cur->_parent;
			}
			else
			{
                //情况2 中 / \ 形状
				if (parent->_left == cur && grandfather->_left == parent)
				{
					RoateR(grandfather);
					grandfather->_col = Red;
					parent->_col = Black;
					break;
				}
				else if (parent->_right == cur && grandfather->_right == parent)
				{
					RoateL(grandfather);
					grandfather->_col = Red;
					parent->_col = Black;
					break;
				}
                //情况2 中 < > 形状
				else if (parent->_left == cur && grandfather->_right == parent)
				{
					RoateR(parent);
					RoateL(grandfather);
					grandfather->_col = Red;
					cur->_col = Black;
					break;
				}
				else
				{
					RoateL(parent);
					RoateR(grandfather);
					grandfather->_col = Red;
					cur->_col = Black;
					break;
				}
			}
		}
		_root->_col = Black;
		return true;
	}
	void InOrder()
	{
		_InOrder(_root);
	}
private:
	void _InOrder(Node* root)
	{
		if (root == nullptr)
			return;
		_InOrder(root->_left);
		cout << root->_kv.first<<" ";
		_InOrder(root->_right);
	}
    //左转
	void RoateL(Node* parent)
	{
		Node* subr = parent->_right;
		Node* subrl = subr->_left;
		parent->_right = subrl;
		if (subrl)
			subrl->_parent = parent;
		Node* ppnode = parent->_parent;
		subr->_left = parent;
		parent->_parent = subr;
		if (ppnode)
		{
			if (ppnode->_left == parent)
			{
				ppnode->_left = subr;
				subr->_parent = ppnode;
			}
			else
			{
				ppnode->_right = subr;
				subr->_parent = ppnode;
			}
		}
		else
		{
			_root = subr;
			subr->_parent = nullptr;
		}
	}
    //右转
	void RoateR(Node* parent)
	{
		Node* subl = parent->_left;
		Node* sublr = subl->_right;
		parent->_left = sublr;
		if (sublr)
			sublr->_parent = parent;
		Node* ppnode = parent->_parent;
		subl->_right = parent;
		parent->_parent = subl;
		if (ppnode)
		{
			if (ppnode->_left == parent)
			{
				ppnode->_left = subl;
				subl->_parent = ppnode;
			}
			else
			{
				ppnode->_right = subl;
				subl->_parent = ppnode;
			}
		}
		else
		{
			_root = subl;
			subl->_parent = nullptr;
		}
	}
	Node* _root=nullptr;

};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会敲代码的运气选手^

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值