当前位置:   article > 正文

【C++】set和map_c++ set map

c++ set map

目录

一、set、map的介绍

1、set的介绍

2、map的介绍

二、红黑树的实现

1、具体框架

2、迭代器

三、set、map的实现

1、具体结构

2、仿函数

3、insert

4、迭代器

5、operator[ ]

四、完整代码


一、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的遍历特征是有序+去重

  1. #include <iostream>
  2. #include <set>
  3. using namespace std;
  4. void test_set1()
  5. {
  6. int a[] = {1, 2, 1, 6, 3, 8, 5};
  7. set<int> s(a, a + sizeof(a) / sizeof(int));
  8. for(const auto& e : s)
  9. {
  10. cout << e << endl;
  11. }
  12. }
  13. int main()
  14. {
  15. test_set1();
  16. return 0;
  17. }

 

 

接下来就是set的删除了

  1. void test_set1()
  2. {
  3. int a[] = {1, 2, 1, 6, 3, 8, 5};
  4. set<int> s(a, a + sizeof(a) / sizeof(int));
  5. for(const auto& e : s)
  6. {
  7. cout << e << " ";
  8. }
  9. s.erase(30);
  10. for(const auto& e : s)
  11. {
  12. cout << e << " ";
  13. }
  14. set<int>::iterator pos = s.find(20);
  15. s.erase(pos);
  16. for(const auto& e : s)
  17. {
  18. cout << e << " ";
  19. }
  20. }

 我们发现上面我写了两种删除,那么这两种删除方式有什么区别吗?

我们先编译运行一下,我们先屏蔽掉下面删除20的代码

发现是没有任何问题的,我们寻找30,set中没有30它也不会报错,也不会删除

接下来我们使用下面的删除逻辑

 

然后我们发现他就崩了原因是:我们查找20,find没有找到它会返回end,然后我们删除end时,end指向的是最后一个元素的下一个位置,我们把它删除了,程序就会崩溃

这就是两种删除方式的区别。

正确做法

 

  1. set<int>::iterator pos = s.find(20);
  2. if(pos != s.end())
  3. {
  4. s.erase(pos);
  5. }
  6. for(const auto& e : s)
  7. {
  8. cout << e << " ";
  9. }

 

 

接下来是count这个函数,它会返回某元素的个数,对于set来说是没有用的,set内部相同元素个数就是1,没有就是0

 这个接口是为了保持接口一致性,主要是给multiset来使用的

multiset和set用法类似,不过就是允许键值冗余的现象存在

  1. void test_multiset()
  2. {
  3. int a[] = {1, 2, 1, 6, 3, 8, 5};
  4. multiset<int> ms(a, a + sizeof(a) / sizeof(int));
  5. for(const auto& e : ms)
  6. {
  7. cout << e << " ";
  8. }
  9. cout << endl;
  10. cout << ms.count(1) << endl;
  11. }

 

这时我们再调用count,1的个数就变成了2

2、map的介绍

map与set也十分的相似,map是K/V的模型,set是K的模型

map也有两种

区别与set和multiset相同,只是键值是否允许冗余的差别

不过map的插入就比较特别了

 

我们发现insert的参数是一个value_type类型

 

然后我们发现它实际上是一个pair

  1. template <class T1, class T2>
  2. struct pair
  3. {
  4. typedef T1 first_type;
  5. typedef T2 second_type;
  6. T1 first;
  7. T2 second;
  8. pair(): first(T1()), second(T2())
  9. {}
  10. pair(const T1& a, const T2& b): first(a), second(b)
  11. {}
  12. };

 pair又叫做键值对:用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。比如:现在要建立一个英汉互译的字典,那该字典中必然有英文单词与其对应的中文含义,而且,英文单词与其中文含义是一一对应的关系,即通过该应该单词,在词典中就可以找到与其对应的中文含义。

也就是说我们每次插入时传入一个键值对

  1. map<string, string> countMap;
  2. 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的默认构造

  1. void test_map()
  2. {
  3. string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
  4. "苹果", "香蕉", "苹果", "香蕉" };
  5. map<string, int> countMap;
  6. for(const auto& e : arr)
  7. {
  8. countMap[e]++;
  9. }
  10. for(const auto& e : countMap)
  11. {
  12. cout << e.first << " : " << e.second << endl;
  13. }
  14. }

 

这与我们的预期一致,最开始的时候map中什么元素都没有,正常调用[ ]一定会崩,他没有崩并且还将其插入了。

