简介
关于map和set的介绍和红黑树,之前博客都有介绍。
- map和set:C++ STL -->set和map的使用
- 红黑树:红黑树(RB-Tree)
这篇文章要用一棵红黑树同时封装出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);

最低0.47元/天 解锁文章

1197

被折叠的 条评论
为什么被折叠?



