目录
前言
今天继续来学习【C++】封装红黑树实现map和set,本文是基于红黑树实现的,【C++】红黑树详情请点击查看
一、map/set源码及框架分析
- map和set是通过红黑树封装实现的,我们首先学习一下STL库中是如何通过封装红黑树实现的map/set,截取核心部分做讲解(stl_map.h/stl_set.h/stl_tree.h)
cpp
template <class Key, class T, class Compare = less<Key>, class Alloc = alloc>
class map {
public:
// typedefs:
typedef Key key_type;
typedef pair<const Key, T> value_type;
private:
typedef rb_tree<key_type, value_type,
select1st<value_type>, key_compare, Alloc> rep_type;
rep_type t; // red-black tree representing map
};
template <class Key, class Compare = less<Key>, class Alloc = alloc>
class set {
public:
// typedefs:
typedef Key key_type;
typedef Key value_type;
private:
typedef rb_tree<key_type, value_type,
identity<value_type>, key_compare, Alloc> rep_type;
rep_type t; // red-black tree representing set
};
- 从源码中我们可以看到,map和set使用是一个红黑树,map中的value是pair结构(存储的key,value),set的value是key,那为什么还要key结构呢?

- 分析map和set的整体,rb_tree是实现key的搜索场景,还是key/value的搜索场景不是直接写死的,而是由第二个模板参数Value决定_rb_tree_node中存储的数据类型
- set实例化rb_tree时第二个模板参数给的是key,map实例化rb_tree时第二个模板参数给的是pair<const key, T>,这样⼀颗红黑树既可以实现key搜索场景的set,也可以实现key/value搜索场景的map