总结:

1、map中有这个key,返回value的引用 (查找,修改value)

2、map中没有这个key,会插入一个pair(key, V()),返回value的引用  (插入+修改) 

二、红黑树的实现

1、具体框架

红黑树基本代码:

  1. #pragma once
  2. #include <iostream>
  3. #include <utility>
  4. #include <cassert>
  5. #include <ctime>
  6. using namespace std;
  7. enum Colour
  8. {
  9. RED,
  10. BLACK
  11. };
  12. template<class K,class V>
  13. struct RBTreeNode
  14. {
  15. RBTreeNode<K, V>* _left;
  16. RBTreeNode<K, V>* _right;
  17. RBTreeNode<K, V>* _parent;
  18. pair<const K, V> _kv;
  19. Colour _col;
  20. RBTreeNode(const pair<const K,V>& kv)
  21. :_left(nullptr)
  22. ,_right(nullptr)
  23. ,_parent(nullptr)
  24. ,_kv(kv)
  25. {}
  26. };
  27. template<class K,class V>
  28. class RBTree
  29. {
  30. typedef RBTreeNode<K, V> Node;
  31. public:
  32. bool insert(const pair<const K, V> kv)
  33. {
  34. if (_root == nullptr)
  35. {
  36. _root = new Node(kv);
  37. _root->_col = BLACK;
  38. return true;
  39. }
  40. Node* cur = _root;
  41. Node* parent = nullptr;
  42. while (cur)
  43. {
  44. if (cur->_kv.first < kv.first)
  45. {
  46. parent = cur;
  47. cur = cur->_right;
  48. }
  49. else if (cur->_kv.first > kv.first)
  50. {
  51. parent = cur;
  52. cur = cur->_left;
  53. }
  54. else
  55. {
  56. return false;
  57. }
  58. }
  59. cur = new Node(kv);
  60. cur->_col = RED;
  61. if (parent->_kv.first < kv.first)
  62. {
  63. parent->_right = cur;
  64. }
  65. else
  66. {
  67. parent->_left = cur;
  68. }
  69. cur->_parent = parent;
  70. //�����ڵ���ɫ
  71. //�ߵ��ջ��߸��׵���ɫ�Ǻ�ɫ����ֹͣ����
  72. while (parent && parent->_col == RED)
  73. {
  74. Node* grandfather = parent->_parent;
  75. assert(grandfather);
  76. assert(grandfather->_col == BLACK);
  77. if (parent == grandfather->_left)
  78. {
  79. Node* uncle = grandfather->_right;
  80. if (uncle && uncle->_col == RED)
  81. {
  82. parent->_col = uncle->_col = BLACK;
  83. grandfather->_col = RED;
  84. cur = grandfather;
  85. parent = cur->_parent;
  86. }
  87. else
  88. {
  89. /* g
  90. * p
  91. * c
  92. */
  93. if (cur == parent->_left)
  94. {
  95. RotateR(grandfather);
  96. parent->_col = BLACK;
  97. grandfather->_col = RED;
  98. }
  99. /* g
  100. * p u
  101. * c
  102. */
  103. else
  104. {
  105. RotateL(parent);
  106. RotateR(grandfather);
  107. cur->_col = BLACK;
  108. grandfather->_col = RED;
  109. }
  110. break;
  111. }
  112. }
  113. else
  114. {
  115. Node* uncle = grandfather->_left;
  116. if (uncle && uncle->_col == RED)
  117. {
  118. parent->_col = uncle->_col = BLACK;
  119. grandfather->_col = RED;
  120. cur = grandfather;
  121. parent = cur->_parent;
  122. }
  123. else
  124. {
  125. /* g
  126. * p
  127. * c
  128. */
  129. if (cur == parent->_right)
  130. {
  131. RotateL(grandfather);
  132. parent->_col = BLACK;
  133. grandfather->_col = RED;
  134. }
  135. /* g
  136. * u p
  137. * c
  138. */
  139. else
  140. {
  141. RotateR(parent);
  142. RotateL(grandfather);
  143. cur->_col = BLACK;
  144. grandfather->_col = RED;
  145. }
  146. }
  147. }
  148. }
  149. _root->_col = BLACK;
  150. return true;
  151. }
  152. void InOrder()
  153. {
  154. _InOrder(_root);
  155. }
  156. bool IsBalance()
  157. {
  158. int benchmark = 0;
  159. return _PrevCheck(_root, 0, benchmark);
  160. }
  161. private:
  162. bool _PrevCheck(Node* root, int blackNum, int& benchmark)
  163. {
  164. if (root == nullptr)
  165. {
  166. if (benchmark == 0)
  167. {
  168. benchmark = blackNum;
  169. return true;
  170. }
  171. if (blackNum != benchmark)
  172. {
  173. cout << "��ɫ�ڵ�����ͬ" << endl;
  174. return false;
  175. }
  176. else
  177. {
  178. return true;
  179. }
  180. }
  181. if (root->_col == BLACK)
  182. {
  183. blackNum++;
  184. }
  185. if (root->_col == RED && root->_parent->_col == RED)
  186. {
  187. cout << "�������ĺ�ɫ�ڵ�" << endl;
  188. return false;
  189. }
  190. return _PrevCheck(root->_left, blackNum, benchmark)
  191. && _PrevCheck(root->_right, blackNum, benchmark);
  192. }
  193. void _InOrder(Node* root)
  194. {
  195. if (root == nullptr)
  196. {
  197. return;
  198. }
  199. _InOrder(root->_left);
  200. cout << root->_kv.first << " : " << root->_kv.second << endl;
  201. _InOrder(root->_right);
  202. }
  203. void RotateL(Node* parent)
  204. {
  205. Node* subR = parent->_right;
  206. Node* subRL = subR->_left;
  207. parent->_right = subRL;
  208. if (subRL)
  209. {
  210. subRL->_parent = parent;
  211. }
  212. Node* ppNode = parent->_parent;
  213. subR->_left = parent;
  214. parent->_parent = subR;
  215. if (_root == parent)
  216. {
  217. _root = subR;
  218. subR->_parent = nullptr;
  219. }
  220. else
  221. {
  222. if (ppNode->_left == parent)
  223. {
  224. ppNode->_left = subR;
  225. }
  226. else
  227. {
  228. ppNode->_right = subR;
  229. }
  230. subR->_parent = ppNode;
  231. }
  232. }
  233. void RotateR(Node* parent)
  234. {
  235. Node* subL = parent->_left;
  236. Node* subLR = subL->_right;
  237. parent->_left = subLR;
  238. if (subLR)
  239. {
  240. subLR->_parent = parent;
  241. }
  242. Node* ppNode = parent->_parent;//��¼parent��parent����ת���֮������
  243. subL->_right = parent;
  244. parent->_parent = subL;
  245. if (_root == parent)
  246. {
  247. _root = subL;
  248. subL->_parent = nullptr;
  249. }
  250. else
  251. {
  252. if (ppNode->_left == parent)
  253. {
  254. ppNode->_left = subL;
  255. }
  256. else
  257. {
  258. ppNode->_right = subL;
  259. }
  260. subL->_parent = ppNode;
  261. }
  262. }
  263. Node* _root = nullptr;
  264. };
  265. void testRBTree()
  266. {
  267. int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
  268. RBTree<int, int> rb;
  269. /*for (const auto& it : a)
  270. {
  271. rb.insert(make_pair(it, it));
  272. }*/
  273. //rb.InOrder();
  274. const size_t N = 100000;
  275. srand(time(0));
  276. for (size_t i = 0; i < N; i++)
  277. {
  278. int x = rand();
  279. cout << x << endl;
  280. rb.insert(make_pair(x, x));
  281. }
  282. cout << rb.IsBalance() << endl;
  283. }

