本期我们来对map和set进行模拟实现,此处需要红黑树基础,没有看过红黑树的小伙伴建议先去看看红黑树,如果没了解过map和set的小伙伴也建议先去看一看,博客链接我都放在这里了
目录
我们先来看看源码

这是set.h的头文件,其中stl_tree里实现的就是红黑树,里面还有set和multiset,我们先来看set
我们正常情况会认为,map和set的实现是两棵树,一棵树kv结构,一棵是k结构,但其实不是的,map和set使用的是一棵树

这里的代码进行了一些裁减,当然裁减的是一些无关紧要的东西,我们来看重点

我们可以看到上面的rb_tree是一个kv结构

但是我们从typedef来看,无论是key还是value,他们其实都是Key,下面我们再看看map

map也是kv结构,这里的key是Key,但是value是一个pair

我们可以看到,树的成员里有一个header,是link_type,而它的本质其实就是node* ,而树的节点存的是Value
但是这个value就是真的value吗?不是的,对于map而言,这里的value是pair,对于set而言,这里的value是Key,真正决定树里面存什么的是第二个模板参数传的是什么,我们继续看

这里先是有一个基类base,里面就是红黑树的正常结构,color,parent,left和right

然后用了一个子类去继承,这里才是node

Value是value_field,rb_tree到底是k结构还是kv结构,谁也不知道,这里是搞了一个泛型
另外,这里的node也不是必须用继承,只是库里面喜欢这样写而已,一会我们实现时可以不用继承
我们可以体会到,库的设计是非常强的,只用了一棵红黑树就解决了所有问题,只取决于传的第二个模板参数,这里的value到底是key还是pair都可以由我们选择
另外这里可能会有人提出一个疑问,我们可以不传第一个模板参数Key吗?答案是不行的,因为map和set只是封装而已,核心部分的接口是调用树里面的,而树里面会调用find和erase等等,他们都是需要Key来适配的,我们再想想,map和set用的也并不是同一棵树,而是同一个类模板,同一个类模板用不同的模板参数实现出不同的类,大家要仔细想想