- rb_tree第二个模板参数Value已经控制了红黑树结点中存储的数据类型,为什么还要传第一个模板参数Key呢?尤其是set,两个模板参数是⼀样的。要注意的是对于map和set,find/erase时的函数参数都是Key,所以第一个模板参数是传给find/erase等函数做形参的类型的。对于set而言两个参数是一样的,但是对于map而言就完全不⼀样了,map insert的是pair对象,但是find和ease的是Key对象
二、红黑树框架修改
- 前面我们实现了红黑树,通过上面源码的分析,我们对红黑树代码,进行修改,红黑树节点实现泛型编程
- 节点我们传入T类型,T根据传入的数据类型来确定(set是key,map是pair<K, V>)
cpp
template<class T>
struct RBTreeNode
{
T _data;
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
Colour _col;
RBTreeNode(const T& data)
:_data(data)
, _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
{}
};
cpp
template<class K, class T>
class RBTree
{
typedef RBTreeNode<T> Node;
private:
Node* _root = nullptr;
};
三、map/set的封装实现
- 首先根据源码我们将map/set结构搭建
cpp
//set
namespace gy
{
template<class K>
class set
{
public:
bool insert(const K& key)
{
return _t.Insert(key);
}
private:
RBTree<K, K> _t;
};
}
//map
namespace gy
{
template<class K, class V>
class map
{
public:
bool insert(const pair<K, V>& kv)
{
return _t.Insert(kv);
}
private:
RBTree<K, pair<K, V>> _t;
};
}
insert
- 下面是原来我们实现的红黑树插入代码,传入的是pair类型数据
cpp
bool Insert(const pair<K, V>& kv)
{
if (_root == nullptr)
{
_root = new Node(kv);
_root->_col = BLACK;
return true;
}
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
if (cur->_kv.first < kv.first)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_kv.first > kv.first)
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}
cur = new Node(kv);
cur->_col = RED;
if (parent->_kv.first < kv.first)
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
cur->_parent = parent;
while (parent && parent->_col == RED)
{
Node* grandparent = parent->_parent;
if (parent == grandparent->_left)
{
Node* uncle = grandparent->_right;
if (uncle && uncle->_col == RED)
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandparent->_col = RED;
//继续往上处理
cur = grandparent;
parent = cur->_parent;
}
else
{
//uncle不存在,或者存在且为黑色
// g
//p u
//c
//单旋
if (cur == parent->_left)
{
RotateR(grandparent);
//将parent->Col :BLACK
//将grandparent->Col:RED
parent->_col = BLACK;
grandparent->_col = RED;
}
else
{
// g
//p u
// c
//双旋
RotateL(parent);
RotateR(grandparent);
cur->_col = BLACK;
grandparent->_col = RED;
}
break;
}
}
else
{
Node* uncle = grandparent->_left;
if (uncle && uncle->_col == RED)
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandparent->_col = RED;
//继续往上处理
cur = grandparent;
parent = cur->_parent;
}
else
{
//存在且为黑或者不存在
// g
//u p
// c
//单旋
if (cur == parent->_right)
{
RotateL(grandparent);
//将parent->Col :BLACK
//将grandparent->Col:RED
parent->_col = BLACK;
grandparent->_col = RED;
}
else
{
// g
//u p
// c
//双旋
RotateR(parent);
RotateL(grandparent);
cur->_col = BLACK;
grandparent->_col = RED;
}
break;
}
}
}
_root->_col = BLACK;
return true;
}
- 现在我们将其修改为泛型编程逻辑,data不确定类型(set是key,map是pair),那么里面的比较逻辑我们就不能只是单纯的使用cur->_data < data来比较了,set的key支持比较大小,但是pair支持吗?
- 查看文档我们发现pair支持比较大小,但是其比较逻辑是first小就小,first等于再去比较second,second小就小,但是我们需要的比较逻辑是比较first
>
- 我们在map和set层分别实现一个MapKeyOfT和SetKeyOfT的仿函数传给RBTree的KeyOfT,然后RBTree中通过KeyOfT仿函数取出T类型对象中的key,再进行比较
cpp
//myset.h
namespace gy
{
template<class K>
class set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
bool insert(const K& key)
{
return _t.Insert(key);
}
private:
RBTree<K, K, SetKeyOfT> _t;
};
}
//mymap.h
namespace gy
{
template<class K, class V>
class map
{
struct MapKeyOfT
{
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
public:
bool insert(const pair<K, V>& key)
{
return _t.Insert(key);
}
private:
RBTree<K, pair<K, V>, MapKeyOfT> _t;
};
}
cpp
//RBTree.h
template<class K, class T, class KeyOfT>
class RBTree
{
typedef RBTreeNode<T> Node;
private:
Node* _root = nullptr;
};
cpp
//泛型编程Insert代码
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;
while (parent && parent->_col == RED)
{
Node* grandparent = parent->_parent;
if (parent == grandparent->_left)
{
Node* uncle = grandparent->_right;
if (uncle && uncle->_col == RED)
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandparent->_col = RED;
//继续往上处理
cur = grandparent;
parent = cur->_parent;
}
else
{
//uncle不存在,或者存在且为黑色
// g
//p u
//c
//单旋
if (cur == parent->_left)
{
RotateR(grandparent);
//将parent->Col :BLACK
//将grandparent->Col:RED
parent->_col = BLACK;
grandparent->_col = RED;
}
else
{
// g
//p u
// c
//双旋
RotateL(parent);
RotateR(grandparent);
cur->_col = BLACK;
grandparent->_col = RED;
}
break;
}
}
else
{
Node* uncle = grandparent->_left;
if (uncle && uncle->_col == RED)
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandparent->_col = RED;
//继续往上处理
cur = grandparent;
parent = cur->_parent;
}
else
{
//存在且为黑或者不存在
// g
//u p
// c
//单旋
if (cur == parent->_right)
{
RotateL(grandparent);
//将parent->Col :BLACK
//将grandparent->Col:RED
parent->_col = BLACK;
grandparent->_col = RED;
}
else
{
// g
//u p
// c
//双旋
RotateR(parent);
RotateL(grandparent);
cur->_col = BLACK;
grandparent->_col = RED;
}
break;
}
}
}
_root->_col = BLACK;
return true;
}
find
- 同理,红黑树的查找也要使用仿函数来解决泛型编程导致底层不知道类型的问题
cpp
Node* Find(const K& key)
{
KeyOfT kot;
Node* cur = _root;
while (cur)
{
if (kot(cur->_data) < key)
{
cur = cur->_right;
}
else if (kot(cur->_data) > key)
{
cur = cur->_left;
}
else
{
return cur;
}
}
return nullptr;
}
iterator
iterator源码逻辑:
cpp
//iterator++
void increment()
{
if (node->right != 0) {
node = node->right;
while (node->left != 0)
node = node->left;
}
else {
base_ptr y = node->parent;
while (node == y->right) {
node = y;
y = y->parent;
}
if (node->right != y)
node = y;
}
}
//iterator--
void decrement()
{
if (node->color == __rb_tree_red &&
node->parent->parent == node)
node = node->right;
else if (node->left != 0) {
base_ptr y = node->left;
while (y->right != 0)
y = y->right;
node = y;
}
else {
base_ptr y = node->parent;
while (node == y->left) {
node = y;
y = y->parent;
}
node = y;
}
}
iterator++
- iterator实现的大框架跟list的iterator思路是一致的,用一个类型封装结点的指针,再通过重载运算符实现,迭代器像指针一样访问的行为
- map和set的迭代器走的是中序遍历,左子树->根结点->右子树,那么begin()会返回中序第一个结点的iterator
- 迭代器++时,如果it指向的结点的右子树不为空 ,代表当前结点已经访问完了,要访问下一个结点是右子树的中序第一个,一棵树中序第一个是最左结点,所以直接找右子树的最左结点即可