我们前面已经实现了红黑树的基本功能,接下来就是我们将红黑树封装一下,让它能够既能是K模型也可以是K/V模型,并且给它加上迭代器


使两种模型都能够存在,我们就要将上述的红黑树的节点存储一个模板T

T可以是K也可以是pair,这就解决了一部分问题,接下来的问题就是我们要插入节点,一定会需要进行比较,我们无法区分pair和K,虽然pair库中已经帮我们实现了<和>但是,这种实现方式并不是我们想要的

 

我们的map是只比较pair的第一个元素,库中实现的无法满足我们的需求,我们只好借助与仿函数来实现,我们使用仿函数来获取pair的第一个元素,仿函数的具体实现我们并不关系

  1. template<class T>
  2. struct RBTreeNode
  3. {
  4. RBTreeNode<T>* _left;
  5. RBTreeNode<T>* _right;
  6. RBTreeNode<T>* _parent;
  7. T _data;
  8. Colour _col;
  9. RBTreeNode(const T& data)
  10. :_left(nullptr)
  11. ,_right(nullptr)
  12. ,_parent(nullptr)
  13. ,_data(data)
  14. {}
  15. };

树的节点内容已经变更为data

2、迭代器

红黑树的迭代器比较像我们的list的迭代器,它们同样不是连续的物理地址空间

  1. template<class T, class Ref, class Ptr>
  2. struct __RBTree_iterator
  3. {
  4. typedef RBTreeNode<T> Node;
  5. typedef __RBTree_iterator<T, Ref, Ptr> self;
  6. Node* _node;
  7. };

