赞
踩
目录
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
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的引用 (插入+修改)
红黑树基本代码:
- #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
红黑树的迭代器比较像我们的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是K的模型map是K/V的模型,它是两棵树,难道我们要写两棵红黑树,一个是K的模型,一个是K/V的模型吗?
其实并不需要,我们查看一下stl源码的实现
我们发现它的红黑树的参数T,set传的是K,map传的是一个pair这样就完美的解决了到底是K的模型还是K/V的模型的问题了。不过在我们find和insert的时候又会有其他的问题了,我们查找时,因为是红黑树,所以我们需要节点存的值进行比较,可是对于set来说还好直接比较K
但是map的T是一个pair,虽然pair库中已经帮我们实
对于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;
- };
这就是最简单的
根据是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;
- }
- };
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);
- }
-
-
-
同理调用红黑树的
- iterator begin()
- {
- return _t.begin();
- }
-
- const_iterator begin() const
- {
- return _t.begin();
- }
-
- iterator end()
- {
- return _t.end();
- }
-
- const_iterator end() const
- {
- return _t.end();
- }
这个是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;
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。