我们先把之前写的红黑树拿过来(红黑树源码可以去本期博客开头部分的链接里去找)
- template<class T>
- struct RBTreeNode
- {
- RBTreeNode
* _left; - RBTreeNode
* _right; - RBTreeNode
* _parent; - T _data;
- Colour _col;
- RBTreeNode(const T& data)
- :_left(nullptr)
- , _right(nullptr)
- , _parent(nullptr)
- , _data(data)
- ,_col(RED)
- {}
- };
-
- template<class K, class T>
- struct RBTree
- {
- typedef RBTreeNode
Node; - public:
- bool Insert(const T& data)
并且我们需要修改一下代码,这里我们把V改为了T,并且去掉了pair改为data
- //MySet.h
- #include"RBTree.h"
- namespace bai
- {
- template<class K>
- class set
- {
- private:
- RBTree
_t; - };
- }
- //MyMap.h
- #include"RBTree.h"
- namespace bai
- {
- template<class K,class V>
- class map
- {
- private:
- RBTree
>_t; - };
- }
然后我们写一写框架

此时的调用关系就是这样的
下面我们还要继续修改红黑树里的代码,红黑树里有很多比较大小的语句,对于set没什么,但对于map,我们传的是pair,我们希望用first来比较,所以下面我们要进行多处修改,需要使用仿函数来进行控制

这个仿函数在库里面也有,意思是把value里的key取出来
- namespace bai
- {
- template<class K>
- class set
- {
- struct SetKeyOfT
- {
- const K& operator()(const K& key)
- {
- return key;
- }
- };
- private:
- RBTree
_t; - };
- }
对于set,我们返回key即可
- namespace bai
- {
- template<class K,class V>
- class map
- {
- struct MapKeyOfT
- {
- const K& operator()(const pair
& kv) - {
- return kv.first;
- }
- };
- private:
- RBTree
, MapKeyOfT>_t; - };
- }
对于map,我们取出pair的first返回
- template<class K, class T,class KeyOfT>
- struct RBTree
- {
- typedef RBTreeNode
Node; - public:
- Node* Find(const K& key)
- {
-
- }
- bool Insert(const T& data)
- {
- if (_root == nullptr)
- {
- _root = new Node(data);
- _root->_col = BLACK;
- return true;
- }
- Node* cur = _root;
- Node* parent = nullptr;
- 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 false;
- }
- }
- cur = new Node(data);
- cur->_col = RED;
- if (kot(parent->_data) < kot(data))
- {
- parent->_right = cur;
- }
- else
- {
- parent->_left = cur;
- }
- cur->_parent = parent;
接着就是修改insert的部分代码,我们可以看到,比较大小时我们都使用的是kot,大家想想,如果不使用仿函数的话,我们该如何比较大小呢?对于set可以直接比较,但是map就不行了(其实这里map的pair也可以直接比较,库里面实现了,但是库里面的比较方法并不是我们需要的比较大小,所以这里需要我们自己写一下)

我们简单画一下调用关系就是这样 ,这里的比较并不是使用kot比较,而是kot会把T对象的值拿来进行比较,比如map,就会把pair中的first返回

我们看到库里面除了kot,还有一个compare,这个compare是用来比较T的大小的,也就是说,库用了一个仿函数来取T对象里的值,又用另一个仿函数比较T的大小
其实这个kot完全是为了map设计的,因为map的data比较不符合我们的需求,是一个pair,所以需要仿函数的帮助
大家仔细看,KeyOfT是在树这一层的,在map和set这一层是没有keyoft的
- Node* Find(const K& key)
- {
- Node* cur = _root;
- KeyOfT kot;
- while (cur)
- {
- if (kot(cur->_data) < key)
- {
- cur = cur->_right;
- }
- else if(kot(cur->_data) > key)
- {
- cur = cur->_left;
- }
- else
- {
- return cur;
- }
- }
- return nullptr;
- }
我们还要给红黑树写一个find


然后在set和map里再写一层insert,并且加上public

我们简单测试一下,没有问题
接下来我们来实现迭代器

这是stl库里set的迭代器,是rep_type

而它的本质就是rb_tree
另外我们还发现,无论是迭代器还是const迭代器,它其实都是const_iterator

我们继续追溯源头,这是stl_tree.h里的,它的迭代器是这样的

这是它的定义,这里和节点那里一样,都是写了一个基类base,然后继承

这是base的结构 ,里面有一个节点的指针node

然后operator*返回里面的value_field,这个value_field对于set而言就是key,对于map而言就是pair,当然这些其实都不是重点

重点是++和--,我们实现列表等等++和--其实没啥,但是这里是一棵树,它++怎么到下一个节点呢?

我们写代码一般是这样写的,begin是其实位置,而这棵树是二叉搜索树,所以应该是最左节点,也就是最小的值 ,我们看看库里面是不是也是这样的

库里面返回的是一个leftmost

库里面返回的是一个header->left,和我们要实现的有一些不一样,一会我们会讲解一下库里面是什么情况,下面我们来看++怎么走
这里我们需要不借助栈来完成中序的非递归

假设it在这个地方,++要找中序的下一个,也就是10,如果右树不为空,我们要访问右树的最左节点,对于所有节点,我们都可以这样做

我们再看右为空的情况, 我们需要访问它的祖先(注意,这里不一定是父亲),如果it是父亲的左,那我们访问父亲,如果it是父亲的右(也就是it在7的位置时),说明it访问完后父亲也完了,我们需要去祖先里父亲是左的那一个,也就是8的位置
总结一下:右不为空,访问右树最左节点,右为空,访问孩子是父亲左的那个祖先
- template<class T>
- struct __TreeIterator
- {
- typedef RBTreeNode
Node; - typedef __TreeIterator
Self; - Node* _node;
- __TreeIterator(Node* node)
- :_node(node)
- {}
- T& operator*()
- {
- return _node->_data;
- }
- T* operator->()
- {
- return &_node->_data;
- }
- bool operator!=(const Self& s)
- {
- return _node != s._node;
- }
- Self& operator++()
- {
-
- }
- };
我们先把框架写好
- 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;
- }
接着我们来实现++,if里边的逻辑很好理解,就是右树不为空,else里就是右树为空,需要找孩子是父亲左的那个祖先,最后返回*this即可,这里建议画图理解

