简单理解红黑树的插入

         红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。

一、初步理解红黑树

        1.基本性质

(1). 每个结点不是红色就是黑色

(2). 根节点是黑色的 

(3). 如果一个节点是红色的,则它的两个孩子结点是黑色的 

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

(5). 每个叶子结点都是黑色的(此处的叶子结点指的是空结点) 

        2.红黑树的节点结构

template<class T>
struct RBTreeNode
{
	typedef RBTreeNode<T> Node;
	Node* _parent;
	Node* _left;
	Node* _right;
	colour _col;
	T _data;

	RBTreeNode(const T& data)
		:_parent(nullptr)
		, _left(nullptr)
		, _right(nullptr)
		, _col(RED)
		, _data(data)
	{
	}
};

二、红黑树的插入

        因为新节点的默认颜色是红色,因此:如果其双亲节点的颜色是黑色,没有违反红黑树任何性质,则不需要调整;但当新插入节点的双亲节点颜色为红色时,就违反了性质三不能有连在一起的红色节点,此时需要对红黑树分情况来讨论:

        

        可以总结以上情况为:

        1.父亲节点为黑,则不需要处理。

        2.父亲节点为红且uncle节点存在且为红,只需要grand变红,uncle和parent变黑继续向上讨论即可。

        3.父亲节点为红且uncle为黑色或者不存在,需要旋转加变色,旋转的情况需要讨论:如果grand节点、parent节点、cur节点在同一侧则只单旋,parent变黑,grand变红;反之则需要双旋,cur变黑,grand变红。以下为红黑树插入代码C++实现。

bool insert(const T& data)
	{
		KeyOfT kot;//提取key值的仿函数对象
		if (_root == nullptr)
		{
			_root = new Node(data);
			_root->_col = BLACK;
			return true;
		}
		Node* cur = _root, * parent = nullptr;
		while (cur)
		{
			if (kot(data) > kot(cur->_data))
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (kot(data) < kot(cur->_data))
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return false;
			}
		}
		cur = new Node(data);
		if (kot(parent->_data) > kot(data))
		{
			parent->_left = cur;
		}
		else
		{
			parent->_right = cur;
		}
		cur->_parent = parent;

		while (parent && parent->_col == RED)
		{
			Node* pparent = parent->_parent;
			if (pparent->_left == parent)
			{
				Node* uncle = pparent->_right;
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					pparent->_col = RED;

					cur = pparent;
					parent = cur->_parent;
				}
				else
				{
					if (parent->_left == cur)
					{
						RevolveR(pparent);
						parent->_col = BLACK;
						pparent->_col = RED;
					}
					else
					{
						RevolveL(parent);
						RevolveR(pparent);
						cur->_col = BLACK;
						pparent->_col = RED;
					}

                     break;

				}
			}
			else
			{
				Node* uncle = pparent->_left;
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					pparent->_col = RED;

					cur = pparent;
					parent = cur->_parent;
				}
				else
				{
					if (parent->_right == cur)
					{
						RevolveL(pparent);
						parent->_col = BLACK;
						pparent->_col = RED;
					}
					else
					{
						RevolveR(parent);
						RevolveL(pparent);
						cur->_col = BLACK;
						pparent->_col = RED;
					}

                    break;

				}

			}
			_root->_col = BLACK;
		}
		return true;
	}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值