因为关联式容器中存储的是
的键值对,因此k为key的类型,
ValueType: 如果是map,则为pair; 如果是set,则为k
KeyOfValue: 通过value来获取key的一个仿函数类
我们知道map,和set需要用红黑树来实现,但我们map的数据类型是键值对pair
template<class T>//关键之处
struct RBTreeNode {
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
Color _col;//结点颜色
T _data;
RBTreeNode(const T&data)
:_left(nullptr),
_right(nullptr),
_parent(nullptr),
_col(RED),
_data(data)
{}
};
我们这里把pair
在map中,T传pair
类型
在set中,T传K类型
我们value_type类型用模板参数T代替之后,这个时候就会衍生一个问题,我T可能为键值对类型,我键值对之间怎么比较呢?
例如:T t1与T t2两个变量,我们肯定不能直接比较,肯定要依据他们的键值大小进行比较,所以我们需要自己写一个用于比较的函数,这个时候仿函数刚好能发挥这个用处,可以作为模板参数传入自己写的比较函数
取出他们的键,让他们进行比较,这里set也这样写是为了配合map,因为两者都用的一个红黑树模板
struct SetKeyOfT {
const K& operator()(const K&key) {
return key;
}
};
struct MapKeyOfT
{
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
示例:红黑树中Find函数的实现:
Node* Find(const K& key)
{
Node* cur = _root;
KeyOfT kot;//KeyOfT为仿函数的类型
//写好仿函数后先实例化出来
while (cur)
{
if (kot(cur->_data) < key)
{
cur = cur->_right;
}
else if (kot(cur->_data) > key)
{
cur = cur->_left;
}
else
{
return cur;
}
}
return nullptr;
}
因为set插入进去后,set的值不可以被修改,为了实现这一操作我们可以在迭代器上下手
//typename是告诉编译器这里后面跟的是类型不是对象,以免编译器报错
typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;
typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;
//既然不可修改,那我就都用const类型的迭代器
在map中,我们是键不可修改,而其所对应的值可被修改,所以不能用set的那种操作,可以在传模板参数的时候动手脚,传pair的时候直接把K改为const类型
typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::iterator iterator;
typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::const_iterator const_iterator;
iterator begin()
{
Node* leftMin = _root;
while (leftMin && leftMin->_left)
{
leftMin = leftMin->_left;
}
return iterator(leftMin);
}
iterator end()
{
return iterator(nullptr);
}
const_iterator begin() const
{
Node* leftMin = _root;
while (leftMin && leftMin->_left)
{
leftMin = leftMin->_left;
}
return const_iterator(leftMin);
}
const_iterator end() const
{
return const_iterator(nullptr);
}
1.cur的右不为空访问右树的最左结点
2.cur的右为空,找到cur是parent左子树的位置,此时parent的位置就是++后的位置
Self& operator++()
{
if (_node->_right)
{
// 右树的最左节点(最小节点)
Node* subLeft = _node->_right;
while (subLeft->_left)
{
subLeft = subLeft->_left;
}
_node = subLeft;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
// 找孩子是父亲左的那个祖先节点,就是下一个要访问的节点
while (parent && cur == parent->_right)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
–就与++反着来
1.左不为空,找到左树的最右结点
2.左为空,找到cur是parent右的那个结点,此时parent的位置就是–之后的位置
Self& operator--()
{
if (_node->_left)
{
Node* subRight = _node->_left;
while (subRight->_right)
{
subRight = subRight->_right;
}
_node = subRight;
}
else
{
// 孩子是父亲的右的那个节点
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_left)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
template<class T, class Ptr, class Ref>
struct __TreeIterator
{
typedef RBTreeNode<T> Node;
typedef __TreeIterator<T, Ptr, Ref> Self;
typedef __TreeIterator<T, T*, T&> Iterator;
__TreeIterator(const Iterator& it)
:_node(it._node)
{}
Node* _node;
__TreeIterator(Node* node)
:_node(node)
{}
};
1.当我们Ptr与Ref分别实例化为T与T&的时候,__TreeIterator(const Iterator& it)就是一个拷贝构造函数,因为Iterator与Self类型相同
2.当我们Ptr与Ref分别实例化为const T与const T&的时候,__TreeIterator(const Iterator& it)是一个构造,支持普通迭代器构造const类型的迭代器因为Self为const类型,Iterator为普通类型
这里支持用普通迭代器去构造const类型的迭代器,就可以满足我们set的插入功能的实现
typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;
typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;
pair<iterator,bool>insert(const K&key){
pair<typename RBTree<K, K, SetKeyOfT>::iterator, bool> ret = _t.Insert(key);
//这里RBTree里面的iterator类型为普通迭代器类型,而我们返回值里面的pair中的iterator为const类型,
//所以要想返回必须先把RBTree中的iterator变为const类型,这个时候可以拷贝构造
//让普通迭代器变为const类型的迭代器
return pair<iterator, bool>(ret.first, ret.second);
}
这里会涉及到红黑树的一些变色问题,之前的博客有提到过【C++】红黑树插入操作实现以及验证红黑树是否正确
需要的小伙伴可以去看一下
#pragma once
#include
using namespace std;
enum Color {
RED,
BLACK
};
template<class T>//关键之处
struct RBTreeNode {
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
Color _col;//结点颜色
T _data;
RBTreeNode(const T&data)
:_left(nullptr),
_right(nullptr),
_parent(nullptr),
_col(RED),
_data(data)
{}
};
template<class T, class Ptr, class Ref>
struct __TreeIterator
{
typedef RBTreeNode<T> Node;
typedef __TreeIterator<T, Ptr, Ref> Self;
typedef __TreeIterator<T, T*, T&> Iterator;
__TreeIterator(const Iterator& it)
:_node(it._node)
{}
Node* _node;
__TreeIterator(Node* node)
:_node(node)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
bool operator!=(const Self& s) const
{
return _node != s._node;
}
bool operator==(const Self& s) const
{
return _node != s._node;
}
Self& operator--()
{
if (_node->_left)
{
Node* subRight = _node->_left;
while (subRight->_right)
{
subRight = subRight->_right;
}
_node = subRight;
}
else
{
// 孩子是父亲的右的那个节点
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_left)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
Self& operator++()
{
if (_node->_right)
{
// 右树的最左节点(最小节点)
Node* subLeft = _node->_right;
while (subLeft->_left)
{
subLeft = subLeft->_left;
}
_node = subLeft;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
// 找孩子是父亲左的那个祖先节点,就是下一个要访问的节点
while (parent && cur == parent->_right)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
};
template<class K,class T,class KeyOfT>
class RBTree {
typedef RBTreeNode<T> Node;
public:
// 同一个类模板,传的不同的参数实例化出的不同类型
typedef __TreeIterator<T, T*, T&> iterator;
typedef __TreeIterator<T, const T*, const T&> const_iterator;
iterator begin()
{
Node* leftMin = _root;
while (leftMin && leftMin->_left)
{
leftMin = leftMin->_left;
}
return iterator(leftMin);
}
iterator end()
{
return iterator(nullptr);
}
const_iterator begin() const
{
Node* leftMin = _root;
while (leftMin && leftMin->_left)
{
leftMin = leftMin->_left;
}
return const_iterator(leftMin);
}
const_iterator end() const
{
return const_iterator(nullptr);
}
Node* Find(const K& key)
{
Node* cur = _root;
KeyOfT kot;//KeyOfT为仿函数的类型
//写好仿函数后先实例化出来
while (cur)
{
if (kot(cur->_data) < key)
{
cur = cur->_right;
}
else if (kot(cur->_data) > key)
{
cur = cur->_left;
}
else
{
return cur;
}
}
return nullptr;
}
pair<iterator, bool> Insert(const T& data)
{
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK;
return make_pair(iterator(_root), true);
}
Node* parent = nullptr;
Node* cur = _root;
KeyOfT kot;
while (cur)
{
if (kot(cur->_data) < kot(data))
{
parent = cur;
cur = cur->_right;
}
else if (kot(cur->_data) > kot(data))
{
parent = cur;
cur = cur->_left;
}
else
{
return make_pair(iterator(cur), false);
}
}
cur = new Node(data);
cur->_col = RED;
Node* newnode = cur;
if (kot(parent->_data) < kot(data))
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
cur->_parent = parent;
while (parent && parent->_col == RED)
{
Node* grandfather = parent->_parent;
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
// u存在且为红
if (uncle && uncle->_col == RED)
{
// 变色
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
// 继续向上处理
cur = grandfather;
parent = cur->_parent;
}
else // u不存在 或 存在且为黑
{
if (cur == parent->_left)
{
// g
// p
// c
RotateR(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
else
{
// g
// p
// c
RotateL(parent);
RotateR(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
else // parent == grandfather->_right
{
Node* uncle = grandfather->_left;
// u存在且为红
if (uncle && uncle->_col == RED)
{
// 变色
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
// 继续向上处理
cur = grandfather;
parent = cur->_parent;
}
else
{
if (cur == parent->_right)
{
// g
// p
// c
RotateL(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
}
else
{
// g
// p
// c
RotateR(parent);
RotateL(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
}
_root->_col = BLACK;
return make_pair(iterator(newnode), true);
}
void RotateL(Node* parent)
{
Node* cur = parent->_right;
Node* curleft = cur->_left;
parent->_right = curleft;
if (curleft)
{
curleft->_parent = parent;
}
cur->_left = parent;
Node* ppnode = parent->_parent;
parent->_parent = cur;
if (parent == _root)
{
_root = cur;
cur->_parent = nullptr;
}
else
{
if (ppnode->_left == parent)
{
ppnode->_left = cur;
}
else
{
ppnode->_right = cur;
}
cur->_parent = ppnode;
}
}
void RotateR(Node* parent)
{
Node* cur = parent->_left;
Node* curright = cur->_right;
parent->_left = curright;
if (curright)
curright->_parent = parent;
Node* ppnode = parent->_parent;
cur->_right = parent;
parent->_parent = cur;
if (ppnode == nullptr)
{
_root = cur;
cur->_parent = nullptr;
}
else
{
if (ppnode->_left == parent)
{
ppnode->_left = cur;
}
else
{
ppnode->_right = cur;
}
cur->_parent = ppnode;
}
}
private:
Node* _root = nullptr;
};
#pragma once
#include"RBTree.h"
namespace bit {
template<class K, class V>
class map
{
struct MapKeyOfT
{
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
public:
typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::iterator iterator;
typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::const_iterator const_iterator;
iterator begin()
{
return _t.begin();
}
iterator end()
{
return _t.end();
}
const_iterator begin() const
{
return _t.begin();
}
const_iterator end() const
{
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<const K, V>, MapKeyOfT> _t;
};
}
#pragma once
#include"RBTree.h"
namespace bit {
template<class K>
class set {
struct SetKeyOfT {
const K& operator()(const K&key) {
return key;
}
};
public:
typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;
typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;
const_iterator begin() const
{
return _t.begin();
}
const_iterator end() const
{
return _t.end();
}
pair<iterator,bool>insert(const K&key){
pair<typename RBTree<K, K, SetKeyOfT>::iterator, bool> ret = _t.Insert(key);
return pair<iterator, bool>(ret.first, ret.second);
}
private:
RBTree<K, K, SetKeyOfT> _t;
};
}