C++ STL->用一棵红黑树封装出map和set

简介

关于map和set的介绍和红黑树,之前博客都有介绍。

这篇文章要用一棵红黑树同时封装出set和map,主要利用泛型编程的思想来完成。
之前博客实现的红黑树是K,V模型的,而set是K模型,map是K,V模型。(K模型和KV模型,是二叉搜索树的两个主要应用的两个大模型。关于K和KV模型,在二叉搜索树的最后应用场景有介绍:二叉搜索树(BST)

要用同一棵红黑树来封装map和set,使用模板参数来确定树中存放的是K还是KV模型。
对之前的红黑树进行修改如下:
(删除了验证红黑树相关成员函数,添加了析构和查找函数)

红黑树源码

enum Color
{
   
   
	RED,
	BLACK
};
template <class T>
struct RBTreeNode
{
   
   
	RBTreeNode<T>* _left;
	RBTreeNode<T>* _right;
	RBTreeNode<T>* _parent;
	T _data;//存储元素
	Color _color; //使用枚举值定义结点的颜色

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

template <class K, class T>
class RBTree
{
   
   
public:
	typedef RBTreeNode<T> Node;
	bool insert(const T& data)
	{
   
   
		//空树直接做为根结点
		if (_root == nullptr)
		{
   
   
			_root = new Node(data);
			_root->_color = BLACK;
			return true;
		}
		//1、 确定插入的位置
		Node* cur = _root;
		Node* parent = nullptr;
		while (cur != nullptr)
		{
   
   
			if (data < cur->_data)
			{
   
   
				parent = cur;
				cur = cur->_left;
			}
			else if (data > cur->_data)
			{
   
   
				parent = cur;
				cur = cur->_right;
			}
			else
			{
   
   
				return false;//键值冗余不允许插入
			}
		}
		//2、进行链接
		cur = new Node(data);
		if (data < parent->_data)
		{
   
   
			parent->_left = cur;
		}
		else
		{
   
   
			parent->_right = cur;
		}
		cur->_parent = parent;

		//3、若插入结点的父结点是红色的,则需要对红黑树进行调整
		while (parent != nullptr && parent->_color == RED)
		{
   
   
			Node* grandfahter = parent->_parent; //parent为红色,grandfahter一定存在
			if (grandfahter->_left == parent) //parent是grandfather左孩子的情况
			{
   
   
				Node* uncle = grandfahter->_right;//uncle若存在,一定是其右孩子
				if (uncle != nullptr && uncle->_color == RED)//情况一:u存在且为红
				{
   
   
					//颜色调整
					parent->_color = BLACK;
					uncle->_color = BLACK;
					grandfahter->_color = RED;

					//继续向上调整
					cur = grandfahter;
					parent = cur->_parent;
				}
				else //情况2+3(u不存在/u存在且为黑)
				{
   
   
					//cur是parent的左
					/*    g
					*   p    u
					* c
					*/
					if (cur == parent->_left)
					{
   
   
						//右旋
						RotateR(grandfahter);
						//更新颜色
						parent->_color = BLACK;
						grandfahter->_color = RED;
					}
					else//cur是parent的右
					{
   
   
						/*    g
						*   p    u
						*     c
						*/
						//左右双旋(先以p为旋点左旋,在以g为旋点右旋)
						RotateL(parent);
						RotateR(grandfahter);
						// cur变黑,g变红
						cur->_color = BLACK;
						grandfahter->_color = RED;
					}
					break;
				}
			}
			else //parent是grandfather的右孩子
			{
   
   
				Node* uncle = grandfahter->_left; //uncle若存在一定是其左孩子
				if (uncle != nullptr && uncle->_color == RED)//u存在且为红
				{
   
   
					//颜色调整
					parent->_color = BLACK;
					uncle->_color = BLACK;
					grandfahter->_color = RED;
					//继续向上调整
					cur = grandfahter;
					parent = cur->_parent;
				}
				else//u不存在/u存在为黑
				{
   
   
					//cur是parent的右
					/*   g
					*  u   p 
					*		 c
					*/
					if (cur == parent->_right)
					{
   
   
						//左旋
						RotateL(grandfahter);
						// p变黑,g变红
						parent->_color = BLACK;
						grandfahter->_color = RED;
					}
					else
					{
   
   
						//cur是parent的左
						/*   g
						*  u   p
						*	 c
						*/
						//右左双旋(先以p为轴点右旋,再以g为轴点左旋)
						RotateR(parent);
						
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

C++下等马

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

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

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

打赏作者

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

抵扣说明:

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

余额充值