我们还是写一个结构体,重载它的操作符

对于迭代器来说解引用一定会返回这个节点的值,对于K模型来说就是K,对于K/V模型来说就是pair    ->操作符同样道理,只有指针才会有->操作,所以我们要返回的是节点的地址

  1. Ref operator*()
  2. {
  3. return _node->_data;
  4. }
  5. Ptr operator->()
  6. {
  7. return &_node->_data;
  8. }

接下来是=操作符重载和 != 操作符重载,这两个操作符十分的重要,遍历容器时一定会用上

  1. bool operator!=(const self& s) const
  2. {
  3. return _node != s._node;
  4. }
  5. bool operator==(const self& s) const
  6. {
  7. return _node == s._node;
  8. }

接下来就是++和--  我们先来看++

假如我们的迭代器现在指向8,按照中序遍历的规则,它的下一个元素就是10,它是8的右子树的最左节点

而如果我们的迭代器指向7呢?

就需要我们去寻找祖先里面孩子不是祖先的右的那个

  1. self& operator++()
  2. {
  3. if(_node->_right)
  4. {
  5. Node* cur = _node-> _right;
  6. while(cur->_left)
  7. {
  8. cur = cur->_left;
  9. }
  10. _node = cur;
  11. }
  12. else
  13. {
  14. Node* parent = _node->_parent;
  15. Node* cur = _node;
  16. while(parent && cur == parent->_right)
  17. {
  18. cur = cur->_parent;
  19. parent = parent->_parent;
  20. }
  21. _node = parent;
  22. }
  23. return *this;
  24. }

对于--就完全跟++相反

  1. self& operator--()
  2. {
  3. if(_node->_left)
  4. {
  5. Node* cur = _node-> _left;
  6. while(cur->_right)
  7. {
  8. cur = cur->_right;
  9. }
  10. _node = cur;
  11. }
  12. else
  13. {
  14. Node* parent = _node->_parent;
  15. Node* cur = _node;
  16. while(parent && cur == parent->_left)
  17. {
  18. cur = cur->_parent;
  19. parent = parent->_parent;
  20. }
  21. _node = parent;
  22. }
  23. return *this;
  24. }

红黑树迭代器实现

  1. template<class T, class Ref, class Ptr>
  2. struct __RBTree_iterator
  3. {
  4. typedef RBTreeNode<T> Node;
  5. typedef __RBTree_iterator<T, Ref, Ptr> self;
  6. Node* _node;
  7. __RBTree_iterator(Node* node)
  8. :_node(node)
  9. {}
  10. Ref operator*()
  11. {
  12. return _node->_data;
  13. }
  14. Ptr operator->()
  15. {
  16. return &_node->_data;
  17. }
  18. self& operator++()
  19. {
  20. if(_node->_right)
  21. {
  22. Node* cur = _node-> _right;
  23. while(cur->_left)
  24. {
  25. cur = cur->_left;
  26. }
  27. _node = cur;
  28. }
  29. else
  30. {
  31. Node* parent = _node->_parent;
  32. Node* cur = _node;
  33. while(parent && cur == parent->_right)
  34. {
  35. cur = cur->_parent;
  36. parent = parent->_parent;
  37. }
  38. _node = parent;
  39. }
  40. return *this;
  41. }
  42. self& operator--()
  43. {
  44. if(_node->_left)
  45. {
  46. Node* cur = _node-> _left;
  47. while(cur->_right)
  48. {
  49. cur = cur->_right;
  50. }
  51. _node = cur;
  52. }
  53. else
  54. {
  55. Node* parent = _node->_parent;
  56. Node* cur = _node;
  57. while(parent && cur == parent->_left)
  58. {
  59. cur = cur->_parent;
  60. parent = parent->_parent;
  61. }
  62. _node = parent;
  63. }
  64. return *this;
  65. }
  66. bool operator!=(const self& s) const
  67. {
  68. return _node != s._node;
  69. }
  70. bool operator==(const self& s) const
  71. {
  72. return _node == s._node;
  73. }
  74. };

