红黑树(RBTree)的实现

本文深入讲解红黑树的基本特点及插入实现过程,并通过代码示例展示其内部运作机制。此外,还对比了红黑树与AVL树的区别,强调了红黑树在实际应用中的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

红黑树的特点:

1、任意一个结点要么是红色,要么是黑色
2、根结点是黑色
3、一条路径上不能出现两个连续的红色结点
4、从根节点到任一叶子节点的黑色结点个数相同
5、NUL结点默认为黑色结点(可忽略)


插入实现
注意:cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点
【情况一】cur为红,p为红,g为黑,u存在且为红则将p,u改为黑,g改为红,然后把g当成cur,继续向上调整。

【情况二】cur为红,p为红,g为黑,u不存在/u为黑p为g的左孩子,cur为p的左孩子,则进行右单旋转;相反,p为g的右孩子,cur为p的右孩子,则进行左单旋转p、g变色--p变黑,g变红

【情况三】cur为红,p为红,g为黑,u不存在/u为黑p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;相反,p为g的右孩子,cur为p的左孩子,则针对p做右单旋转则转换成了情况2

#pragma  once
#include<iostream>
using namespace std;


enum Color{RED,BLACK};

template<class K, class V>
struct RBTreeNode
{
	RBTreeNode(const K & key,const V & value,Color color = RED)
		:_value(value)
		,_key(key)
		,_pLeft(NULL)
		,_pRight(NULL)
		,_pParent(NULL)
		,_color(color)
	{

	}

	K _key;
	V _value;
	RBTreeNode<K,V> * _pLeft;
	RBTreeNode<K,V> *_pRight;
	RBTreeNode<K,V> *_pParent;
	Color _color;  //节点的颜色。
};
//红黑树迭代器实现
template<class K, class V, class Ref, class Ptr>
class Iterator
{
public:
	typedef RBTreeNode<K,V>  Node;
	typedef Iterator<K,V,Ref,Ptr> Self;

	Iterator():_pNode(NULL) { }
	Iterator(Node *Root):_pNode(Root) { }
	Iterator(const Self & it):_pNode(it._pNode){ }

	Ref operator*()
	{
		return _pNode->_key;
	}
	Ptr operator->()
	{
		   return &(operator*() );
	}

	Self& operator++()
	{
		_pNode = Increment();
		return *this;
	}
	Self operator++(int)
	{
		Self temp(*this);
		_pNode = Increment();
		return temp;
	}
	Self& operator--()
	{
		_pNode = Decrement();
		return *this;
	}
	Self operator--(int)
	{
		Self temp(*this);
		_pNode = Decrement();
		return temp;
	}
	bool operator==(const Self & it)
	{
		return _pNode == it._pNode;
	}
	bool operator != (const Self & it)
	{
		return _pNode != it._pNode;
	}

private:
	Node* Increment()
	{
		Node *pCur = _pNode;
		if (pCur->_pRight) //当右子树存在,当前节点的下一个节点就是右子树的最左节点。
		{
			Node *pRight = pCur->_pRight;
			while (pRight->_pLeft)
			{
				pRight = pRight->_pLeft;
			}
			pCur = pRight;
		}
		else  //右子树不存在。
		{
			Node *pParent = pCur->_pParent;

			while (pParent->_pRight == pCur)
			{
				pCur = pParent;
				pParent = pParent->_pParent;
			}
			if ( pCur->_pRight != pParent) //特殊情况,最后一个节点还能再++,++后指向end().
			{
				pCur =  pParent;
			}
		}

		return pCur;
	}
	Node* Decrement()
	{
		Node *pCur = _pNode;

		if (RED == pCur->_color && pCur->_pParent->_pParent == pNode)//特殊情况在end()的位置
			pCur = pCur->_pRight;
		else if (pCur->_pLeft) //当左子树存在,当前节点的下一个节点就是左子树的最右节点。
		{
			Node *pLeft = pCur->_pLeft;
			while (pRight->_pLeft)
			{
				pRight = pRight->_pLeft;
			}
			pCur = pRight;
		}
		else  //左子树不存在。
		{
			Node *pParent = pCur->_pParent;

			while (pParent->_pLeft == pCur)
			{
				pCur = pParent;
				pParent = pParent->_pParent;
			}
				pCur =  pParent;  //第一个节点不能再减了,如果减就是随机值
		}

		return pCur;
	}

private:
	Node *_pNode;
};




