目录
前言:map和set容器是以平衡二叉搜索树(红黑树)为底层来实现的,与接下来要学习的unordered_map和unordered_set是C++使用最多的关联式容器。
map和set的底层是红黑树,要想学map和set的模拟实现,就要先学红黑树,而学习红黑树前建议先学AVLTree。
AVLTree-》深入理解AVLTree【旋转控制平衡(单旋、双旋)】_糖果雨滴a的博客-CSDN博客
红黑树-》深入理解 红黑树【满足红黑树5条规则】_糖果雨滴a的博客-CSDN博客
之前学过的vector、list、deque等容器都叫做序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。
而今天所学习的关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是
根据应用场景的不同,STL实现了两种不同结构的关联式容器:树型结构和哈希结构。树型结构的关联式容器主要有四种:map、set、multimap、multiset。这四种容器的共同点是:使用平衡搜索树(红黑树)作为其底层结构,容器中的元素是一个有序的序列。
键值对是用来表示具有一一对应关系的一种结构 ,该结构中一般只包括两个成员变量key和value,key代表键值, value表示与key对应的信息。
① set是按照一定次序存储元素的容器
② 在set中,元素的value也表示key(value就是key,类型为T),并且每个value(key)必须是唯一的
③ 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格若排序准则进行排序
④ set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代
⑤ set的底层是用平衡搜索二叉树(红黑树)实现的
注意:
① set/multiset与map/multimap不同,map中存储的是真正的键值对
② set中插入元素时,只需要插入value即可,不需要构造键值对
③ set中的元素不可以重复(因此可以使用set进行去重)
④ 使用set的迭代器遍历set中的元素,可以得到有序序列
⑤ set中的元素默认按照小于来比较(升序)
⑥ set中查找某个元素时,时间复杂度为:O(log2n)
⑦ set中的元素不允许修改

T: set中存放元素的类型,实际在底层存储
Compare:set中元素默认按照小于来比较
Alloc:set中元素空间的管理方式,使用STL提供的空间配置器管理
set() 构造空的set
set(Inputlterator first, Inputlterator last) 用(first, last)区间中的元素构造set
set(const set
) set的拷贝构造
迭代器与之前相同,依旧是正向、反向、const修饰的迭代器
- // 排序 + 去重
- set<int>::iterator it = s.begin();
- while (it != s.end())
- {
- //*it = 10;
- cout << *it << " ";
- ++it;
- }
- cout << endl;
-
- for (auto e : s)
- {
- cout << e << " ";
- }
- cout << endl;
empty() 检测set是否为空,空返回true,否则返回false
size() 返回set中有效元素的个数
pair
insert(const value_type& x) 插入(在set中插入元素x,实际插 入的是构成的键值对,如果 插入成功,返回<该元素在set中的 位置, true>,如果插入失败,说明 x在set中已经存在,返回 )
void erase(iterator position) 删除set中position位置上的元素
size_type erase(const key_type& x) (multiset)删除set中值为x的元素,返回删除的 元素的个数
void erase(iterator first, iterator last) 删除set中(first, last)区间中的元素
void swap(set
& st) 交换set中的元素void clear() 将set中的元素清空
iterator find(const key_type& x) 返回set中值为x的元素的位置
size_type count(const key_type& x) 返回set中值为x的元素的个数
iterator lower_bound(const value_type& val) 返回>=val的位置的迭代器
upper_bound(const value_type& val) 返回>val的位置的迭代器
- void test_set1()
- {
- set<int> s;
- s.insert(4);
- s.insert(5);
- s.insert(2);
- s.insert(1);
- s.insert(1);
- s.insert(3);
- s.insert(2);
- s.insert(1);
-
- cout << s.erase(3) << endl;
- cout << s.erase(30) << endl;
-
- for (auto e : s)
- {
- cout << e << " ";
- }
- cout << endl;
-
- set<int>::iterator pos = s.find(3);
- if (pos != s.end())
- s.erase(pos);
-
- for (auto e : s)
- {
- cout << e << " ";
- }
- cout << endl;
-
- if (s.count(5))
- {
- cout << "5在" << endl;
- }
- }
-
- void test_set2()
- {
- set<int> s;
- s.insert(4);
- s.insert(5);
- s.insert(1);
- s.insert(3);
- s.insert(2);
- s.insert(7);
- s.insert(9);
-
- for (auto e : s)
- {
- cout << e << " ";
- }
- cout << endl;
-
- // 返回>x位置的迭代器 -》 都是返回 7位置的迭代器
- //set
::iterator upIt = s.upper_bound(5); // 存在 - //upIt = s.upper_bound(6); // 不存在
-
- // 删除x <= <= y的区间 删除 [x,y]
- int x, y;
- cin >> x >> y;
- auto leftIt = s.lower_bound(x); // [
- auto rightIt = s.upper_bound(y); // )
- s.erase(leftIt, rightIt);
- for (auto e : s)
- {
- cout << e << " ";
- }
- cout << endl;
- }
① map是关联式容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素
② 在map中,键值key通常用于排序和唯一的标识元素,而值value中存储与此键值key关联的内容,键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起,与其取别名为pair
③ 在内部,map中的元素总是按照键值key进行比较排序的
④ map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)
⑤ map支持下标访问符,即在[]中放入key,就可以找到与key对应的value
⑥ map的底层是用平衡搜索二叉树(红黑树)实现的