接着我们还要在树里面实现一下
我们还要在set里写一下,但是此时是不能运行的,因为类模板没有被实例化时是没有生成具体代码的,里面可能有一些语法问题等等,编译器在这里是不敢去类模板里找这个iterator的,iterator是属于RBTree这个类域的,找出来还设计没有实例化的具体参数,比如这里的K,这个K具体是int还是char,是不知道的,所以编译器在这里是认不出来的,而且,编译器在类里面去取,取到的可能是一个内嵌类型(一种是typedef,一种是内部类),也可能是静态成员变量,那iterator到底是内嵌类型还是静态成员变量,编译器也不知道

所以我们需要在这里加一个typename,告诉编译器等类模板实例化了再去找

这时候我们的迭代器就能跑起来了,是不是很有趣?

我们再把map的也补上

和set不一样的是这里出错了

我们实现的operator*返回的是data,对于set而言data是key,但是对于map而言,是一个pair
pair是不支持流插入的

所以这里我们可以使用->,另外大家还记得吗?这里是两个->,编译器优化了一个,这也是我们之前讲过的知识

此时我们还可以使用auto和范围for
虽然上面我们实现了这么多,但是还是有很多大坑的

比如我们的set是允许修改的,这可出现问题了,所以,任重道远啊

还记得我们上面说了库里面的无论iterator和const_iterator都是const吗?下面我们就要按照库的方法走
另外,map不能和set用一样的方法,对于map,key不允许修改,但是value是允许的

所以map的迭代器是正常的

也就是说,对于map来说,我们要不允许first,而允许second ,而且对于first这一行要在编译时就报错

库里面是这样做的,把key设为了const,下面我们来解决这些问题


我们给迭代器和树加上两个模板参数,如果是普通迭代器,我们传T*,T&,const就传const版本

再修改修改代码
- typedef typename RBTree
::const_iterator iterator; - typedef typename RBTree
::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();
- }
接着我们在set里写出const版本,并且我们把const和普通迭代器都改为const,和库里面是一样的

我们再看看库里面的,const版本普通迭代器,和我们的还是有点不一样的

此时我们运行,这里报错了
这里的原因是

t是一个普通对象

就会调用普通的begin,返回一个普通迭代器,这里就存在一个转换

大家要知道,这两个迭代器是同一个类模板,传不同的参数, 实例化出不同的类型

首先我们要提供const版本的begin和end

我们再次看看库里面的,这是stl_set.h 里的

我们和库里面改成一样的,把我们的const版本先屏蔽掉 ,结果成功了

我们来看,如果我们不加const,t就是普通的t,只能调用普通的begin,返回的是普通的iterator,这里的iterator我们看起来是iterator,其实不是的

它是我们typedef出来的const_iterator

它的本质是这样的,也就是说我们只提供这个就行
那为什么我们还要写普通的iterator呢?

因为我们使用的时候写的是普通的,这里set的问题就暂时解决了,下面我们来看map的

这里我们模仿库里面的写法,在k前加上const

另外别忘了修改成员里的

此时就可以只修改value,而key不能修改

我们还要提供一下const版本的,普通的迭代器key不可以修改,value可以,const迭代器是都不可以修改

比如这里,使用了const迭代器就都不可以修改了

我们再把operator==实现一下,然后给这些能加const的加上const,下面我们实现一下operator--
--就是反过来,++走的是中序,--就是右子树,根,左子树的顺序
- 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;
- }
逻辑和++反一下即可,下面我们来看看库里面的结构