接下来回到红黑树的整体框架

红黑树的begin一定是返回中序遍历的第一个节点,也就是我们的最左节点(如果最左节点存在) 

红黑树的end是中序遍历的最后一个节点的下一个节点,也就是nullptr

  1. typedef __RBTree_iterator<T, T&, T*> iterator;
  2. typedef __RBTree_iterator<T, const T&, const T*> const_iterator;
  3. iterator begin()
  4. {
  5. Node* left = _root;
  6. while (left && left->_left)
  7. {
  8. left = left->_left;
  9. }
  10. return iterator(left);
  11. }
  12. const_iterator begin() const
  13. {
  14. Node* left = _root;
  15. while (left && left->_left)
  16. {
  17. left = left->_left;
  18. }
  19. return iterator(left);
  20. }
  21. iterator end()
  22. {
  23. return iterator(nullptr);
  24. }
  25. const_iterator end() const
  26. {
  27. return iterator(nullptr);
  28. }

最后就剩下insert的修改了

insert就是将返回值修改为pair,再根据不同的情况返回不同的值

如果已经存在这个值了,再插入就返回该元素迭代器和false组成的pair

没有这个值,就插入再返回该元素迭代器和true组成的pair

  1. pair<iterator, bool> insert(const T& data)
  2. {
  3. KeyOfT k2t;
  4. if (_root == nullptr)
  5. {
  6. _root = new Node(data);
  7. _root->_col = BLACK;
  8. return make_pair(iterator(_root), true);
  9. }
  10. Node* cur = _root;
  11. Node* parent = nullptr;
  12. while (cur)
  13. {
  14. if (k2t(cur->_data) < k2t(data))
  15. {
  16. parent = cur;
  17. cur = cur->_right;
  18. }
  19. else if (k2t(cur->_data) > k2t(data))
  20. {
  21. parent = cur;
  22. cur = cur->_left;
  23. }
  24. else
  25. {
  26. return make_pair(iterator(cur), false);
  27. }
  28. }
  29. cur = new Node(data);
  30. Node* newNode = cur;
  31. cur->_col = RED;
  32. if (k2t(parent->_data) < k2t(data))
  33. {
  34. parent->_right = cur;
  35. }
  36. else
  37. {
  38. parent->_left = cur;
  39. }
  40. cur->_parent = parent;
  41. while (parent && parent->_col == RED)
  42. {
  43. Node* grandfather = parent->_parent;
  44. assert(grandfather);
  45. assert(grandfather->_col == BLACK);
  46. if (parent == grandfather->_left)
  47. {
  48. Node* uncle = grandfather->_right;
  49. if (uncle && uncle->_col == RED)
  50. {
  51. parent->_col = uncle->_col = BLACK;
  52. grandfather->_col = RED;
  53. cur = grandfather;
  54. parent = cur->_parent;
  55. }
  56. else
  57. {
  58. /* g
  59. * p
  60. * c
  61. */
  62. if (cur == parent->_left)
  63. {
  64. RotateR(grandfather);
  65. parent->_col = BLACK;
  66. grandfather->_col = RED;
  67. }
  68. /* g
  69. * p u
  70. * c
  71. */
  72. else
  73. {
  74. RotateL(parent);
  75. RotateR(grandfather);
  76. cur->_col = BLACK;
  77. grandfather->_col = RED;
  78. }
  79. break;
  80. }
  81. }
  82. else
  83. {
  84. Node* uncle = grandfather->_left;
  85. if (uncle && uncle->_col == RED)
  86. {
  87. parent->_col = uncle->_col = BLACK;
  88. grandfather->_col = RED;
  89. cur = grandfather;
  90. parent = cur->_parent;
  91. }
  92. else
  93. {
  94. /* g
  95. * p
  96. * c
  97. */
  98. if (cur == parent->_right)
  99. {
  100. RotateL(grandfather);
  101. parent->_col = BLACK;
  102. grandfather->_col = RED;
  103. }
  104. /* g
  105. * u p
  106. * c
  107. */
  108. else
  109. {
  110. RotateR(parent);
  111. RotateL(grandfather);
  112. cur->_col = BLACK;
  113. grandfather->_col = RED;
  114. }
  115. }
  116. }
  117. }
  118. _root->_col = BLACK;
  119. return make_pair(iterator(newNode), true);
  120. }