key:键值对中key的类型
T:键值对
Compare:比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)
Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器
map() 构造一个空的map
迭代器与之前相同,依旧是正向、反向、const修饰的迭代器
- // 遍历
- //map
::iterator it = dict.begin(); - auto it = dict.begin();
- while (it != dict.end())
- {
- //cout << *it << " "; // it->operator*()
- //cout << (*it).first << ":" << (*it).second << endl;
- cout << it->first << ":" << it->second << endl;
- ++it;
- }
- cout << endl;
-
- for (const auto& kv : dict)
- {
- cout << kv.first << ":" << kv.second << endl;
- }
empty() 检查map中的元素是否为空
size() 返回map中有效元素的个数
mapped_type& operator[](const key_type& k) 返回key对应的value
pair
insert(const value_type& x) 在map中插入键值对x,注意x是一 个键值对,返回值也是键值对: iterator代表新插入元素的位置, bool代表释放插入成功void erase(iterator position) 删除position位置上的元素
size_type erase(const key_type& x) 删除键值为x的元素
void erase(iterator first) 删除(first, last)区间中的元素
void swap(map
& mp) 交换两个map中的元素void clear() 将map中的元素清空
iterator find(const key_type& x) 在map中插入key为x的元素,找到返回该元素的位置 的迭代器,否则返回end
const_iterator find(const key_type& x) 在map中插入key为x的元素,找到返回该元素 的位置的const迭代器,否则返回cend
size_type count(const key_type& x) 返回key为x的键值在map中的个数,注意map中 key是唯一的,因此该函数的返回值要么为0,要 么为1,因此也可以用该函数来检测一个key是否 在map中
- void test_map1()
- {
- map
dict; -
- // pair构造函数
- dict.insert(pair
("sort", "排序")); - pair
kv("insert", "插入") ; - dict.insert(kv);
-
- // make_pair
- auto ret1 = dict.insert(make_pair("left", "左边"));
- auto ret2 = dict.insert(make_pair("left", "剩余"));
-
- dict["operator"] = "重载"; // 插入+修改
- dict["left"] = "左边、剩余"; // 修改
- dict["erase"]; // 插入
- cout << dict["left"] << endl; // 查找
-
-
- // C++11方法
- //dict.insert({ "right", "右边" });
-
- // 遍历
- //map
::iterator it = dict.begin(); - auto it = dict.begin();
- while (it != dict.end())
- {
- //cout << *it << " "; // it->operator*()
- //cout << (*it).first << ":" << (*it).second << endl;
- cout << it->first << ":" << it->second << endl;
- ++it;
- }
- cout << endl;
-
- for (const auto& kv : dict)
- {
- cout << kv.first << ":" << kv.second << endl;
- }
- }
-
- void test_map2()
- {
- string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
-
- // 方法1
- /*map
countMap; - for (auto& str : arr)
- {
- map
::iterator it = countMap.find(str); - if (it != countMap.end())
- {
- it->second++;
- }
- else
- {
- countMap.insert(make_pair(str, 1));
- }
- }*/
-
- // 方法2
- //map
countMap; - //for (auto& str : arr)
- //{
- // //pair
- // auto ret = countMap.insert(make_pair(str, 1));
- // if (ret.second == false)
- // {
- // ret.first->second++;
- // }
- //}
-
- // 方法3
- map
int> countMap; - for (auto& str : arr)
- {
- countMap[str]++;
- }
-
- for (const auto& kv : countMap)
- {
- cout << kv.first << ":" << kv.second << endl;
- }
- }
① multiset是按照特定顺序存储元素的容器,其中元素是可以重复的
② 在multiset中,元素的value也会识别它(因为multiset中本身存储的就是
③ 在内部,multiset中的元素总是按照其内部比较规则(类型比较)所指示的特定严格若排序准则进行排序
④ multiset容器通过key访问单个元素的速度通常比unordered_multiset容器慢,但当使用迭代器遍历时会得到一个有序序列
⑤ multiset底层结构为二叉搜索树(红黑树)
注意:
① multiset中在底层中存储的是
② multiset的插入接口中只需要插入即可
③ 与set的区别是,multiset中的元素可以重复,set中的元素不能重复
④ 使用迭代器对multiset中的元素进行遍历,可以得到有序的序列
⑤ multiset中的元素不能修改
⑥ 在multiset中找某个元素,时间复杂度为O(log2n)
⑦ multiset的作用:可以对元素进行排序
① multimap是关联式容器,它按照特定的顺序,存储由key和value映射的键值对
② 在multimap中,通常按照key排序和唯一的标识元素,而映射的value存储与key关联的内容。key和value的类型可能不同,通过multimap内部的成员类型value_type组合在一起,value_type是组合key和value的键值对
③ 在内部,multimap中的元素总是通过其内部比较对象,按照指定的特定严格弱排序标准对key进行排序的
④ multimap通过key访问单个元素的速度通常比unordered_multimap容器慢,但是使用迭代器直接遍历multimap中的元素可以得到关于key有序的序列
⑤ multimap的底层结构为二叉搜索树(红黑树)
注意:
① multimap中的key是可以重复的
② multimap中的元素默认将key按照小于来比较
③ multimap中没有重载operator[]操作
④ 使用时与map包含的头文件相同
multiset和set的使用几乎相同,multimap和map的使用几乎相同(multimap不能用operator[])
map和set的模拟实现实际上就是在红黑树的基础上进行封装,因此主要实现的红黑树,红黑树实现好了,map和set只要封装一下就可以了。
因为我们不知道要用红黑树来实现set还是map,所以我们模板参数就用一个T,并且数据用_data(而不是kv或key)。
- template<class T>
- struct RBTreeNode
- {
- RBTreeNode
* _left; - RBTreeNode
* _right; - RBTreeNode
* _parent; - T _data;
-
- Color _col;
-
- RBTreeNode(const T& data)
- : _data(data)
- , _left(nullptr)
- , _right(nullptr)
- , _parent(nullptr)
- , _col(RED)
- {}
- };
template
增加KeyOfT的仿函数(支持取出T对象中key的仿函数)
set RBTree
map RBTree>
如果是set则比较好取出key进行比较,而如果是map就需要先取出kv在找到first才能进行比较,因此我们需要实现一个仿函数来进行封装。
这里的插入函数就要通过创建KeyOfT类型的对象,通过仿函数来完成对于不同的T对象实现相同的操作。
- pair
bool > Insert(const T& data) - {
- // 1.搜索树的规则插入
- // 2.看是否违反平衡规则,如果违反就需要处理:旋转
- if (_root == nullptr)
- {
- _root = new Node(data);
- _root->_col = BLACK;
- return make_pair(iterator(_root), true);
- }
-
- KeyOfT kot;
-
- Node* parent = nullptr;
- Node* cur = _root;
- 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), true);
- }
- }
-
- 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* grandfather = parent->_parent;
- assert(grandfather);
-
- if (grandfather->_left == parent)
- {
- Node* uncle = grandfather->_right;
- // 情况一:叔叔存在且为红
- if (uncle && uncle->_col == RED)
- {
- // 变色
- parent->_col = uncle->_col = BLACK;
- grandfather->_col = RED;
-
- // 继续往上处理
- cur = grandfather;
- parent = cur->_parent;
- }
- // 叔叔不存在 or 叔叔存在且为黑
- else
- {
- // 情况二:单旋(右单旋)
- 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;
-
- }
- }
- // grandfather->_right == parent
- else
- {
- Node* uncle = grandfather->_left;
- // 情况一:叔叔存在且为红
- if (uncle && uncle->_col == RED)
- {
- // 变色
- parent->_col = uncle->_col = BLACK;
- grandfather->_col = RED;
-
- // 继续往上处理
- cur = grandfather;
- parent = cur->_parent;
- }
- // 叔叔不存在 or 叔叔存在且为黑
- else
- {
- // 情况二:单旋(左单旋)
- if (cur == parent->_right)
- {
- // g
- // p
- // c
- RotateL(grandfather);
- parent->_col = BLACK;
- grandfather->_col = RED;
- }
- // 情况三:双旋(右左双旋)
- else
- {
- // g
- // p
- // c
- RotateR(parent);
- RotateL(grandfather);
- cur->_col = BLACK;
- grandfather->_col = RED;
- }
-
- break;
- }
- }
- }
-
- _root->_col = BLACK;
-
- return make_pair(iterator(newnode), true);
- }
- template<class T, class Ref, class Ptr>
- struct __RBTreeIterator
- {
- typedef RBTreeNode
Node; - typedef __RBTreeIterator
Self; - Node* _node;
-
- __RBTreeIterator(Node* node)
- : _node(node)
- {}
-
- Ref operator*()
- {
- return _node->_data;
- }
-
- Ptr operator->()
- {
- return &_node->_data;
- }
-
- Self& operator++()
- {
- if (_node->_right == nullptr)
- {
- // 找祖先里面,孩子是父亲的那个
- Node* cur = _node;
- Node* parent = cur->_parent;
- while (parent && parent->_right == cur)
- {
- cur = cur->_parent;
- parent = parent->_parent;
- }
-
- _node = parent;
- }
- else
- {
- // 右子树的最左节点
- Node* subLeft = _node->_right;
- while (subLeft->_left)
- {
- subLeft = subLeft->_left;
- }
-
- _node = subLeft;
- }
-
- return *this;
- }
-
- Self operator++(int)
- {
- Self tmp(*this);
-
- ++(*this);
-
- return tmp;
- }
-
- Self& operator--()
- {
- if (_node->_left == nullptr)
- {
- // 找祖先里面,孩子是父亲
- Node* cur = _node;
- Node* parent = cur->_parent;
- while (parent && cur == parent->_left)
- {
- cur = cur->_parent;
- parent = parent->_parent;
- }
-
- _node = parent;
- }
- else
- {
- // 左子树的最右节点
- Node* subRight = _node->_left;
- while (subRight->_right)
- {
- subRight = subRight->_right;
- }
-
- _node = subRight;
- }
-
- return *this;
- }
-
- Self operator--(int)
- {
- Self tmp(*this);
-
- --(*this);
-
- return tmp;
- }
-
- bool operator!=(const Self& s) const
- {
- return _node != s._node;
- }
-
- bool operator==(const Self& s) const
- {
- return _node == s->_node;
- }
- };
这个迭代器的增加类似于链表list类的实现C++ list类(包括反向迭代器适配器的实现)_糖果雨滴a的博客-CSDN博客_list 反向迭代器
需要我们自己去封装一个迭代器,这里的模板参数中Ref是T&,Ptr是T*,然后将节点类typedef为Node,将自己typedef为Self。
接下来就是分别实现各种操作符重载,operator*,->,!=,==都比较简单,这里不过多赘述。而operator++要详细的说一下。
我们根据这个图来说明:
我们实现的++是中序遍历,左子树 根 右子树。这里因为是3叉链,因此我们可以有比之前更简单的代码实现。这里我们实现迭代版的。
这里我们可以根据当前位置的右子树是否为空来进行分情况讨论:
第一种情况:右子树为空-》找孩子是祖先的左的那个节点
第二种情况:右孩子不为空-》找右子树最左的那个节点
根据上面的图来说,第一个it是5所在的迭代器,它的右子树为空,因此找它的祖先里面,孩子是父亲的左的那个,这里6是5的祖先,5是6的左,因此下一个到6的迭代器。6的右子树不为空,找到它右子树的最左节点,7的迭代器。7的右子树为空,因此往上找,6是7的祖先,但是7不是6的左节点,继续往上,8是6和7的祖先,并且7是8的左节点,因此下一个是8的迭代器。右边同理。
代码实现:
- Self& operator++()
- {
- if (_node->_right == nullptr)
- {
- // 找祖先里面,孩子是父亲的那个
- Node* cur = _node;
- Node* parent = cur->_parent;
- while (parent && parent->_right == cur)
- {
- cur = cur->_parent;
- parent = parent->_parent;
- }
-
- _node = parent;
- }
- else
- {
- // 右子树的最左节点
- Node* subLeft = _node->_right;
- while (subLeft->_left)
- {
- subLeft = subLeft->_left;
- }
-
- _node = subLeft;
- }
-
- return *this;
- }
operator--的实现正好与++相反:
--相当于:右子树 根 左子树
第一种情况:左子树为空-》找孩子是祖先的右的那个节点
第二种情况:左孩子不为空-》找左子树最右的那个节点
代码实现:
- Self& operator--()
- {
- if (_node->_left == nullptr)
- {
- // 找祖先里面,孩子是父亲
- Node* cur = _node;
- Node* parent = cur->_parent;
- while (parent && cur == parent->_left)
- {
- cur = cur->_parent;
- parent = parent->_parent;
- }
-
- _node = parent;
- }
- else
- {
- // 左子树的最右节点
- Node* subRight = _node->_left;
- while (subRight->_right)
- {
- subRight = subRight->_right;
- }
-
- _node = subRight;
- }
-
- return *this;
- }
这里实现的++和--都是前置的,而后置只需要调用前置的并进行一定修改即可:
- Self operator++(int)
- {
- Self tmp(*this);
-
- ++(*this);
-
- return tmp;
- }
-
- Self operator--(int)
- {
- Self tmp(*this);
-
- --(*this);
-
- return tmp;
- }
通过对改造后的红黑树进行封装即可。
注意这里实现的仿函数,直接返回key。(这里因为map,所以才要实现仿函数)
- namespace hb
- {
- 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; -
- iterator begin() const
- {
- return _t.Begin();
- }
-
- iterator end() const
- {
- return _t.End();
- }
-
- pair
bool > insert(const K& key) - {
- // pair
::iterator, bool> ret = _t.Insert(key); - auto ret = _t.Insert(key);
- return pair
bool>(iterator(ret.first._node), ret.second); - }
-
- iterator find(const K& key)
- {
- return _t.Find(key);
- }
- private:
- RBTree
_t; - };
- }
这里面仿函数返回的是kv.first。
map比set多的还有一个operator[],因为这个operator[],就导致红黑树内的insert函数需要返回pair,这样实现operator[]更简单。
- namespace hb
- {
- template<class K, class V>
- class map
- {
- struct MapKeyOfT
- {
- const K& operator()(const pair
& kv) - {
- return kv.first;
- }
- };
- public:
- typedef typename RBTree
, MapKeyOfT>::iterator iterator; - typedef typename RBTree
, MapKeyOfT>::const_iterator const_iterator; -
- iterator begin()
- {
- return _t.Begin();
- }
-
- iterator end()
- {
- return _t.End();
- }
-
- pair
bool > insert(const pair& kv) - {
- return _t.Insert(kv);
- }
-
- iterator find(const K& key)
- {
- return _t.Find(key);
- }
-
- V& operator[](const K& key)
- {
- pair
bool> ret = insert(make_pair(key, V())); - return ret.first->second;
- }
-
- private:
- RBTree
, MapKeyOfT> _t; - };
- }
- #pragma once
-
- #include
-
- enum Color
- {
- RED,
- BLACK,
- };
-
- template<class T>
- struct RBTreeNode
- {
- RBTreeNode
* _left; - RBTreeNode
* _right; - RBTreeNode
* _parent; - T _data;
-
- Color _col;
-
- RBTreeNode(const T& data)
- : _data(data)
- , _left(nullptr)
- , _right(nullptr)
- , _parent(nullptr)
- , _col(RED)
- {}
- };
-
- template<class T, class Ref, class Ptr>
- struct __RBTreeIterator
- {
- typedef RBTreeNode
Node; - typedef __RBTreeIterator
Self; - Node* _node;
-
- __RBTreeIterator(Node* node)
- : _node(node)
- {}
-
- Ref operator*()
- {
- return _node->_data;
- }
-
- Ptr operator->()
- {
- return &_node->_data;
- }
-
- Self& operator++()
- {
- if (_node->_right == nullptr)
- {
- // 找祖先里面,孩子是父亲的那个
- Node* cur = _node;
- Node* parent = cur->_parent;
- while (parent && parent->_right == cur)
- {
- cur = cur->_parent;
- parent = parent->_parent;
- }
-
- _node = parent;
- }
- else
- {
- // 右子树的最左节点
- Node* subLeft = _node->_right;
- while (subLeft->_left)
- {
- subLeft = subLeft->_left;
- }
-
- _node = subLeft;
- }
-
- return *this;
- }
-
- Self operator++(int)
- {
- Self tmp(*this);
-
- ++(*this);
-
- return tmp;
- }
-
- Self& operator--()
- {
- if (_node->_left == nullptr)
- {
- // 找祖先里面,孩子是父亲
- Node* cur = _node;
- Node* parent = cur->_parent;
- while (parent && cur == parent->_left)
- {
- cur = cur->_parent;
- parent = parent->_parent;
- }
-
- _node = parent;
- }
- else
- {
- // 左子树的最右节点
- Node* subRight = _node->_left;
- while (subRight->_right)
- {
- subRight = subRight->_right;
- }
-
- _node = subRight;
- }
-
- return *this;
- }
-
- Self operator--(int)
- {
- Self tmp(*this);
-
- --(*this);
-
- return tmp;
- }
-
- bool operator!=(const Self& s) const
- {
- return _node != s._node;
- }
-
- bool operator==(const Self& s) const
- {
- return _node == s->_node;
- }
- };
-
- // T决定红黑树存什么数据
- // set RBTree
- // map RBTree
> - // KeyOfT -> 支持取出T对象中key的仿函数
- template<class K, class T, class KeyOfT>
- class RBTree
- {
- typedef RBTreeNode
Node; - public:
- typedef __RBTreeIterator
iterator; - typedef __RBTreeIterator
const T&, const T*> const_iterator; -
- iterator Begin()
- {
- Node* subLeft = _root;
- while (subLeft && subLeft->_left)
- {
- subLeft = subLeft->_left;
- }
-
- return iterator(subLeft);
- }
-
- iterator End()
- {
- return iterator(nullptr);
- }
-
- const_iterator Begin() const
- {
- Node* subLeft = _root;
- while (subLeft && subLeft->_left)
- {
- subLeft = subLeft->_left;
- }
-
- return const_iterator(subLeft);
- }
-
- const_iterator End() const
- {
- return const_iterator(nullptr);
- }
-
- pair
bool > Insert(const T& data) - {
- // 1.搜索树的规则插入
- // 2.看是否违反平衡规则,如果违反就需要处理:旋转
- if (_root == nullptr)
- {
- _root = new Node(data);
- _root->_col = BLACK;
- return make_pair(iterator(_root), true);
- }
-
- KeyOfT kot;
-
- Node* parent = nullptr;
- Node* cur = _root;
- 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), true);
- }
- }
-
- 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* grandfather = parent->_parent;
- assert(grandfather);
-
- if (grandfather->_left == parent)
- {
- Node* uncle = grandfather->_right;
- // 情况一:叔叔存在且为红
- if (uncle && uncle->_col == RED)
- {
- // 变色
- parent->_col = uncle->_col = BLACK;
- grandfather->_col = RED;
-
- // 继续往上处理
- cur = grandfather;
- parent = cur->_parent;
- }
- // 叔叔不存在 or 叔叔存在且为黑
- else
- {
- // 情况二:单旋(右单旋)
- 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;
-
- }
- }
- // grandfather->_right == parent
- else
- {
- Node* uncle = grandfather->_left;
- // 情况一:叔叔存在且为红
- if (uncle && uncle->_col == RED)
- {
- // 变色
- parent->_col = uncle->_col = BLACK;
- grandfather->_col = RED;
-
- // 继续往上处理
- cur = grandfather;
- parent = cur->_parent;
- }
- // 叔叔不存在 or 叔叔存在且为黑
- else
- {
- // 情况二:单旋(左单旋)
- if (cur == parent->_right)
- {
- // g
- // p
- // c
- RotateL(grandfather);
- parent->_col = BLACK;
- grandfather->_col = RED;
- }
- // 情况三:双旋(右左双旋)
- else
- {
- // g
- // p
- // c
- RotateR(parent);
- RotateL(grandfather);
- cur->_col = BLACK;
- grandfather->_col = RED;
- }
-
- break;
- }
- }
- }
-
- _root->_col = BLACK;
-
- return make_pair(iterator(newnode), true);
- }
-
- private:
- void RotateL(Node* parent)
- {
- Node* subR = parent->_right;
- Node* subRL = subR->_left;
-
- parent->_right = subRL;
- if (subRL)
- subRL->_parent = parent;
-
- Node* ppNode = parent->_parent;
-
- subR->_left = parent;
- parent->_parent = subR;
-
- if (parent == _root)
- {
- _root = subR;
- _root->_parent = nullptr;
- }
- else
- {
- if (parent == ppNode->_left)
- {
- ppNode->_left = subR;
- }
- else
- {
- ppNode->_right = subR;
- }
-
- subR->_parent = ppNode;
- }
- }
-
- void RotateR(Node* parent)
- {
- Node* subL = parent->_left;
- Node* subLR = subL->_right;
-
- parent->_left = subLR;
- if (subLR)
- subLR->_parent = parent;
-
- Node* ppNode = parent->_parent;
-
- subL->_right = parent;
- parent->_parent = subL;
-
- if (parent == _root)
- {
- _root = subL;
- _root->_parent = nullptr;
- }
- else
- {
- if (ppNode->_left == parent)
- {
- ppNode->_left = subL;
- }
- else
- {
- ppNode->_right = subL;
- }
- subL->_parent = ppNode;
- }
-
- }
-
- iterator 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 iterator(cur);
- }
- }
-
- return End();
- }
- private:
- Node* _root = nullptr;
- };
- #pragma once
-
- #include "RBTree.h"
-
- namespace hb
- {
- 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; -
- iterator begin() const
- {
- return _t.Begin();
- }
-
- iterator end() const
- {
- return _t.End();
- }
-
- pair
bool > insert(const K& key) - {
- // pair
::iterator, bool> ret = _t.Insert(key); - auto ret = _t.Insert(key);
- return pair
bool>(iterator(ret.first._node), ret.second); - }
-
- iterator find(const K& key)
- {
- return _t.Find(key);
- }
- private:
- RBTree
_t; - };
- }
- #pragma once
-
- #include "RBTree.h"
-
- namespace hb
- {
- template<class K, class V>
- class map
- {
- struct MapKeyOfT
- {
- const K& operator()(const pair
& kv) - {
- return kv.first;
- }
- };
- public:
- typedef typename RBTree
, MapKeyOfT>::iterator iterator; - typedef typename RBTree
, MapKeyOfT>::const_iterator const_iterator; -
- iterator begin()
- {
- return _t.Begin();
- }
-
- iterator end()
- {
- return _t.End();
- }
-
- pair
bool > insert(const pair& kv) - {
- return _t.Insert(kv);
- }
-
- iterator find(const K& key)
- {
- return _t.Find(key);
- }
-
- V& operator[](const K& key)
- {
- pair
bool> ret = insert(make_pair(key, V())); - return ret.first->second;
- }
-
- private:
- RBTree
, MapKeyOfT> _t; - };
-
- void test_map1()
- {
- map
int> m; - m.insert(make_pair("111", 1));
- m.insert(make_pair("555", 5));
- m.insert(make_pair("333", 3));
- m.insert(make_pair("222", 2));
-
- map
int>::iterator it = m.begin(); - while (it != m.end())
- {
- cout << it->first << ":" << it->second << endl;
- ++it;
- }
- cout << endl;
-
- for (auto& kv : m)
- {
- cout << kv.first << ":" << kv.second << endl;
- }
- cout << endl;
- }
- }