目录
一、set、map的介绍
1、set的介绍
1. set是按照一定次序存储元素的容器2. 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。3. 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序。4. set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代。5. set在底层是用红黑树实现的。
set主要是用来查看元素是否在某一集合中,并且它默认在set中是升序的,且不含有重复元素
set是一个关联式容器,是K的模型,它不允许有键值冗余的情况发生
set模板具有三个参数,第一个是元素类型,第二个参数是一个仿函数,默认的缺省值是less,排的是升序
并且它的拷贝和赋值都是深拷贝,代价极大,拷贝的是整棵树
find是set常用的接口,插入元素之后需要查找是否存在,如果能够找到返回对应位置的迭代器,如果没有找到,返回的是end
set的遍历特征是有序+去重
#include <iostream>
#include <set>
using namespace std;
void test_set1()
{
int a[] = {1, 2, 1, 6, 3, 8, 5};
set<int> s(a, a + sizeof(a) / sizeof(int));
for(const auto& e : s)
{
cout << e << endl;
}
}
int main()
{
test_set1();
return 0;
}
接下来就是set的删除了
void test_set1()
{
int a[] = {1, 2, 1, 6, 3, 8, 5};
set<int> s(a, a + sizeof(a) / sizeof(int));
for(const auto& e : s)
{
cout << e << " ";
}
s.erase(30);
for(const auto& e : s)
{
cout << e << " ";
}
set<int>::iterator pos = s.find(20);
s.erase(pos);
for(const auto& e : s)
{
cout << e << " ";
}
}
我们发现上面我写了两种删除,那么这两种删除方式有什么区别吗?
我们先编译运行一下,我们先屏蔽掉下面删除20的代码
发现是没有任何问题的,我们寻找30,set中没有30它也不会报错,也不会删除
接下来我们使用下面的删除逻辑
然后我们发现他就崩了原因是:我们查找20,find没有找到它会返回end,然后我们删除end时,end指向的是最后一个元素的下一个位置,我们把它删除了,程序就会崩溃
这就是两种删除方式的区别。
正确做法
set<int>::iterator pos = s.find(20);
if(pos != s.end())
{
s.erase(pos);
}
for(const auto& e : s)
{
cout << e << " ";
}
接下来是count这个函数,它会返回某元素的个数,对于set来说是没有用的,set内部相同元素个数就是1,没有就是0
这个接口是为了保持接口一致性,主要是给multiset来使用的
multiset和set用法类似,不过就是允许键值冗余的现象存在
void test_multiset()
{
int a[] = {1, 2, 1, 6, 3, 8, 5};
multiset<int> ms(a, a + sizeof(a) / sizeof(int));
for(const auto& e : ms)
{
cout << e << " ";
}
cout << endl;
cout << ms.count(1) << endl;
}
这时我们再调用count,1的个数就变成了2
2、map的介绍
map与set也十分的相似,map是K/V的模型,set是K的模型
map也有两种
区别与set和multiset相同,只是键值是否允许冗余的差别
不过map的插入就比较特别了
我们发现insert的参数是一个value_type类型
然后我们发现它实际上是一个pair
template <class T1, class T2>
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair(): first(T1()), second(T2())
{}
pair(const T1& a, const T2& b): first(a), second(b)
{}
};
pair又叫做键值对:用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。比如:现在要建立一个英汉互译的字典,那该字典中必然有英文单词与其对应的中文含义,而且,英文单词与其中文含义是一一对应的关系,即通过该应该单词,在词典中就可以找到与其对应的中文含义。
也就是说我们每次插入时传入一个键值对
map<string, string> countMap;
countMap.insert(pair<string, string>("苹果", "apple"));
这样显得十分的麻烦,这时我们还可以借助其它函数来帮助我们自动生成pair,就不用我们每次手动传一个pair的匿名对象了
countMap.insert(make_pair("香蕉", "banana"));
同时我们还发现一个奇怪的点map的insert的返回值也是一个pair,那么这个pair中存的是什么呢?
通过前面的英文文档我们大概了解了返回值的含义
如果这个元素已经存在了,我们就返回该元素位置的迭代器,也就是pair的第一个参数,pair的第二个 参数就置为flase代表插入失败
如果这个元素不存在,就返回新插入元素的迭代器,返回true
insert的返回值实际上是为了[ ]操作符重载所设计的
map的operator[ ]与我们前面见到的[ ] 都不太一样
[ ]内传入的是V,返回的是K的引用
如果该元素不存在,就插入这个元素,并且调用V的默认构造
void test_map()
{
string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
"苹果", "香蕉", "苹果", "香蕉" };
map<string, int> countMap;
for(const auto& e : arr)
{
countMap[e]++;
}
for(const auto& e : countMap)
{
cout << e.first << " : " << e.second << endl;
}
}
这与我们的预期一致,最开始的时候map中什么元素都没有,正常调用[ ]一定会崩,他没有崩并且还将其插入了。
总结:
1、map中有这个key,返回value的引用 (查找,修改value)
2、map中没有这个key,会插入一个pair(key, V()),返回value的引用 (插入+修改)
二、红黑树的实现
1、具体框架
红黑树基本代码:
#pragma once
#include <iostream>
#include <utility>
#include <cassert>
#include <ctime>
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<const K, V> _kv;
Colour _col;
RBTreeNode(const pair<const K,V>& kv)
:_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_kv(kv)
{}
};
template<class K,class V>
class RBTree
{
typedef RBTreeNode<K, V> Node;
public:
bool insert(const pair<const 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* grandfather = parent->_parent;
assert(grandfather);
assert(grandfather->_col == BLACK);
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
/* g
* p
* c
*/
if (cur == parent->_left)
{
RotateR(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
/* g
* p u
* c
*/
else
{
RotateL(parent);
RotateR(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
else
{
Node* uncle = grandfather->_left;
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
/* g
* p
* c
*/
if (cur == parent->_right)
{
RotateL(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
/* g
* u p
* c
*/
else
{
RotateR(parent);
RotateL(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
}
}
}
_root->_col = BLACK;
return true;
}
void InOrder()
{
_InOrder(_root);
}
bool IsBalance()
{
int benchmark = 0;
return _PrevCheck(_root, 0, benchmark);
}
private:
bool _PrevCheck(Node* root, int blackNum, int& benchmark)
{
if (root == nullptr)
{
if (benchmark == 0)
{
benchmark = blackNum;
return true;
}
if (blackNum != benchmark)
{
cout << "��ɫ�ڵ�����ͬ" << endl;
return false;
}
else
{
return true;
}
}
if (root->_col == BLACK)
{
blackNum++;
}
if (root->_col == RED && root->_parent->_col == RED)
{
cout << "�������ĺ�ɫ�ڵ�" << endl;
return false;
}
return _PrevCheck(root->_left, blackNum, benchmark)
&& _PrevCheck(root->_right, blackNum, benchmark);
}
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
cout << root->_kv.first << " : " << root->_kv.second << endl;
_InOrder(root->_right);
}
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 (_root == parent)
{
_root = subR;
subR->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
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;//��¼parent��parent����ת���֮������
subL->_right = parent;
parent->_parent = subL;
if (_root == parent)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subL;
}
else
{
ppNode->_right = subL;
}
subL->_parent = ppNode;
}
}
Node* _root = nullptr;
};
void testRBTree()
{
int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
RBTree<int, int> rb;
/*for (const auto& it : a)
{
rb.insert(make_pair(it, it));
}*/
//rb.InOrder();
const size_t N = 100000;
srand(time(0));
for (size_t i = 0; i < N; i++)
{
int x = rand();
cout << x << endl;
rb.insert(make_pair(x, x));
}
cout << rb.IsBalance() << endl;
}
我们前面已经实现了红黑树的基本功能,接下来就是我们将红黑树封装一下,让它能够既能是K模型也可以是K/V模型,并且给它加上迭代器
使两种模型都能够存在,我们就要将上述的红黑树的节点存储一个模板T
T可以是K也可以是pair,这就解决了一部分问题,接下来的问题就是我们要插入节点,一定会需要进行比较,我们无法区分pair和K,虽然pair库中已经帮我们实现了<和>但是,这种实现方式并不是我们想要的
我们的map是只比较pair的第一个元素,库中实现的无法满足我们的需求,我们只好借助与仿函数来实现,我们使用仿函数来获取pair的第一个元素,仿函数的具体实现我们并不关系
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)
{}
};
树的节点内容已经变更为data
2、迭代器
红黑树的迭代器比较像我们的list的迭代器,它们同样不是连续的物理地址空间
template<class T, class Ref, class Ptr>
struct __RBTree_iterator
{
typedef RBTreeNode<T> Node;
typedef __RBTree_iterator<T, Ref, Ptr> self;
Node* _node;
};
我们还是写一个结构体,重载它的操作符
对于迭代器来说解引用一定会返回这个节点的值,对于K模型来说就是K,对于K/V模型来说就是pair ->操作符同样道理,只有指针才会有->操作,所以我们要返回的是节点的地址
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;
}
接下来就是++和-- 我们先来看++
假如我们的迭代器现在指向8,按照中序遍历的规则,它的下一个元素就是10,它是8的右子树的最左节点
而如果我们的迭代器指向7呢?
就需要我们去寻找祖先里面孩子不是祖先的右的那个
self& operator++()
{
if(_node->_right)
{
Node* cur = _node-> _right;
while(cur->_left)
{
cur = cur->_left;
}
_node = cur;
}
else
{
Node* parent = _node->_parent;
Node* cur = _node;
while(parent && cur == parent->_right)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
对于--就完全跟++相反
self& operator--()
{
if(_node->_left)
{
Node* cur = _node-> _left;
while(cur->_right)
{
cur = cur->_right;
}
_node = cur;
}
else
{
Node* parent = _node->_parent;
Node* cur = _node;
while(parent && cur == parent->_left)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
红黑树迭代器实现
template<class T, class Ref, class Ptr>
struct __RBTree_iterator
{
typedef RBTreeNode<T> Node;
typedef __RBTree_iterator<T, Ref, Ptr> self;
Node* _node;
__RBTree_iterator(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* parent = _node->_parent;
Node* cur = _node;
while(parent && cur == parent->_right)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
self& operator--()
{
if(_node->_left)
{
Node* cur = _node-> _left;
while(cur->_right)
{
cur = cur->_right;
}
_node = cur;
}
else
{
Node* parent = _node->_parent;
Node* cur = _node;
while(parent && cur == parent->_left)
{
cur = 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是中序遍历的最后一个节点的下一个节点,也就是nullptr
typedef __RBTree_iterator<T, T&, T*> iterator;
typedef __RBTree_iterator<T, const T&, const T*> const_iterator;
iterator begin()
{
Node* left = _root;
while (left && left->_left)
{
left = left->_left;
}
return iterator(left);
}
const_iterator begin() const
{
Node* left = _root;
while (left && left->_left)
{
left = left->_left;
}
return iterator(left);
}
iterator end()
{
return iterator(nullptr);
}
const_iterator end() const
{
return iterator(nullptr);
}
最后就剩下insert的修改了
insert就是将返回值修改为pair,再根据不同的情况返回不同的值
如果已经存在这个值了,再插入就返回该元素迭代器和false组成的pair
没有这个值,就插入再返回该元素迭代器和true组成的pair
pair<iterator, bool> insert(const T& data)
{
KeyOfT k2t;
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK;
return make_pair(iterator(_root), true);
}
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
if (k2t(cur->_data) < k2t(data))
{
parent = cur;
cur = cur->_right;
}
else if (k2t(cur->_data) > k2t(data))
{
parent = cur;
cur = cur->_left;
}
else
{
return make_pair(iterator(cur), false);
}
}
cur = new Node(data);
Node* newNode = cur;
cur->_col = RED;
if (k2t(parent->_data) < k2t(data))
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
cur->_parent = parent;
while (parent && parent->_col == RED)
{
Node* grandfather = parent->_parent;
assert(grandfather);
assert(grandfather->_col == BLACK);
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
/* g
* p
* c
*/
if (cur == parent->_left)
{
RotateR(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
/* g
* p u
* c
*/
else
{
RotateL(parent);
RotateR(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
else
{
Node* uncle = grandfather->_left;
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
/* g
* p
* c
*/
if (cur == parent->_right)
{
RotateL(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
/* g
* u p
* c
*/
else
{
RotateR(parent);
RotateL(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
}
}
}
_root->_col = BLACK;
return make_pair(iterator(newNode), true);
}
三、set、map的实现
set和map的底层都是红黑树,我们只要将红黑树稍微修改就可以实现set和map了
但是这里有一个问题,set是K的模型map是K/V的模型,它是两棵树,难道我们要写两棵红黑树,一个是K的模型,一个是K/V的模型吗?
其实并不需要,我们查看一下stl源码的实现
我们发现它的红黑树的参数T,set传的是K,map传的是一个pair这样就完美的解决了到底是K的模型还是K/V的模型的问题了。不过在我们find和insert的时候又会有其他的问题了,我们查找时,因为是红黑树,所以我们需要节点存的值进行比较,可是对于set来说还好直接比较K
但是map的T是一个pair,虽然pair库中已经帮我们实
1、具体结构
对于set和map而言,我们只需要封装红黑树的迭代器和insert就好了,set和map内部其实什么都没有,就好像栈和队列一样
#include "RBTree.hpp"
template<class K>
class set
{
public:
private:
RBTree<K, K, K2T> _t;
};
template<class K, class V>
class map
{
public:
private:
RBTree<K, pair<K, V>, K2T> _m;
};
这就是最简单的
2、仿函数
根据是map还是set设计出的仿函数是不同的,不过都是返回K
//set仿函数
struct K2T
{
const K& operator()(const K& key)
{
return key;
}
};
//map仿函数
struct K2T
{
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
3、insert
insert其实特别的简单,我们只需要调用红黑树的insert就可以了
//set
pair<iterator, bool> insert(const K& key)
{
_t.insert(key);
}
//map
pair<iterator, bool> insert(const pair<K, V>& kv)
{
return _m.insert(kv);
}
4、迭代器
同理调用红黑树的
iterator begin()
{
return _t.begin();
}
const_iterator begin() const
{
return _t.begin();
}
iterator end()
{
return _t.end();
}
const_iterator end() const
{
return _t.end();
}
5、operator[ ]
这个是map独有的,我们前面已经介绍了原理,所以我们直接拿出代码
V& operator[](const K& key)
{
pair<iterator, bool> ret = insert(make_pair(key, V()));
return ret.first->second;
}
四、完整代码
//RBTree.hpp
#pragma once
#include <iostream>
#include <utility>
#include <cassert>
#include <ctime>
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)
{}
};
template<class T, class Ref, class Ptr>
struct __RBTree_iterator
{
typedef RBTreeNode<T> Node;
typedef __RBTree_iterator<T, Ref, Ptr> self;
Node* _node;
__RBTree_iterator(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* parent = _node->_parent;
Node* cur = _node;
while(parent && cur == parent->_right)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
self& operator--()
{
if(_node->_left)
{
Node* cur = _node-> _left;
while(cur->_right)
{
cur = cur->_right;
}
_node = cur;
}
else
{
Node* parent = _node->_parent;
Node* cur = _node;
while(parent && cur == parent->_left)
{
cur = 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;
}
};
template<class K, class T, class KeyOfT>
class RBTree
{
typedef RBTreeNode<T> Node;
public:
typedef __RBTree_iterator<T, T&, T*> iterator;
typedef __RBTree_iterator<T, const T&, const T*> const_iterator;
iterator begin()
{
Node* left = _root;
while (left && left->_left)
{
left = left->_left;
}
return iterator(left);
}
const_iterator begin() const
{
Node* left = _root;
while (left && left->_left)
{
left = left->_left;
}
return iterator(left);
}
iterator end()
{
return iterator(nullptr);
}
const_iterator end() const
{
return iterator(nullptr);
}
pair<iterator, bool> insert(const T& data)
{
KeyOfT k2t;
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK;
return make_pair(iterator(_root), true);
}
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
if (k2t(cur->_data) < k2t(data))
{
parent = cur;
cur = cur->_right;
}
else if (k2t(cur->_data) > k2t(data))
{
parent = cur;
cur = cur->_left;
}
else
{
return make_pair(iterator(cur), false);
}
}
cur = new Node(data);
Node* newNode = cur;
cur->_col = RED;
if (k2t(parent->_data) < k2t(data))
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
cur->_parent = parent;
while (parent && parent->_col == RED)
{
Node* grandfather = parent->_parent;
assert(grandfather);
assert(grandfather->_col == BLACK);
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
/* g
* p
* c
*/
if (cur == parent->_left)
{
RotateR(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
/* g
* p u
* c
*/
else
{
RotateL(parent);
RotateR(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
else
{
Node* uncle = grandfather->_left;
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
/* g
* p
* c
*/
if (cur == parent->_right)
{
RotateL(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
/* g
* u p
* c
*/
else
{
RotateR(parent);
RotateL(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
}
}
}
_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 (_root == parent)
{
_root = subR;
subR->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
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 (_root == parent)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subL;
}
else
{
ppNode->_right = subL;
}
subL->_parent = ppNode;
}
}
Node* _root = nullptr;
};
//set.hpp
#pragma once
#include "RBTree.hpp"
template<class K>
class set
{
struct K2T
{
const K& operator()(const K& key)
{
return key;
}
};
public:
typedef typename RBTree<K, K, K2T>::iterator iterator;
typedef typename RBTree<K, K, K2T>::const_iterator const_iterator;
iterator begin()
{
return _t.begin();
}
const_iterator begin() const
{
return _t.begin();
}
iterator end()
{
return _t.end();
}
const_iterator end() const
{
return _t.end();
}
pair<iterator, bool> insert(const K& key)
{
_t.insert(key);
}
private:
RBTree<K, K, K2T> _t;
};
void test_set()
{
set<int> s;
s.insert(23);
s.insert(34);
s.insert(23);
s.insert(67);
s.insert(235);
s.insert(12);
s.insert(45);
s.insert(98);
s.insert(245);
s.insert(2333);
s.insert(123);
set<int>::iterator it = s.begin();
while(it != s.end())
{
cout << *it << " ";
++it;
}
cout << endl;
}
//map.hpp
#pragma once
#include "RBTree.hpp"
template<class K, class V>
class map
{
struct K2T
{
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
public:
typedef typename RBTree<K, pair<K, V>, K2T>::iterator iterator;
typedef typename RBTree<K, pair<K, V>, K2T>::const_iterator const_iterator;
iterator begin()
{
return _m.begin();
}
const_iterator begin() const
{
return _m.begin();
}
iterator end()
{
return _m.end();
}
const_iterator end() const
{
return _m.end();
}
pair<iterator, bool> insert(const pair<K, V>& kv)
{
return _m.insert(kv);
}
V& operator[](const K& key)
{
pair<iterator, bool> ret = insert(make_pair(key, V()));
return ret.first->second;
}
private:
RBTree<K, pair<K, V>, K2T> _m;
};
void test_map()
{
string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
map<string, int> countMap;
for (auto& str : arr)
{
countMap[str]++;
}
map<string, int>::iterator it = countMap.begin();
while (it != countMap.end())
{
cout << it->first << ":" << it->second << endl;
++it;
}
cout << endl;
for (auto& kv : countMap)
{
cout << kv.first << ":" << kv.second << endl;
}
}