三、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内部其实什么都没有,就好像栈和队列一样

  1. #include "RBTree.hpp"
  2. template<class K>
  3. class set
  4. {
  5. public:
  6. private:
  7. RBTree<K, K, K2T> _t;
  8. };

  1. template<class K, class V>
  2. class map
  3. {
  4. public:
  5. private:
  6. RBTree<K, pair<K, V>, K2T> _m;
  7. };

这就是最简单的

2、仿函数

根据是map还是set设计出的仿函数是不同的,不过都是返回K

  1. //set仿函数
  2. struct K2T
  3. {
  4. const K& operator()(const K& key)
  5. {
  6. return key;
  7. }
  8. };

  1. //map仿函数
  2. struct K2T
  3. {
  4. const K& operator()(const pair<K, V>& kv)
  5. {
  6. return kv.first;
  7. }
  8. };

3、insert

insert其实特别的简单,我们只需要调用红黑树的insert就可以了

  1. //set
  2. pair<iterator, bool> insert(const K& key)
  3. {
  4. _t.insert(key);
  5. }
  6. //map
  7. pair<iterator, bool> insert(const pair<K, V>& kv)
  8. {
  9. return _m.insert(kv);
  10. }

4、迭代器

同理调用红黑树的

  1. iterator begin()
  2. {
  3. return _t.begin();
  4. }
  5. const_iterator begin() const
  6. {
  7. return _t.begin();
  8. }
  9. iterator end()
  10. {
  11. return _t.end();
  12. }
  13. const_iterator end() const
  14. {
  15. return _t.end();
  16. }

5、operator[ ]

这个是map独有的,我们前面已经介绍了原理,所以我们直接拿出代码

  1. V& operator[](const K& key)
  2. {
  3. pair<iterator, bool> ret = insert(make_pair(key, V()));
  4. return ret.first->second;
  5. }