库和我们不同的是它增加了一个哨兵位的头节点,并且让它的左指向最左节点,右指向最右节点
这样的好处是可以快速找到最小节点和最大节点

所以库里面的是leftmost和rightmost
![]()
而它的end就直接是header,而我们的end是空,库里面的begin相对而言更高效一点,不够这是要付出代价的,比如在最左边插入一个节点,header的left就需要修改,另外,这里的header的parent是指向根的,然后root的parent指向header,删除,旋转等等都是需要维护header的

而且还要单独判断一下这个特殊情况,不然会死循环,这里cur等于parent的右,就会无限循环


我们看库里面的,这些我们了解即可
下面我们再实现一下operator[ ]

operator[ ] 的实现需要insert,我们看看库里面的insert,first是迭代器,second是bool

所以我们需要把树里面的insert改一下

修改返回值和返回类型

接着修改map和set的insert

然后我们编译,就出错了 ,set的insert是编不过的
这里的t是普通对象,调用insert,返回普通迭代器,也就是pair里的迭代器是普通迭代器
但是这里的迭代器是const_iterator

是这个样子,我们来看看库里面是怎么解决的

这是stl_set库,它用了pair的first去构造了一个

结合起来看一下

再看我们的,大家先想想,这里选中的iterator是const还是普通的 ?
是const,而后面的ret.first是普通迭代器,这里是不能用make_pair的一个原因,make_pair是自己推
这里的本质是调用了pair的构造函数

是这样子的,所以这里的本质是用普通迭代器构造const迭代器,我们以前实现的迭代器都是不支持的

库里面支持这样玩的原因是因为有这样一个函数 ,我们看最后一行,按理来说迭代器是不需要写拷贝构造的,但是这里并不是纯的拷贝构造,这里没有用self,大家仔细看self和iterator的区别
self就是这个迭代器,但iterator并不一定是

再结合这里来看
![]()
当这个类被实例化成const迭代器时,这个函数是一个构造函数,支持普通迭代器构造const迭代器

普通迭代器不受传的Ptr和Ref影响, const迭代器传const Ref和const Ptr时,普通迭代器还是value&和value*,始终是一个普通迭代器,这个函数就相当于一个普通的构造函数,它的参数是普通迭代器,用来构造const迭代器(链表那里也是这样做的)
当这个类被实例化为普通迭代器时,这个函数就是一个拷贝构造,普通迭代器构造普通迭代器,就是一个拷贝构造

所以我们也需要加上构造
我们上面那么费时费力的原因就是因为这个东西,大家要想清楚
- V& operator[](const K& key)
- {
- pair
bool> ret = insert(make_pair(key, V())); - return ret.first->second;
- }
此时我们终于可以完成operator[ ] 了,这里先调insert,然后调用make_pair,first是key,value是V的缺省值,如果没有,会先插入,如果有了就不插入,ret是pair,pair.first是一个迭代器,然后用->取second