- 迭代器++时,如果it指向的结点的右子树空,代表当前结点已经访问完了且当前结点所在的子树也访问完了,要访问的下一个结点在当前结点的
祖先里面,所以要沿着当前结点到根的祖先路径向上找(下面15节点iterator++之后是18,25节点iterator++之后是30) - 当前结点是父亲的左,下一个访问的结点(iterator++)就是当前结点的父亲(如25节点);如果当前结点是父亲的右,当前结点所在的子树访问完了,当前结点所在父亲的子树也访问完了,那么下一个访问的需要继续往根的祖先中去找,直到找到孩子是父亲左的那个祖先就是中序要问题的下一个结点(15节点)

- end()如何表示呢?当it指向50时,++it,50是40的右,40是30的右,30是18的右,18到根没有父亲,没有找到孩子是父亲左的那个祖先,父亲为空了,那我们就把it中的结点指针置为nullptr,我们用nullptr去充当end。
- iterator实现的大框架跟list的iterator思路是一致的,详情搭建过程在这里不做过多赘述详情请点击查看
cpp
//RBTree.h
template<class T>
struct _TreeIterator
{
typedef RBTreeNode<T> Node;
typedef _TreeIterator<T> Self;
Node* _node;
_TreeIterator(Node* node)
:_node(node)
{ }
T& operator*()
{
return _node->_data;
}
T* operator->()
{
return &_node->_data;
}
Self& operator++()
{
if (_node->_right)
{
_node = _node->_right;
while (_node->_left)
{
_node = _node->_left;
}
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
bool operator!=(const Self& s)
{
return _node != s._node;
}
};
class RBTree
{
typedef RBTreeNode<T> Node;
public:
typedef _TreeIterator<T> Iterator;
Iterator Begin()
{
Node* minLeft = _root;
while (minLeft && minLeft->_left)
{
minLeft = minLeft->_left;
}
return Iterator(minLeft);
}
Iterator Begin()
{
return Iterator(nullptr);
}
//.....
};
- 上层map和set的iterator的实现,注意,当需要使用一个模板里面的某一个函数或者变量时,typedef必须要加上typename
cpp
//set.h
typedef typename RBTree<K, K, MapKeyOfT>::Iterator iterator;
iterator begin()
{
return _t.Begin();
}
iterator end()
{
return _t.End();
}
//map.h
typedef typename RBTree<K, pair<K, V>, MapKeyOfT>::Iterator iterator;
iterator begin()
{
return _t.Begin();
}
iterator end()
{
return _t.End();
}
测试
cpp
void test_set()
{
gy::set<int> s;
s.insert(1);
s.insert(4);
s.insert(3);
s.insert(6);
gy::set<int>::iterator it = s.begin();
while (it != s.end())
{
cout << *it <<" ";
++it;
}
cout << endl;
}
void test_map()
{
gy::map<string, string> dict;
dict.insert({"left", "左边"});
dict.insert({ "right", "右边" });
dict.insert({"sort", "排序"});
dict.insert({"string", "字符串"});
gy::map<string, string>::iterator it = dict.begin();
while (it != dict.end())
{
cout << it->first << ":" << it->second << endl;
++it;
}
}
int main()
{
test_set();
test_map();
return 0;
}

iterator--
- 迭代器--的实现跟++的思路完全类似,逻辑正好反过来即可,因为他访问顺序是右子树->根结点->左子树
- iterator--有一个需要注意的是:当节点为空时即为end()节点 ,所以我们需要从根节点遍历,遍历到最右边节点,所以还需要一个根节点
cpp
Self& operator--()
{
if (_node == nullptr) // end()
{
// --end(),特殊处理,⾛到中序最后⼀个结点,整棵树的最右结点
Node* rightMost = _root;
while (rightMost && rightMost->_right)
{
rightMost = rightMost->_right;
}
_node = rightMost;
}
else if(_node->_left)
{
_node = _node->_left;
while (_node->_right)
{
_node = _node->_right;
}
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_left)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
- 最终代码
cpp
template<class T>
struct _TreeIterator
{
typedef RBTreeNode<T> Node;
typedef _TreeIterator<T> Self;
Node* _node;
Node* _root;
_TreeIterator(Node* node, Node* root)
:_node(node)
,_root(root)
{ }
T& operator*()
{
return _node->_data;
}
T* operator->()
{
return &_node->_data;
}
Self& operator++()
{
if (_node->_right)
{
_node = _node->_right;
while (_node->_left)
{
_node = _node->_left;
}
}
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 == nullptr) // end()
{
// --end(),特殊处理,⾛到中序最后⼀个结点,整棵树的最右结点
Node* rightMost = _root;
while (rightMost && rightMost->_right)
{
rightMost = rightMost->_right;
}
_node = rightMost;
}
else if(_node->_left)
{
_node = _node->_left;
while (_node->_right)
{
_node = _node->_right;
}
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_left)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
//后置++
Self operator++(int)
{
Self tmp = *this;
++(*this);
return tmp;
}
//后置--
Self operator--(int)
{
Self tmp = *this;
--(*this);
return tmp;
}
bool operator!=(const Self& s)
{
return _node != s._node;
}
};
template<class K, class T, class KeyOfT>
class RBTree
{
typedef RBTreeNode<T> Node;
public:
typedef _TreeIterator<T> Iterator;
Iterator Begin()
{
Node* minLeft = _root;
while (minLeft && minLeft->_left)
{
minLeft = minLeft->_left;
}
return Iterator(minLeft, _root);
}
Iterator End()
{
return Iterator(nullptr, _root);
}
//.....
}
测试
cpp
void test_set()
{
gy::set<int> s;
s.insert(1);
s.insert(4);
s.insert(3);
s.insert(6);
gy::set<int>::iterator it = s.end();
while (it != s.begin())
{
--it;
cout << *it <<" ";
}
cout << endl;
}
void test_map()
{
gy::map<string, string> dict;
dict.insert({"left", "左边"});
dict.insert({ "right", "右边" });
dict.insert({"sort", "排序"});
dict.insert({"string", "字符串"});
gy::map<string, string>::iterator it = dict.end();
while (it != dict.begin())
{
--it;
cout << it->first << ":" << it->second << endl;
}
}
int main()
{
test_set();
test_map();
return 0;
}

const_iterator
const_iterator和list的iterator也是类似的,const迭代器不是本身不能修改,而是指向的内容不能修改,因此我们可以和list的实现一样,多传入两个参数来控制内容不可改变和可变
cpp
typedef _TreeIterator<T, T&, T*> Iterator;
typedef _TreeIterator<T, const T&, const T*> ConstIterator;
cpp
//RBTree.h
template<class T, class Ref, class Ptr>
struct _TreeIterator
{
typedef RBTreeNode<T> Node;
typedef _TreeIterator<T, Ref, Ptr> Self;
Node* _node;
Node* _root;
_TreeIterator(Node* node, Node* root)
:_node(node)
,_root(root)
{ }
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
//......
}
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*> ConstIterator;
Iterator Begin()
{
Node* minLeft = _root;
while (minLeft && minLeft->_left)
{
minLeft = minLeft->_left;
}
return Iterator(minLeft, _root);
}
Iterator End()
{
return Iterator(nullptr, _root);
}
ConstIterator Begin() const
{
Node* minLeft = _root;
while (minLeft && minLeft->_left)
{
minLeft = minLeft->_left;
}
return ConstIterator (minLeft, _root);
}
ConstIterator End() const
{
return ConstIterator (nullptr, _root);
}
//.....
}
cpp
//set.h
namespace gy
{
template<class K>
class set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
typedef typename RBTree<K, K, SetKeyOfT>::Iterator iterator;
typedef typename RBTree<K, K, SetKeyOfT>::ConstIterator 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();
}
bool insert(const K& key)
{
return _t.Insert(key);
}
private:
RBTree<K, K, SetKeyOfT> _t;
};
}
//map.h
namespace gy
{
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<K, V>, MapKeyOfT>::Iterator iterator;
typedef typename RBTree<K, pair<K, V>, MapKeyOfT>::ConstIterator 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();
}
bool insert(const pair<K, V>& key)
{
return _t.Insert(key);
}
private:
RBTree<K, pair<K, V>, MapKeyOfT> _t;
};
}
测试
cpp
void Print(const gy::set<int>& s)
{
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
}
void test_set()
{
gy::set<int> s;
s.insert(1);
s.insert(4);
s.insert(3);
s.insert(6);
gy::set<int>::iterator it = s.end();
Print(s);
}
int main()
{
test_set();
return 0;
}