四、完整代码

  1. //RBTree.hpp
  2. #pragma once
  3. #include <iostream>
  4. #include <utility>
  5. #include <cassert>
  6. #include <ctime>
  7. using namespace std;
  8. enum Colour
  9. {
  10. RED,
  11. BLACK
  12. };
  13. template<class T>
  14. struct RBTreeNode
  15. {
  16. RBTreeNode<T>* _left;
  17. RBTreeNode<T>* _right;
  18. RBTreeNode<T>* _parent;
  19. T _data;
  20. Colour _col;
  21. RBTreeNode(const T& data)
  22. :_left(nullptr)
  23. ,_right(nullptr)
  24. ,_parent(nullptr)
  25. ,_data(data)
  26. {}
  27. };
  28. template<class T, class Ref, class Ptr>
  29. struct __RBTree_iterator
  30. {
  31. typedef RBTreeNode<T> Node;
  32. typedef __RBTree_iterator<T, Ref, Ptr> self;
  33. Node* _node;
  34. __RBTree_iterator(Node* node)
  35. :_node(node)
  36. {}
  37. Ref operator*()
  38. {
  39. return _node->_data;
  40. }
  41. Ptr operator->()
  42. {
  43. return &_node->_data;
  44. }
  45. self& operator++()
  46. {
  47. if(_node->_right)
  48. {
  49. Node* cur = _node-> _right;
  50. while(cur->_left)
  51. {
  52. cur = cur->_left;
  53. }
  54. _node = cur;
  55. }
  56. else
  57. {
  58. Node* parent = _node->_parent;
  59. Node* cur = _node;
  60. while(parent && cur == parent->_right)
  61. {
  62. cur = cur->_parent;
  63. parent = parent->_parent;
  64. }
  65. _node = parent;
  66. }
  67. return *this;
  68. }
  69. self& operator--()
  70. {
  71. if(_node->_left)
  72. {
  73. Node* cur = _node-> _left;
  74. while(cur->_right)
  75. {
  76. cur = cur->_right;
  77. }
  78. _node = cur;
  79. }
  80. else
  81. {
  82. Node* parent = _node->_parent;
  83. Node* cur = _node;
  84. while(parent && cur == parent->_left)
  85. {
  86. cur = cur->_parent;
  87. parent = parent->_parent;
  88. }
  89. _node = parent;
  90. }
  91. return *this;
  92. }
  93. bool operator!=(const self& s) const
  94. {
  95. return _node != s._node;
  96. }
  97. bool operator==(const self& s) const
  98. {
  99. return _node == s._node;
  100. }
  101. };
  102. template<class K, class T, class KeyOfT>
  103. class RBTree
  104. {
  105. typedef RBTreeNode<T> Node;
  106. public:
  107. typedef __RBTree_iterator<T, T&, T*> iterator;
  108. typedef __RBTree_iterator<T, const T&, const T*> const_iterator;
  109. iterator begin()
  110. {
  111. Node* left = _root;
  112. while (left && left->_left)
  113. {
  114. left = left->_left;
  115. }
  116. return iterator(left);
  117. }
  118. const_iterator begin() const
  119. {
  120. Node* left = _root;
  121. while (left && left->_left)
  122. {
  123. left = left->_left;
  124. }
  125. return iterator(left);
  126. }
  127. iterator end()
  128. {
  129. return iterator(nullptr);
  130. }
  131. const_iterator end() const
  132. {
  133. return iterator(nullptr);
  134. }
  135. pair<iterator, bool> insert(const T& data)
  136. {
  137. KeyOfT k2t;
  138. if (_root == nullptr)
  139. {
  140. _root = new Node(data);
  141. _root->_col = BLACK;
  142. return make_pair(iterator(_root), true);
  143. }
  144. Node* cur = _root;
  145. Node* parent = nullptr;
  146. while (cur)
  147. {
  148. if (k2t(cur->_data) < k2t(data))
  149. {
  150. parent = cur;
  151. cur = cur->_right;
  152. }
  153. else if (k2t(cur->_data) > k2t(data))
  154. {
  155. parent = cur;
  156. cur = cur->_left;
  157. }
  158. else
  159. {
  160. return make_pair(iterator(cur), false);
  161. }
  162. }
  163. cur = new Node(data);
  164. Node* newNode = cur;
  165. cur->_col = RED;
  166. if (k2t(parent->_data) < k2t(data))
  167. {
  168. parent->_right = cur;
  169. }
  170. else
  171. {
  172. parent->_left = cur;
  173. }
  174. cur->_parent = parent;
  175. while (parent && parent->_col == RED)
  176. {
  177. Node* grandfather = parent->_parent;
  178. assert(grandfather);
  179. assert(grandfather->_col == BLACK);
  180. if (parent == grandfather->_left)
  181. {
  182. Node* uncle = grandfather->_right;
  183. if (uncle && uncle->_col == RED)
  184. {
  185. parent->_col = uncle->_col = BLACK;
  186. grandfather->_col = RED;
  187. cur = grandfather;
  188. parent = cur->_parent;
  189. }
  190. else
  191. {
  192. /* g
  193. * p
  194. * c
  195. */
  196. if (cur == parent->_left)
  197. {
  198. RotateR(grandfather);
  199. parent->_col = BLACK;
  200. grandfather->_col = RED;
  201. }
  202. /* g
  203. * p u
  204. * c
  205. */
  206. else
  207. {
  208. RotateL(parent);
  209. RotateR(grandfather);
  210. cur->_col = BLACK;
  211. grandfather->_col = RED;
  212. }
  213. break;
  214. }
  215. }
  216. else
  217. {
  218. Node* uncle = grandfather->_left;
  219. if (uncle && uncle->_col == RED)
  220. {
  221. parent->_col = uncle->_col = BLACK;
  222. grandfather->_col = RED;
  223. cur = grandfather;
  224. parent = cur->_parent;
  225. }
  226. else
  227. {
  228. /* g
  229. * p
  230. * c
  231. */
  232. if (cur == parent->_right)
  233. {
  234. RotateL(grandfather);
  235. parent->_col = BLACK;
  236. grandfather->_col = RED;
  237. }
  238. /* g
  239. * u p
  240. * c
  241. */
  242. else
  243. {
  244. RotateR(parent);
  245. RotateL(grandfather);
  246. cur->_col = BLACK;
  247. grandfather->_col = RED;
  248. }
  249. }
  250. }
  251. }
  252. _root->_col = BLACK;
  253. return make_pair(iterator(newNode), true);
  254. }
  255. private:
  256. void RotateL(Node* parent)
  257. {
  258. Node* subR = parent->_right;
  259. Node* subRL = subR->_left;
  260. parent->_right = subRL;
  261. if (subRL)
  262. {
  263. subRL->_parent = parent;
  264. }
  265. Node* ppNode = parent->_parent;
  266. subR->_left = parent;
  267. parent->_parent = subR;
  268. if (_root == parent)
  269. {
  270. _root = subR;
  271. subR->_parent = nullptr;
  272. }
  273. else
  274. {
  275. if (ppNode->_left == parent)
  276. {
  277. ppNode->_left = subR;
  278. }
  279. else
  280. {
  281. ppNode->_right = subR;
  282. }
  283. subR->_parent = ppNode;
  284. }
  285. }
  286. void RotateR(Node* parent)
  287. {
  288. Node* subL = parent->_left;
  289. Node* subLR = subL->_right;
  290. parent->_left = subLR;
  291. if (subLR)
  292. {
  293. subLR->_parent = parent;
  294. }
  295. Node* ppNode = parent->_parent;
  296. subL->_right = parent;
  297. parent->_parent = subL;
  298. if (_root == parent)
  299. {
  300. _root = subL;
  301. subL->_parent = nullptr;
  302. }
  303. else
  304. {
  305. if (ppNode->_left == parent)
  306. {
  307. ppNode->_left = subL;
  308. }
  309. else
  310. {
  311. ppNode->_right = subL;
  312. }
  313. subL->_parent = ppNode;
  314. }
  315. }
  316. Node* _root = nullptr;
  317. };
  1. //set.hpp
  2. #pragma once
  3. #include "RBTree.hpp"
  4. template<class K>
  5. class set
  6. {
  7. struct K2T
  8. {
  9. const K& operator()(const K& key)
  10. {
  11. return key;
  12. }
  13. };
  14. public:
  15. typedef typename RBTree<K, K, K2T>::iterator iterator;
  16. typedef typename RBTree<K, K, K2T>::const_iterator const_iterator;
  17. iterator begin()
  18. {
  19. return _t.begin();
  20. }
  21. const_iterator begin() const
  22. {
  23. return _t.begin();
  24. }
  25. iterator end()
  26. {
  27. return _t.end();
  28. }
  29. const_iterator end() const
  30. {
  31. return _t.end();
  32. }
  33. pair<iterator, bool> insert(const K& key)
  34. {
  35. _t.insert(key);
  36. }
  37. private:
  38. RBTree<K, K, K2T> _t;
  39. };
  40. void test_set()
  41. {
  42. set<int> s;
  43. s.insert(23);
  44. s.insert(34);
  45. s.insert(23);
  46. s.insert(67);
  47. s.insert(235);
  48. s.insert(12);
  49. s.insert(45);
  50. s.insert(98);
  51. s.insert(245);
  52. s.insert(2333);
  53. s.insert(123);
  54. set<int>::iterator it = s.begin();
  55. while(it != s.end())
  56. {
  57. cout << *it << " ";
  58. ++it;
  59. }
  60. cout << endl;
  61. }

  1. //map.hpp
  2. #pragma once
  3. #include "RBTree.hpp"
  4. template<class K, class V>
  5. class map
  6. {
  7. struct K2T
  8. {
  9. const K& operator()(const pair<K, V>& kv)
  10. {
  11. return kv.first;
  12. }
  13. };
  14. public:
  15. typedef typename RBTree<K, pair<K, V>, K2T>::iterator iterator;
  16. typedef typename RBTree<K, pair<K, V>, K2T>::const_iterator const_iterator;
  17. iterator begin()
  18. {
  19. return _m.begin();
  20. }
  21. const_iterator begin() const
  22. {
  23. return _m.begin();
  24. }
  25. iterator end()
  26. {
  27. return _m.end();
  28. }
  29. const_iterator end() const
  30. {
  31. return _m.end();
  32. }
  33. pair<iterator, bool> insert(const pair<K, V>& kv)
  34. {
  35. return _m.insert(kv);
  36. }
  37. V& operator[](const K& key)
  38. {
  39. pair<iterator, bool> ret = insert(make_pair(key, V()));
  40. return ret.first->second;
  41. }
  42. private:
  43. RBTree<K, pair<K, V>, K2T> _m;
  44. };
  45. void test_map()
  46. {
  47. string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
  48. map<string, int> countMap;
  49. for (auto& str : arr)
  50. {
  51. countMap[str]++;
  52. }
  53. map<string, int>::iterator it = countMap.begin();
  54. while (it != countMap.end())
  55. {
  56. cout << it->first << ":" << it->second << endl;
  57. ++it;
  58. }
  59. cout << endl;
  60. for (auto& kv : countMap)
  61. {
  62. cout << kv.first << ":" << kv.second << endl;
  63. }
  64. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/570971?site
推荐阅读
相关标签
  

闽ICP备14008679号