我们简单测试一下,就和库里面差不多了
- //RBTree.h
- #include
- using namespace std;
-
- enum Colour
- {
- RED,
- BLACK
- };
- template<class T>
- struct RBTreeNode
- {
- RBTreeNode
* _left; - RBTreeNode
* _right; - RBTreeNode
* _parent; - T _data;
- Colour _col;
- RBTreeNode(const T& data)
- :_left(nullptr)
- , _right(nullptr)
- , _parent(nullptr)
- , _data(data)
- ,_col(RED)
- {}
- };
-
- template<class T,class Ptr,class Ref>
- struct __TreeIterator
- {
- typedef RBTreeNode
Node; - typedef __TreeIterator
Self; - typedef __TreeIterator
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>
- struct RBTree
- {
- typedef RBTreeNode
Node; - public:
- typedef __TreeIterator
iterator; - typedef __TreeIterator
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;
- 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
bool > Insert(const T& data) - {
- if (_root == nullptr)
- {
- _root = new Node(data);
- _root->_col = BLACK;
- return make_pair(iterator(_root),true);
- }
- Node* cur = _root;
- Node* parent = nullptr;
- 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)//parent在grandfather的左边
- {
- Node* uncle = grandfather->_right;
- if (uncle && uncle->_col == RED)//叔叔存在且为红
- {
- //变色
- uncle->_col = BLACK;
- parent->_col = BLACK;
- grandfather->_col = RED;
- //继续向上处理
- cur = grandfather;
- parent = cur->_parent;
- }
- else//叔叔不存在/存在且为黑
- {
- if (cur == parent->_left)
- {
- RotateR(grandfather);
- parent->_col = BLACK;
- grandfather->_col = RED;
- }
- else
- {
- RotateL(parent);
- RotateR(grandfather);
- cur->_col = BLACK;
- grandfather->_col = RED;
- }
- break;
- }
- }
- else//parent在grandfather的右边
- {
- Node* uncle = grandfather->_left;
- if (uncle && uncle->_col == RED)//叔叔存在且为红
- {
- uncle->_col = BLACK;
- parent->_col = BLACK;
- grandfather->_col = RED;
- cur = grandfather;
- parent = cur->_parent;
- }
- else//叔叔不存在/存在且为黑
- {
- if (cur == parent->_right)
- {
- RotateL(grandfather);
- parent->_col = BLACK;
- grandfather->_col = RED;
- }
- else
- {
- 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)//parent是根节点
- {
- _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;
- }
- }
- bool IsBalance()
- {
- return IsBalance(_root);
- }
- bool CheckColour(Node* root,int blacknum,int benchmark)//检查节点颜色
- {
- if (root == nullptr)
- {
- if (benchmark != blacknum)//黑色节点数量不对
- return false;
- return true;
- }
- if (root->_col == BLACK)//检测黑色节点数量
- {
- ++blacknum;
- }
- if (root->_col == RED && root->_parent && root->_parent->_col == RED)
- {
- cout << root->_kv.first << "连续红节点" << endl;
- return false;
- }
-
- return CheckColour(root->_left,blacknum, benchmark)
- && CheckColour(root->_right, blacknum, benchmark);
-
- }
- bool IsBalance(Node* root)
- {
- if (root == nullptr)
- return true;
- if (root->_col != BLACK)
- return false;
- int benchmark = 0;//黑色节点基准值
- Node* cur = _root;
- while (cur)
- {
- if (cur->_col==BLACK)
- ++benchmark;
- cur = cur->_left;
- }
- return CheckColour(root,0, benchmark);
- }
- private:
- Node* _root = nullptr;
- };
- //MySet.h
- #include"RBTree.h"
- namespace bai
- {
- template<class K>
- class set
- {
- struct SetKeyOfT
- {
- const K& operator()(const K& key)
- {
- return key;
- }
- };
- public:
- typedef typename RBTree
::const_iterator iterator; - typedef typename RBTree
::const_iterator const_iterator; - const_iterator begin() const
- {
- return _t.begin();
- }
- const_iterator end() const
- {
- return _t.end();
- }
- /*const_iterator begin() const
- {
- return _t.begin();
- }
- const_iterator end() const
- {
- return _t.end();
- }*/
- pair
bool > insert(const K& key) - {
- pair
::iterator, bool> ret = _t.Insert(key); - return pair
bool>(ret.first,ret.second); - }
- private:
- RBTree
_t; - };
- }
- //MyMap.h
- #include"RBTree.h"
- namespace bai
- {
- template<class K,class V>
- class map
- {
- struct MapKeyOfT
- {
- const K& operator()(const pair
& kv) - {
- return kv.first;
- }
- };
- public:
- typedef typename RBTree
const K,V>, MapKeyOfT>::iterator iterator; - typedef typename RBTree
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
bool> ret = insert(make_pair(key, V())); - return ret.first->second;
- }
- pair
bool > insert(const pair& kv) - {
- return _t.Insert(kv);
- }
- private:
- RBTree
const K,V>, MapKeyOfT>_t; - };
- }
以上即为本期全部内容,希望大家可以有所收获
如有错误,还请指正