template<class K, class V>
class RBTree
{
	typedef RBTreeNode<K, V> Node;
	typedef Iterator<K,V,K&,K*> Iterator;
public:
	RBTree(): _pHead(NULL)
	{
		_pHead = new Node(0,0);
		_pHead->_pLeft = _pHead;
		_pHead->_pRight = _pHead;

	}

	Iterator Begin()
	{
		return Iterator(_pHead->_pLeft);
	}
	Iterator End()
	{
		return  Iterator(_pHead);
	}

	Node *GetMaxNode()
	{
		Node *pCur = GetRoot();
		while (pCur->_pRight)//不需要判空  在insert中调用  不会为空
			pCur = pCur->_pRight;
		return pCur;
	}
	Node *GetMinNode()
	{
		Node *pCur = GetRoot();
		while (pCur->_pLeft)//不需要判空  在insert中调用  不会为空
			pCur = pCur->_pLeft;
		return pCur;
	}


	bool Insert(const K& key, const V& value)
	{
		Node *& pRoot= GetRoot();
		if (pRoot == NULL)
		{
			pRoot = new Node(key,value);
			pRoot->_color = BLACK;
			pRoot->_pParent = _pHead;
			return true;
		}

		Node *pCur = pRoot;
		Node *pParent = NULL;
		while (pCur)
		{
			if (key < pCur->_key)
			{
				pParent = pCur;
				pCur = pCur->_pLeft;
			}
			else if (key == pCur->_key)
			{
				return false;
			}
			else
			{
				pParent = pCur;
				pCur = pCur->_pRight;
			}
		}
		pCur = new Node(key,value);
		if (key < pParent->_key)
		{
			pParent->_pLeft = pCur;
			pCur->_pParent = pParent;
		}
		else
		{
			pParent->_pRight = pCur;
			pCur->_pParent = pParent;
		}

		//调整颜色。

		while (pCur != pRoot &&  pParent->_color == RED )  //根不需要调整,因为退了这个循环直接把根的颜色改成黑色。
		{
			Node *garndFather = pParent->_pParent;
			Node *uncle = NULL;
			if (pParent == garndFather->_pRight)
			{
				uncle = garndFather->_pLeft;
			}
			else
				uncle = garndFather->_pRight;


			if (uncle != NULL && uncle->_color == RED) //unclue存在且为红
			{
				pParent->_color = BLACK;
				uncle->_color = BLACK;
				garndFather->_color = RED;
			}
			else  //u不存在或者u为黑。
			{
				if (pParent == garndFather->_pLeft)  //父亲是爷爷的左孩子
				{
					if (pCur == pParent->_pRight)
					{
						RotateLeft(pParent);
						swap(pParent,pCur);
					}

					if (pCur == pParent->_pLeft)
					{
						RotateRight(garndFather);
						pParent->_color = BLACK;
						garndFather->_color = RED;
					}
				}
				else                        //父亲是爷爷的右孩子。
				{
					if (pCur == pParent->_pLeft)
					{
						RotateRight(pParent);
						swap(pParent,pCur);
					}

					if (pCur == pParent->_pRight)
					{
						RotateLeft(garndFather);
						pParent->_color = BLACK;
						garndFather->_color = RED;
					}
				}

			}

			pCur = garndFather;
			pParent = pCur->_pParent;
		}
		_pHead->_pLeft = GetMinNode();
		_pHead->_pRight = GetMaxNode();
		pRoot->_color = BLACK;

		return true;
	}
	void RotateLeft(Node* parent)
	{
		Node *pparent = parent->_pParent;
		Node *subR = parent->_pRight;
		Node *subRL = subR->_pLeft;

		if(pparent == _pHead)
		{
			Node *& pRoot = GetRoot();
			pRoot = subR;
		}
		else
		{
			if (parent == pparent->_pLeft)
			{
				pparent->_pLeft = subR;
			}
			else
			{
				pparent->_pRight = subR;	
			}
		}
		subR->_pParent = pparent;

		subR->_pLeft = parent;
		parent->_pParent = subR;

		parent->_pRight = subRL;
		if (subRL != NULL)
		{
			subRL->_pParent = parent;
		}
	}
	void RotateRight(Node* parent)
	{
		Node * subL = parent->_pLeft;
		Node *subLR = subL->_pRight;
		Node *pparent = parent->_pParent;

		if (pparent == _pHead)
		{
			Node *& pRoot = GetRoot();
			pRoot = subL;
		}
		else
		{
			if (parent == pparent->_pLeft)
			{
				pparent->_pLeft = subL;	
			}
			else
			{
				pparent->_pRight = subL;
			}
		}
		subL->_pParent = pparent;


		subL->_pRight = parent;
		parent->_pParent = subL;


		parent->_pLeft = subLR;
		if (subLR != NULL)
		{
			subLR->_pParent = parent;
		}
	}


