红黑树

1. 红黑树的概念

红黑树是一棵二叉搜索树,它在每一个结点上增加了一个存储位来标记结点的颜色,可以是red 或者 black。

2. 红黑树的性质

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

(2)树的根节点是黑色的

(3)没有两个连续的红色结点

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

3. 红黑树的插入

首先,我们规定新插入的结点是红色。在插入新结点后,可能会破坏红黑树的性质,此时,我们就需要对树进行调整。

红黑树的插入分为5种情况

(1)如果树为空,插入结点后会破坏性质2,此时,需要将颜色改为黑色。

(2)插入结点的父节点为黑色,不违反任何性质,直接插入。

(3)插入结点cur 为红色,pParent为红色,grandfather为黑色,uncle结点存在且为红色。

解决方法:将pParent结点 和 uncle结点改为黑色,grandfather结点改为红色,将cur=grandfather再向上调整

(4)插入结点cur为红色,pParent为红色,grandfather为黑色,uncle结点不存在或者为黑色。

解决方法:如果cur为pParent的左子树,pParent为grandfather的左子树,进行右旋;如果cur为pParent的右子树,pParent为grandfather的右子树,进行左旋;

再将pParent结点黑色,grandfather结点改为红色。

(5)插入结点cur为红色,pParent为红色,grandfather为黑色,uncle结点不存在或者为黑色。

解决方法:如果cur为pParent的右子树,pParent为grandfather的左子树,进行左旋;如果cur为pParent的左子树,pParent为grandfather的右子树,进行右旋;交换pParent和cur结点。

即转化为情况(4)处理。

整体代码如下:

bool InsertNode(const K& key, const V& value, COLOR color=RED)
	{
		if (_PRoot == NULL)
		{
			_PRoot = new Node(key, value);
			_PRoot->_color = BLACK;
			return true;
		}
		PNode Pcur = _PRoot;
		PNode pParent = NULL;
		while (Pcur)
		{
			if (key < Pcur->_key)
			{
				pParent = Pcur;
				Pcur = Pcur->_PLeft;
			}
			else if (key>Pcur->_key)
			{
				pParent = Pcur;
				Pcur = Pcur->_PRight;
			}
			else
			{
				return false;
			}
				

		}
		Pcur = new Node(key, value);
		if (pParent->_key > key)
			pParent->_PLeft = Pcur;
		else
			pParent->_PRight = Pcur;
		Pcur->_Pparent = pParent;

		while (_PRoot!=Pcur && pParent->_color==RED)
		{
			PNode grandFather = pParent->_Pparent;
			if (pParent == grandFather->_PLeft)
			{
              PNode uncle = pParent->_PRight;
			  if (uncle && uncle->_color == RED)//情况三
			  {
				  pParent->_color = BLACK;
				  uncle->_color = BLACK;
				  grandFather->_color = RED;
				  Pcur = Pcur->_Pparent->_Pparent;
			  }
			  else
			  {
				  if (Pcur == pParent->_PRight)//情况五
				  {
					  RotateL(pParent);
					  swap(pParent, Pcur);
				  }
				  pParent->_color = BLACK;
				  grandFather->_color = RED;
				  RotateR(grandFather);
			  }
			}
			else
			{
				PNode uncle = grandFather->_PLeft;
				if (uncle && uncle->_color == RED)
				{
					uncle->_color = BLACK;
					pParent->_color = BLACK;
					grandFather->_color = RED;
					Pcur = Pcur->_Pparent->_Pparent;
				}
				else
				{
					if (Pcur == pParent->_PLeft)
					{
						RotateR(pParent);
						swap(pParent, Pcur);
					}
					pParent->_color = BLACK;
					grandFather->_color = RED;
					RotateL(grandFather);
				}
				break;
			}

		}
		_PRoot->_color = BLACK;
		return true;
	}
void RotateL(PNode pParent)
	{
		PNode subR = pParent->_PRight;
		PNode subRL = subR->_PLeft;

		pParent->_PRight = subRL;
		if (subRL)
			subRL->_Pparent = pParent;

		subR->_PLeft = pParent;
		PNode ppParent = pParent->_Pparent;
		pParent->_Pparent = subR;
		subR->_Pparent = ppParent;
		
		if (_PRoot == pParent)
			_PRoot = subR;
		else
		{
			if (ppParent->_PLeft == pParent)
				ppParent->_PLeft = subR;
			else
				ppParent->_PRight = subR;
		}

	}

 

void RotateR(PNode pParent)
	{
		PNode subL = pParent->_PLeft;
		PNode subLR = subL->_PRight;

		pParent->_PLeft = subLR;
		if (subLR)
			subLR->_Pparent = pParent;

		subL->_PRight = pParent;
		PNode ppParent = pParent->_Pparent;
		pParent->_Pparent = subL;
		subL->_Pparent = ppParent;

		if (_PRoot == pParent)
			_PRoot = subL;
		else
		{
			if (ppParent->_PLeft == pParent)
				ppParent->_PLeft = subL;
			else
				ppParent->_PRight = subL;
		}
	}

4. 红黑树的查找平均长度

平均查找长度ASL=log N;

插入的时间复杂度 O(log N);

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值