key不支持修改问题
- 上面实现的代码,普通迭代器的key是能够修改的,这不符合map/set的规则
- 对于set而言,key不能修改,因此在
RBTree<K, K, SetKeyOfT> _t加入const修饰RBTree<K, const K, SetKeyOfT> _t
cpp
namespace gy
{
template<class K>
class set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
typedef typename RBTree<K, const K, SetKeyOfT>::Iterator iterator;
typedef typename RBTree<K, const K, SetKeyOfT>::ConstIterator 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();
}
bool insert(const K& key)
{
return _t.Insert(key);
}
private:
//const修饰key,不可改变
RBTree<K, const K, SetKeyOfT> _t;
};
}
- 对于map而言,不能修改pair结构中的key,因此将
RBTree<K, pair<K, V>, MapKeyOfT> _t修改为RBTree<K, pair<const K, V>, MapKeyOfT> _t
cpp
namespace gy
{
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>::ConstIterator 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();
}
bool insert(const pair<K, V>& key)
{
return _t.Insert(key);
}
private:
RBTree<K, pair<const K, V>, MapKeyOfT> _t;
};
}
测试
cpp
void Print(gy::set<int>& s)
{
for (auto& e : s)
{
e++;
cout << e << " ";
}
cout << endl;
}
void test_set()
{
gy::set<int> s;
s.insert(1);
s.insert(4);
s.insert(3);
s.insert(6);
gy::set<int>::iterator it = s.end();
Print(s);
}
void test_map()
{
gy::map<int, int> dict;
dict.insert({ 1, 1 });
dict.insert({ -1, -1 });
dict.insert({6, 6});
dict.insert({3, 3});
gy::map<int, int>::iterator it = dict.begin();
while (it != dict.end())
{
it->first++;
it->second++;
cout << it->first << ":" << it->second << endl;
}
}
int main()
{
test_set();
test_map();
return 0;
}
从结果可以看出,无论是map还是set,普通迭代器也无法修改key,map的value值可以修改
insert/find返回值完善代码
- 根据库里面insert,返回值是一个pair类型,当插入成功,返回新节点的
{iterator,true},插入失败(已经存在),返回旧的节点的{iterator,false}
cpp
pair<Iterator, bool> Insert(const T& data)
{
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK;
return {Iterator(_root, _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 { Iterator(cur, _root), false};
}
}
cur = new Node(data);
Node* newnode = cur;
cur->_col = RED;
if (kot(parent->_data) < kot(data))
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
cur->_parent = parent;
while (parent && parent->_col == RED)
{
Node* grandparent = parent->_parent;
if (parent == grandparent->_left)
{
Node* uncle = grandparent->_right;
if (uncle && uncle->_col == RED)
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandparent->_col = RED;
//继续往上处理
cur = grandparent;
parent = cur->_parent;
}
else
{
//uncle不存在,或者存在且为黑色
// g
//p u
//c
//单旋
if (cur == parent->_left)
{
RotateR(grandparent);
//将parent->Col :BLACK
//将grandparent->Col:RED
parent->_col = BLACK;
grandparent->_col = RED;
}
else
{
// g
//p u
// c
//双旋
RotateL(parent);
RotateR(grandparent);
cur->_col = BLACK;
grandparent->_col = RED;
}
break;
}
}
else
{
Node* uncle = grandparent->_left;
if (uncle && uncle->_col == RED)
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandparent->_col = RED;
//继续往上处理
cur = grandparent;
parent = cur->_parent;
}
else
{
//存在且为黑或者不存在
// g
//u p
// c
//单旋
if (cur == parent->_right)
{
RotateL(grandparent);
//将parent->Col :BLACK
//将grandparent->Col:RED
parent->_col = BLACK;
grandparent->_col = RED;
}
else
{
// g
//u p
// c
//双旋
RotateR(parent);
RotateL(grandparent);
cur->_col = BLACK;
grandparent->_col = RED;
}
break;
}
}
}
_root->_col = BLACK;
return { Iterator(newnode, _root), true};
}
- find的返回值也是迭代器,找到了返回当前节点,没有找到,则返回End()节点
cpp
Iterator Find(const K& key)
{
KeyOfT kot;
Node* cur = _root;
while (cur)
{
if (kot(cur->_data) < key)
{
cur = cur->_right;
}
else if (kot(cur->_data) > key)
{
cur = cur->_left;
}
else
{
return Iterator(cur, _root);
}
}
return End();
}
operator[]
- map的operator[]的实现,当传入的key已经存在,则插入失败,我们可以获得key的iterator,根据iterator,返回value的值;如果key不存在,则会将{ key, V() }插入到map中,再通过迭代器返回value值
cpp
//map.h
V& operator[](const K& key)
{
pair<iterator, bool> ret = _t.Insert({ key, V() });
return ret.first->second;
}
测试
cpp
void test_map()
{
gy::map<string, string> dict;
dict.insert({"left", "左边"});
dict.insert({ "right", "右边" });
dict.insert({"sort", "排序"});
dict.insert({"string", "字符串"});
gy::map<string, string>::iterator it = dict.begin();
while (it != dict.end())
{
cout << it->first << ":" << it->second << endl;
++it;
}
cout << endl;
dict["insert"];
dict["left"] = "剩余";
for (auto& e : dict)
{
cout << e.first << ":" << e.second << endl;
}
}
int main()
{
test_map();
return 0;
}
operator[]从下面运行结果可以看到成功实现
> 


