红黑树源代码
我们将由下列的KV模型红黑树来模拟封装STL库中的map和set
注意:为了实现封装map和set,我们需要对下列源码进行优化。
#pragma once
#include<iostream>
using namespace std;
//枚举类型的颜色分类
enum Colour
{
RED,
BLACK
};
//定义一个结构体结点
template<class K,class V>
struct RBTreeNode
{
RBTreeNode<K, V>* _left;
RBTreeNode<K, V>* _right;
RBTreeNode<K, V>* _parent;
pair<K, V> _kv;
Colour _col;
RBTreeNode(const pair<K, V>& kv)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _kv(kv)
, _col(RED)
{}
};
//红黑树类
template<class K, class V>
class RBTree
{
typedef RBTreeNode<K, V> Node;
public:
//中序遍历副函数
void Inorder()
{
_Inorder(_root);
}
//中序遍历主函数
void _Inorder(Node* root)
{
if (root == nullptr)
return;
_Inorder(root->_left);
cout << root->_kv.first << " ";
_Inorder(root->_right);
}
//插入函数
bool insert(const pair<K, V>& kv)
{
//按照二叉树搜索树插入
if (_root == nullptr)//根结点为空时new一个最初的根结点
{
_root = new Node(kv);
_root->_col = BLACK;//根结点一定为黑
return true;
}
Node* parent = nullptr;//这个为当前指针cur的父结点指针
Node* cur = _root;//当前指针指向根
while (cur)//当不为空,说明存在值,那么继续搜索可插入的地方
{
if (cur->_kv.first < kv.first)//key大于结点值,往右走
{
parent = cur;
cur = cur->_right;
}
else if (cur->_kv.first > kv.first)//key小于结点值,往左走
{
parent = cur;
cur = cur->_left;
}
else//相等,那么不插入,插入失败
{
return false;
}
}
cur = new Node(kv);//新增结点
cur->_col = RED;//默认红色
//插入
if (parent->_kv.first > kv.first)
{
parent->_left = cur;
cur->_parent = parent;
}
else
{
parent->_right = cur;
cur->_parent = parent;
}
//开始判断颜色
while (parent != nullptr && parent->_col == RED)
{
Node* grandfather = parent->_parent;
//如果父亲为红,那么违反红红规则,开始判断情况
if (parent != nullptr && parent == grandfather->_left)
{
Node* uncle = grandfather->_right;//记录叔叔结点
if (uncle != nullptr && uncle->_col == RED)//如果叔叔存在或者为红色,情况一
{
//变色
parent->_col = uncle->_col = BLACK;//父亲和叔叔都变黑
grandfather->_col = RED;//爷爷变红
//将cur和parent往上移继续判断
cur = grandfather;
parent = cur->_parent;
}
else//叔叔不存在或者存在且为黑色,情况二和情况三结合
{
if (cur == parent->_left)
{
RotateR(grandfather);//右旋
parent->_col = BLACK;
grandfather->_col = RED;
}
else
{
RotateLR(grandfather); //左右双旋
grandfather->_col = RED;
cur->_col = BLACK;
}
break;//根结点为黑,不需要往上了
}
}
else//parent在grandfather的右边
{
Node* uncle = grandfather->_left;//记录叔叔结点
if (uncle != nullptr && uncle->_col == RED)//如果叔叔存在或者为红色,情况一
{
parent->_col = uncle->_col = BLACK;//父亲和叔叔都变黑
grandfather->_col = RED;//爷爷变红
//向上调整
cur = grandfather;
parent = grandfather->_parent;
}
else//叔叔不存在或者存在且为黑色,情况二和情况三结合
{
if (cur == parent->_left)//如果插入在parent的左边
{
RotateRL(grandfather);//右左双旋
cur->_col = BLACK;
grandfather->_col = RED;
}
else//如果插入在parent的右边
{
RotateL(grandfather);//左旋
grandfather->_col = RED;
parent->_col = BLACK;
}
break;//根结点为黑,不需要往上了
}
}
}
_root->_col = BLACK;//往上移动后无论cur是否为根结点,统一为改黑
return true;//插入成功
}
//左单旋
void RotateL(Node* parent)
{
//定义新指针,方便操作
Node* subR = parent->_right;
Node* subRL = subR->_left;
Node* pp = parent->_parent;//方便更改_root的操作
parent->_right = subRL;//让parent结点链接subRL
subR->_left = parent;//让subR的左子树链接parent
parent->_parent = subR;//由于parent的_parent由nullptr变成了subR,所以也需要重新链接
if (subRL)
//判断subRL是否为空,如果为空的话就不需要对subRL进行操作了,不然会出现对空指针进行解引用的问题
{
subRL->_parent = parent;//不为空,那么让subRL链接parent
}
if (pp == nullptr)//如果parent是整棵树的根结点
{
_root = subR;//subR变为根结点
subR->_parent = nullptr;//subR的_parent为空
}
else//如果parent不是整棵树的根结点,那么将新的parent重新链接上一个结点
{
if (pp->_left = parent)//如果parent是上一个结点的左子树,那么新的parent也是
{
pp->_left = subR;
}
else//如果parent是上一个结点的右子树,那么新的parent也是
{
pp->_right = subR;
}
subR->_parent = pp;//更新subR的父结点
}
//parent->_bf = subR->_bf = 0;//由于旋转后,整棵树的高度变回插入前的,那么此时parent和subR(cur)的因子都变回0
}
//右单旋
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subRR = subL->_right;
Node* pp = parent->_parent;
//建立subL和parent之间的关系
parent->_left = subRR;
subL->_right = parent;
//建立parent和subRR之间的关系
parent->_parent = subL;
if (subRR != nullptr)
{
subRR->_parent = parent;
}
//建立PP和subL之间的关系
if (pp == nullptr)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (pp->_left == parent)
{
pp->_left = subL;
}
else
{
pp->_right = parent;
}
subL->_parent = pp;
}
//更新平衡因子
//subL->_bf = parent->_bf = 0;
}
//左右双旋
void RotateLR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
//int bf = subLR->_bf;
RotateL(parent->_left);
RotateR(parent);
//if (bf == 0)
//{
// //subLR自己就是新增
// subLR->_bf = 0;
// subL->_bf = 0;
// parent->_bf = 0;
//}
//else if (bf == -1)
//{
// //subLR的左子树新增
// subLR->_bf = 0;
// subL->_bf = 0;
// parent->_bf = 1;
//}
//else if (bf == 1)
//{
// //subLR的右子树新增
// subLR->_bf = 0;
// subL->_bf = -1;
// parent->_bf = 0;
//}
//else
//{
// assert(false);
//}
}
//右左双旋
void RotateRL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
//int bf = subRL->_bf;
RotateR(parent->_right);
RotateL(parent);
//if (bf == 0)
//{
// //subRL自己就是新增
// parent->_bf = subR->_bf = subRL->_bf = 0;
//}
//else if (bf == -1)
//{
// //subRL的左子树新增
// parent->_bf = 0;
// subRL->_bf = 0;
// subR->_bf = 1;
//}
//else if (bf == 1)
//{
// //subRL的右子树新增
// parent->_bf = -1;
// subRL->_bf = 0;
// subR->_bf = 0;
//}
//else
//{
// assert(false);
//}
}
// blacknum是根结点到当前结点的黑色结点数量
bool check(Node* root,int blacknum,int count)
{
if (root == nullptr)
{
if(count != blacknum)
{
cout << "黑色结点数量不等" << endl;
return false;
}
return true;
}
if (root->_col == RED && root->_parent->_col == RED)
{
cout << "有连续的红色结点" << endl;
return false;
}
if (root->_col == BLACK)
{
++blacknum;
}
return check(root->_left,blacknum,count) && check(root->_right,blacknum,count);
}
bool isbalance()
{
if (_root == nullptr)
{
return true;
}
if (_root->_col == RED)
{
return false;
}
//找最左路径作为黑色结点数目的参考值
Node* cur = _root;
int count = 0;
while (cur)
{
if (cur->_col == BLACK)
++count;
cur = cur->_left;
}
int blacknum = 0;
return check(_root,blacknum,count);
}
private:
Node* _root = nullptr;
};
红黑树的模板
首先,我们要知道,set是K模型,map是KV模型,那么如何用一颗红黑树同时封装出两种模型呢?这时候就应该想到模板了。
我们需要对红黑树类模板进行修改:
这是原始代码:
template<class K, class V>
class RBTree
这是修改后的代码:
template<class K, class T, class KeyofT>
class RBTree
可以看到,这将V变为T,然后多出了KeyofT,这是什么意思呢?
class V ---> class T
set是K模型,map是KV模型
在set容器中,T是对应着key:
template<class K>
class set
{
public:
//...
private:
RBTree<K, K, SetKeyofT> _t;
};
在map容器中,T是对应着key和value组成的键值对:
template<class K,class V>
class map
{
public:
//...
private:
RBTree<K, pair<K, V>, MapKeyofT> _t;
};
这时候会有一个疑问,能不能把第一个参数:class K 给去掉,因为在set中,K已经重复了;在map中,貌似键值对里也已经包含着key和value了?
可以肯定地说:不能去掉!在set中,确实可以省略不要;但是在map中,有些容器接口需要给出key的类型,那么在键值对中,我们只能取到key的值。所以在map中不能删去。
所以,我们更改了红黑树源码中的结点类实现
结点类实现
//定义一个结构体结点
template<class T>
struct RBTreeNode
{
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
T _data;
Colour _col;
RBTreeNode(const T& data)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _data(data)
, _col(RED)
{}
};
可以看到,这里的 T _data就是新增的,T对应set中的key,map中的键值对。
map、set中的仿函数
class KeyofT
在上述set和map容器的私有成员中,分别有着:
在map和set分别传入底层红黑树时,T传入的可能是key,也可能是key和value的键值对,如果是键值对,那么就需要将键值对的key提取出来再进行比较,那么此时就需要用到仿函数。
map容器:
template<class K,class V>
class map
{
public:
struct MapKeyofT
{
const K& operator()(const pair<K,V>& kv)
{
return kv.first;
}
};
private:
RBTree<K, pair<K, V>, MapKeyofT> _t;
};
set容器:
template<class K>
class set
{
public:
struct SetKeyofT
{
const K& operator()(const K& key)
{
return key;
}
};
private:
RBTree<K, K, SetKeyofT> _t;
};
可以看到,我们在这个仿函数中重载了operator(), 这个operator()在map中用来提取kv.first,也就是key值,为了能统一map和set,我们在set也重载了operator()。
所以set传入底层红黑树就是set的仿函数,map传入底层红黑树就是map的仿函数。
那么应该怎么用呢?
例如在insert插入函数中,我们需要获取结点内的key值进行比较大小
新定义了一个kot:
KeyofT kot;
这是其中一小段代码:
if (kot(cur->_data) < kot(data))//key大于结点值,往右走
这里可以调用仿函数,如果_data/data类型是key,那么在仿函数中直接就返回key;如果类型是键值对,那么就返回kv.first
迭代器类实现
在迭代器中,解引用操作就是获取结点的数据的引用,->操作就是获取结点数据的地址即可。
真正有难度的是++和--:
在树中的++和--是按照中序遍历的方式进行的,也就是让指针按照 左子树-根-右子树 的顺序移动。
在++操作中:
如果右子树不为空,那么进入右子树然后寻找最左结点。
如果右子树为空,那么往上返回父亲节点,然后找到当前结点不是父亲结点的右子树的父亲节点。
在--操作中:
如果左子树不为空,那么进入右子树然后寻找最右结点。
如果左子树为空,那么往上返回父亲节点,然后找到当前结点不是父亲结点的左子树的父亲节点。
//迭代器类
template<class T, class Ref,class Ptr>
struct _TreeIterator
{
typedef RBTreeNode<T> Node;//结点类型
typedef _TreeIterator<T, Ref, Ptr> Self;
Node* _node;//结点指针
//构造函数
_TreeIterator(Node* node)
:_node(node)
{}
Ref operator*()
{
return _node->_data;//返回结点数据的引用
}
Ptr operator->()
{
return &_node->_data;//返回结点数据的地址
}
Self operator++()
{
if (_node->_right)//如果右子树存在
{
Node* cur = _node->_right;//则进入右子树
while (cur->_left)//找到右子树的最左结点
{
cur = cur->_left;
}
_node = cur;//更新当前结点
}
else//如果右子树不存在
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right)//父亲结点存在且当前结点为父亲结点的右子树
{
//不断往上循环
cur = parent;
parent = parent->_parent;
}
//当前结点不是父亲的右子树时,更新指针指向当前结点的父亲结点
_node = parent;
}
return *this;
}
Self operator--()
{
if (_node->_left) //结点的左子树不为空
{
//寻找该结点左子树当中的最右结点
Node* right = _node->_left;
while (right->_right)
{
right = right->_right;
}
_node = right; //--后变为该结点
}
else //结点的左子树为空
{
//寻找孩子不在父亲左的祖先
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_left)
{
cur = parent;
parent = parent->_parent;
}
_node = parent; //--后变为该结点
}
return *this;
}
bool operator!=(const Self& s) const
{
return _node != s._node; //判断两个正向迭代器所封装的结点是否是同一个
}
bool operator==(const Self& s) const
{
return _node == s._node; //判断两个正向迭代器所封装的结点是否是同一个
}
};
迭代器函数实现
在树中的begin()和end()也有着不同的规则:
begin()获取的是树的最左结点。
end()获取的是树的最右结点的后一个结点,也就是空结点。
//迭代器函数
typedef _TreeIterator<T,T&,T*> iterator;
typedef _TreeIterator<T, const T&, const T*> const_iterator;
iterator begin()
{
Node* cur = _root;
while (cur && cur->_left)//寻找最左结点
{
cur = cur->_left;
}
return iterator(cur);
}
iterator end()
{
return iterator(nullptr);
}
const_iterator begin() const
{
Node* cur = _root;
while (cur && cur->_left)//寻找最左结点
{
cur = cur->_left;
}
return iterator(cur);
}
const_iterator end() const
{
return iterator(nullptr);
}
优化后的红黑树源码
#pragma once
#include<iostream>
using namespace std;
//枚举类型的颜色分类
enum Colour
{
RED,
BLACK
};
//定义一个结构体结点
template<class T>
struct RBTreeNode
{
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
T _data;
Colour _col;
RBTreeNode(const T& data)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _data(data)
, _col(RED)
{}
};
//迭代器类
template<class T, class Ref,class Ptr>
struct _TreeIterator
{
typedef RBTreeNode<T> Node;
typedef _TreeIterator<T, Ref, Ptr> Self;
Node* _node;
_TreeIterator(Node* node)
:_node(node)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
Self operator++()
{
if (_node->_right)
{
Node* cur = _node->_right;
while (cur->_left)
{
cur = cur->_left;
}
_node = cur;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
Self operator--()
{
if (_node->_left) //结点的左子树不为空
{
//寻找该结点左子树当中的最右结点
Node* right = _node->_left;
while (right->_right)
{
right = right->_right;
}
_node = right; //--后变为该结点
}
else //结点的左子树为空
{
//寻找孩子不在父亲左的祖先
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_left)
{
cur = parent;
parent = parent->_parent;
}
_node = parent; //--后变为该结点
}
return *this;
}
bool operator!=(const Self& s) const
{
return _node != s._node; //判断两个正向迭代器所封装的结点是否是同一个
}
};
//红黑树类
template<class K, class T, class KeyofT>
class RBTree
{
typedef RBTreeNode<T> Node;
public:
//中序遍历副函数
void Inorder()
{
_Inorder(_root);
}
//中序遍历主函数
void _Inorder(Node* root)
{
if (root == nullptr)
return;
_Inorder(root->_left);
cout << root->_kv.first << " ";
_Inorder(root->_right);
}
//迭代器函数
typedef _TreeIterator<T,T&,T*> iterator;
typedef _TreeIterator<T, const T&, const T*> const_iterator;
iterator begin()
{
Node* cur = _root;
while (cur && cur->_left)
{
cur = cur->_left;
}
return iterator(cur);
}
iterator end()
{
return iterator(nullptr);
}
const_iterator begin() const
{
Node* cur = _root;
while (cur && cur->_left)
{
cur = cur->_left;
}
return iterator(cur);
}
const_iterator end() const
{
return iterator(nullptr);
}
//插入函数
pair<iterator,bool> insert(const T& data)
{
//按照二叉树搜索树插入
if (_root == nullptr)//根结点为空时new一个最初的根结点
{
_root = new Node(data);
_root->_col = BLACK;//根结点一定为黑
return make_pair(iterator(_root),true);
}
Node* parent = nullptr;//这个为当前指针cur的父结点指针
Node* cur = _root;//当前指针指向根
KeyofT kot;
while (cur)//当不为空,说明存在值,那么继续搜索可插入的地方
{
if (kot(cur->_data) < kot(data))//key大于结点值,往右走
{
parent = cur;
cur = cur->_right;
}
else if (kot(cur->_data) > kot(data))//key小于结点值,往左走
{
parent = cur;
cur = cur->_left;
}
else//相等,那么不插入,插入失败
{
return make_pair(iterator(cur), false);
}
}
cur = new Node(data);//新增结点
Node* newnode = cur;
cur->_col = RED;//默认红色
//插入
if (kot(parent->_data) > kot(data))
{
parent->_left = cur;
cur->_parent = parent;
}
else
{
parent->_right = cur;
cur->_parent = parent;
}
//开始判断颜色
while (parent != nullptr && parent->_col == RED)
{
Node* grandfather = parent->_parent;
//如果父亲为红,那么违反红红规则,开始判断情况
if (parent != nullptr && parent == grandfather->_left)
{
Node* uncle = grandfather->_right;//记录叔叔结点
if (uncle != nullptr && uncle->_col == RED)//如果叔叔存在或者为红色,情况一
{
//变色
parent->_col = uncle->_col = BLACK;//父亲和叔叔都变黑
grandfather->_col = RED;//爷爷变红
//将cur和parent往上移继续判断
cur = grandfather;
parent = cur->_parent;
}
else//叔叔不存在或者存在且为黑色,情况二和情况三结合
{
if (cur == parent->_left)
{
RotateR(grandfather);//右旋
parent->_col = BLACK;
grandfather->_col = RED;
}
else
{
RotateLR(grandfather); //左右双旋
grandfather->_col = RED;
cur->_col = BLACK;
}
break;//根结点为黑,不需要往上了
}
}
else//parent在grandfather的右边
{
Node* uncle = grandfather->_left;//记录叔叔结点
if (uncle != nullptr && uncle->_col == RED)//如果叔叔存在或者为红色,情况一
{
parent->_col = uncle->_col = BLACK;//父亲和叔叔都变黑
grandfather->_col = RED;//爷爷变红
//向上调整
cur = grandfather;
parent = grandfather->_parent;
}
else//叔叔不存在或者存在且为黑色,情况二和情况三结合
{
if (cur == parent->_left)//如果插入在parent的左边
{
RotateRL(grandfather);//右左双旋
cur->_col = BLACK;
grandfather->_col = RED;
}
else//如果插入在parent的右边
{
RotateL(grandfather);//左旋
grandfather->_col = RED;
parent->_col = BLACK;
}
break;//根结点为黑,不需要往上了
}
}
}
_root->_col = BLACK;//往上移动后无论cur是否为根结点,统一为改黑
return make_pair(iterator(newnode), true);//插入成功
}
//左单旋
void RotateL(Node* parent)
{
//定义新指针,方便操作
Node* subR = parent->_right;
Node* subRL = subR->_left;
Node* pp = parent->_parent;//方便更改_root的操作
parent->_right = subRL;//让parent结点链接subRL
subR->_left = parent;//让subR的左子树链接parent
parent->_parent = subR;//由于parent的_parent由nullptr变成了subR,所以也需要重新链接
if (subRL)
//判断subRL是否为空,如果为空的话就不需要对subRL进行操作了,不然会出现对空指针进行解引用的问题
{
subRL->_parent = parent;//不为空,那么让subRL链接parent
}
if (pp == nullptr)//如果parent是整棵树的根结点
{
_root = subR;//subR变为根结点
subR->_parent = nullptr;//subR的_parent为空
}
else//如果parent不是整棵树的根结点,那么将新的parent重新链接上一个结点
{
if (pp->_left = parent)//如果parent是上一个结点的左子树,那么新的parent也是
{
pp->_left = subR;
}
else//如果parent是上一个结点的右子树,那么新的parent也是
{
pp->_right = subR;
}
subR->_parent = pp;//更新subR的父结点
}
//parent->_bf = subR->_bf = 0;//由于旋转后,整棵树的高度变回插入前的,那么此时parent和subR(cur)的因子都变回0
}
//右单旋
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subRR = subL->_right;
Node* pp = parent->_parent;
//建立subL和parent之间的关系
parent->_left = subRR;
subL->_right = parent;
//建立parent和subRR之间的关系
parent->_parent = subL;
if (subRR != nullptr)
{
subRR->_parent = parent;
}
//建立PP和subL之间的关系
if (pp == nullptr)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (pp->_left == parent)
{
pp->_left = subL;
}
else
{
pp->_right = parent;
}
subL->_parent = pp;
}
//更新平衡因子
//subL->_bf = parent->_bf = 0;
}
//左右双旋
void RotateLR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
//int bf = subLR->_bf;
RotateL(parent->_left);
RotateR(parent);
//if (bf == 0)
//{
// //subLR自己就是新增
// subLR->_bf = 0;
// subL->_bf = 0;
// parent->_bf = 0;
//}
//else if (bf == -1)
//{
// //subLR的左子树新增
// subLR->_bf = 0;
// subL->_bf = 0;
// parent->_bf = 1;
//}
//else if (bf == 1)
//{
// //subLR的右子树新增
// subLR->_bf = 0;
// subL->_bf = -1;
// parent->_bf = 0;
//}
//else
//{
// assert(false);
//}
}
//右左双旋
void RotateRL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
//int bf = subRL->_bf;
RotateR(parent->_right);
RotateL(parent);
//if (bf == 0)
//{
// //subRL自己就是新增
// parent->_bf = subR->_bf = subRL->_bf = 0;
//}
//else if (bf == -1)
//{
// //subRL的左子树新增
// parent->_bf = 0;
// subRL->_bf = 0;
// subR->_bf = 1;
//}
//else if (bf == 1)
//{
// //subRL的右子树新增
// parent->_bf = -1;
// subRL->_bf = 0;
// subR->_bf = 0;
//}
//else
//{
// assert(false);
//}
}
// blacknum是根结点到当前结点的黑色结点数量
bool check(Node* root, int blacknum, int count)
{
if (root == nullptr)
{
if (count != blacknum)
{
cout << "黑色结点数量不等" << endl;
return false;
}
return true;
}
if (root->_col == RED && root->_parent->_col == RED)
{
cout << "有连续的红色结点" << endl;
return false;
}
if (root->_col == BLACK)
{
++blacknum;
}
return check(root->_left, blacknum, count) && check(root->_right, blacknum, count);
}
bool isbalance()
{
if (_root == nullptr)
{
return true;
}
if (_root->_col == RED)
{
return false;
}
//找最左路径作为黑色结点数目的参考值
Node* cur = _root;
int count = 0;
while (cur)
{
if (cur->_col == BLACK)
++count;
cur = cur->_left;
}
int blacknum = 0;
return check(_root, blacknum, count);
}
private:
Node* _root = nullptr;
};
用红黑树封装set的容器
#pragma once
#include"RBTree.h"
namespace bear
{
template<class K>
class set
{
public:
//仿函数
struct SetKeyofT
{
const K& operator()(const K& key)
{
return key;
}
};
//红黑树最好不要修改,将普通迭代器和const迭代器都用const迭代器重命名
typedef typename RBTree<K, K, SetKeyofT>::const_iterator iterator;
typedef typename RBTree<K, K, SetKeyofT>::const_iterator const_iterator;
iterator begin() const
{
return _t.begin();
}
iterator end() const
{
return _t.end();
}
pair<iterator, bool> Insert(const K& key)
{
return _t.insert(key);
}
private:
RBTree<K, K, SetKeyofT> _t;
};
}
用红黑树封装map的容器
在map中,还需要对[]运算符进行重载。
#pragma once
#include"RBTree.h"
namespace bear
{
template<class K,class V>
class map
{
public:
struct MapKeyofT
{
const K& operator()(const pair<K,V>& kv)
{
return kv.first;
}
};
typedef typename RBTree<K, pair<K, V>, MapKeyofT>::iterator iterator;
iterator begin()
{
return _t.begin();
}
iterator end()
{
return _t.end();
}
V& operator[](const K& key)
{
pair<iterator, bool> ret = insert(make_pair(key, V()));
return ret.first->second;
}
pair<iterator, bool> Insert(const pair<K, V>& kv)
{
return _t.insert(kv);
}
private:
RBTree<K, pair<K, V>, MapKeyofT> _t;
};
}