	void InOrder()
	{
		Node *&pRoot = GetRoot();
		_InOrder(pRoot);
	}

	void _InOrder(Node* pRoot)
	{
		if(pRoot)
		{
			_InOrder(pRoot->_pLeft);
			cout<<pRoot->_key<<" ";
			_InOrder(pRoot->_pRight);
		}
	}
	//检查是不是红黑树
	bool CheckRBTree()
	{
		Node *&pRoot = GetRoot();
		if (pRoot == NULL)
		{
			return true;
		}
		if (pRoot->_color == RED)
		{
			return false;
		}

		//找到一条路径上黑色节点的个数
		size_t blackCount = 0;
		Node *pCur = pRoot;
		while (pCur)
		{
			if (pCur->_color == BLACK)
			{
				blackCount++;
			}
			pCur = pCur->_pLeft;
		}

		size_t k = 0;
		return _CheckRBTree(pRoot,blackCount,k);

	}

	//每一条路径上的黑色节点都要相等才是红黑树。
	bool _CheckRBTree(Node* pRoot, const size_t blackCount, size_t k) //这个地方k一定是值的,假设一条路径 黑-红-黑-黑-红-黑-黑-红-黑  这条路径黑色节点个数为6,现在回溯
	{                                                                                           //                        △,假设回溯到这个节点,如果是引用的话,k还是6,        
		if (pRoot == NULL)                                                                                     //如果你想回溯一次减一,但是回溯的节点可能不是黑色节点,所以引用不行															
		{                                                                                                 //	值的话,现在就是4了,符号要求
			return true;
		}

		//当出现两个连续的红色节点的时候,可以确定不是红黑树
		if (pRoot->_pParent && pRoot->_color == RED && pRoot->_pParent->_color == RED)
		{
			return false;
		}
		//如果是黑节点,k++
		if (pRoot->_color == BLACK)
		{
			k++;
		}
		//如果是叶子节点的话,进行判断k和count是否相等
		if (pRoot->_pLeft == NULL && pRoot->_pRight == NULL)
		{
			if (k != blackCount)
			{
				return false;
			}
		}

		return _CheckRBTree(pRoot->_pLeft,blackCount,k) && _CheckRBTree(pRoot->_pRight,blackCount,k);

	}
private:
	Node* _pHead; //红黑树加上一个头节点进行迭代器操作(头节点的左孩子指向红黑树的最小值,右孩子指向最大值,parent域指向根节点)

private:
	Node * & GetRoot()  
	{
		return _pHead->_pParent;
	}

};



#include "RBTree.h"

void Test()
{
	//int a[] = {10, 8, 7, 15, 5, 6, 11, 13, 12};
	int a[] = {15,14,13,12,11,10,9,8,7,6,5,1,3,2,1,0};
	RBTree<int, int> bt;
	for (size_t idx = 0; idx < sizeof(a)/sizeof(a[0]); ++idx)
		bt.Insert(a[idx], a[idx]);

	//bt.InOrder();
	cout << endl;

	 Iterator<int, int, int&, int *> it = bt.Begin();
	 //cout << "begin()" << *it <<endl;
	 while (it != bt.End())
	 {
		 cout << *it <<  " ";
		 it++;
	 }
	 cout <<endl;


	//cout << bt.CheckRBTree() <<endl;
}


int main()
{
	Test();

	system("pause");
	return 0;
}


红黑树和AVL树的比较
红黑树和AVL树都是高效的平衡二叉树,增删查改的时间复杂度都是O(lg(N))红黑树的不追求完全平衡,保证最长路径不超过最短路径的2倍,相对而言,降低了旋转的要求,所以性能跟AVL树差不多,但是红黑树实现更简单,所以实际运用中红黑树更多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值