• C++之Map与Set的模拟实现


    前言:看这篇博客前首先得看博主关于红黑树的实现:C++之红黑树_cls-evd的博客-CSDN博客

    目录

    前言:看这篇博客前首先得看博主关于红黑树的实现:C++之红黑树_cls-evd的博客-CSDN博客

    一、set与map的源码分析

    源码中的set:

    ​编辑源码中的map:​编辑源码中的红黑树:​编辑

    二、map与set的建立

    三、红黑树节点的修改

    四、红黑树的修改

    insert的修改

    五、迭代器的实现

    迭代器的大框架

    begin的实现

    end的实现 

    operator++的实现

    operator--的实现

    operator[] 的实现(针对于map)

    六、红黑树成员函数的实现

    拷贝构造的实现

    拷贝构造的注意事项

    赋值运算符的实现

    总结及代码

    问题:map/set既然是对红黑树的封装,那么他俩为啥不是适配器?

    完整代码 


    一、set与map的源码分析

    map是kv结构,set的key结构,但是它俩的底层都是红黑树,那么我们实现它俩的时候是应该实现一红黑棵树呢?还是应该用两棵树?如果用一棵树该如何控制kv与k呢?但是如果使用两棵树代码又是冗余的,该如何解决呢?基于当前的原因我们可以看一看源码。

    源码中的set:

    源码中的map:源码中的红黑树:

    源码中是只有一颗红黑树的,它实现两个结构的容器的奥秘就在红黑树的节点

    这个容器是set还是map取决于节点里面存的是key还是pair

    我们就根据源码的思想进行实现。

    二、map与set的建立

    三、红黑树节点的修改

    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. , _col(RED) //红的黑的都无所谓
    14. , _data(data)
    15. {}
    16. };

    四、红黑树的修改

    insert的修改

    (1)原本我们插入的是pair现在都要换成data,最终目的就是实现复用

    (2)同样的insert的比较也就不能使用了,因为现在我们比较的是data。如果data是key没有任何问题,但是如果data是pair我们该如何解决呢? 

    虽然这里不进行修改也不会报错,因为pair本身就支持比较大小,但是pair的比较大小不符合我们的意义 ,pair的小于的定义是first和second有一个小就可以。但是遇到pair我们期望的是只利用pair里面的first比较大小。解决该问题的关键就是源码中红黑树的keyOfValue模板参数。它的作用就是如果你传过来的是key直接返回key,如果你传过来的是pair返回pair的first,由此进行比较,这个模板参数的本质就是一个仿函数。

    我们自己实现的叫:keyOfT

    相应的map与set建立对应的keyOfT结构体,通过重载()实现返回key或者返回kv.first

     

    红黑树中则通过创建keyOfT的一个对象,这个对象的operator()就可以把他们的值给取出来。

    目前为止set与map的插入就实现好了。

    五、迭代器的实现

    实际上set与map的迭代器就是红黑树的迭代器,所以我们实现出红黑树的迭代器即可。 

    迭代器的大框架

    1. template<class T, class Ref, class Ptr>
    2. struct RBTreeIterator
    3. {
    4. typedef RBTreeNode<T> Node;
    5. typedef RBTreeIterator<T, Ref, Ptr> Self;
    6. Node* _node;
    7. RBTreeIterator(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. }
    21. bool operator!=(const Self& s)
    22. {
    23. return _node != s._node;
    24. }
    25. //Self& operator--()
    26. //{
    27. //}
    28. };

    红黑树中就需要typedef一个迭代器

    begin的实现

    begin就是最左节点

    1. iterator begin()
    2. {
    3. Node* min = _root;
    4. while (min && min->_left) //最左节点
    5. {
    6. min = min->_left;
    7. }
    8. return iterator(min);//构造一个迭代器
    9. }

    end的实现 

    1. iterator end()
    2. {
    3. return iterator(nullptr); //end也就是最后一个数据的下一个位置,这里我们用nullptr替代
    4. }

    operator++的实现

    1.如果右子树不为空,中序的下一个就是右子树的最左节点
    2.如果右子树是空,说明我所在的子树已经访问完了,如果我是父亲的左边,下一个访问的就是父亲。如果我是父亲的右,说明一中序已经完了,我就要访问我父亲的父亲。
    所以我就要沿着根路径,找孩子是父亲左的祖先。直到父亲为空
    因为它有三叉链才能这样不借助栈

    1. //前置++
    2. Self& operator ++()
    3. {
    4. if (_node->_right) //访问右子树的最左节点
    5. {
    6. Node* min = _node->_right;
    7. while (min->_left)
    8. {
    9. min = min->_left;
    10. }
    11. _node = min;
    12. }
    13. else
    14. {
    15. Node* cur = _node;
    16. Node* parent = cur->_parent;
    17. while (parent && cur == parent->_right) //parent是进判断根节点的
    18. {
    19. cur = cur->_parent;
    20. parent = parent->_parent;
    21. }
    22. _node = parent;
    23. }
    24. return *this;
    25. }

    operator--的实现

    1. Self& operator--()
    2. {
    3. //右根左,左树不为空就访问左树的最右节点,左树为空就去访问祖先里面
    4. if (_node->_left)
    5. {
    6. Node* max = _node->_left;
    7. while (max->_right)
    8. {
    9. max = max->_right;
    10. }
    11. _node = max;
    12. }
    13. else
    14. {
    15. Node* cur = _node;
    16. Node* parent = cur->_parent;
    17. while (parent&&cur==parent->_left)
    18. {
    19. cur = cur->_parent;
    20. parent = parent->_parent;
    21. }
    22. _node = parent;
    23. }
    24. return *this;
    25. }

    Find的实现

    map/set对Find进行一次封装就是find

    1. iterator Find(const K& key)
    2. {
    3. Node* cur = _root;
    4. KeyOfT kot;
    5. while (cur)
    6. {
    7. if (kot(cur->_data) < key)
    8. {
    9. cur = cur->_right;
    10. }
    11. else if (kot(cur->_data) > key)
    12. {
    13. cur = cur->_left;
    14. }
    15. else
    16. {
    17. return iterator(cur);
    18. }
    19. }
    20. return end();
    21. }

    operator[] 的实现(针对于map)

    首先改造一个插入。将插入的返回值设置为pair,并且跟据相应的规则,如果插入成功返回新插入的节点,如果插入失败返回当前节点。 

    [ ]的实现:

    返回map中的value,ret就是pair<iterator,bool>,pair的first就是iterator,map的iterator就是pair<key,value>。V()会调用V对应的默认构造函数。

    1. V& operator[](const K& key)
    2. {
    3. auto ret = _t.Insert(make_pair(key, V()));
    4. return ret.first->second;
    5. }

    执行结果: 

    六、红黑树成员函数的实现

    拷贝构造的实现

    这里我们没写拷贝构造发现拷贝成功了,是不是就意味着不需要我们再写了呢?

    现在是一个浅拷贝,没有在这里崩溃就是因为我们没写析构函数,析构两次才会崩溃的。

    当我们实现好红黑树的析构以后,自然而然的也就崩溃了

    所以我们得自己实现深拷贝。

    深拷贝实现的思路就是递归的去拷贝,同时要注意我们这里是三叉链要进行链接parent,颜色也需要我们进行拷贝。

    1. RBTree(const RBTree<K, T, KeyOfT>& t)
    2. {
    3. _root = Copy(t._root);
    4. }
    5. Node* Copy(Node* root)
    6. {
    7. if (root == nullptr)
    8. {
    9. return nullptr;
    10. }
    11. Node* newRoot = new Node(root->_data);
    12. newRoot->_col = root->_col;
    13. newRoot->_left = Copy(root->_left);
    14. newRoot->_right = Copy(root->_right);
    15. if (newRoot->_left)
    16. {
    17. newRoot->_left->_parent = newRoot;
    18. }
    19. if (newRoot->_right)
    20. {
    21. newRoot->_right->_parent = newRoot;
    22. }
    23. return newRoot;
    24. }

    这下我们的拷贝构造就没有问题了

    拷贝构造的注意事项

    1.不能去调用红黑树叶子节点的拷贝构造

    new这里用的就是拷贝构造,我们的节点没有写拷贝构造会调用默认的,又因为我们节点中定义的全是指针,全是内置类型,都会进行拷贝

    结果看似正确,但是实际这棵树已经非常的乱了。

     我们以根放的左子树为例

    copy这棵树唯独parent没有进行深拷贝还是进行了浅拷贝,因此copy这个数的祖先和s这个数的祖先一模一样,这种问题很难被发现,尤其是当你进行插入的时候,如果你往copy这个树插入节点你就会惊奇的发现新插入的节点居然出现在了s这棵树上。

    赋值运算符的实现

    1. RBTree<K, T, KeyOfT>& operator =(RBTree<K, T, KeyOfT>& t)
    2. {
    3. swap(_root, t._root);
    4. return *this;
    5. }

    empty()接口的实现

    红黑树为空返回0,不为空返回1

    1. bool Empty()const
    2. {
    3. if (_root == nullptr)
    4. return false;
    5. return true;
    6. }

    size()接口的实现

    返回红黑树总结点的个数

    1. size_t Size()const
    2. {
    3. return SizeNode(_root);
    4. }
    5. size_t SizeNode(Node* root) const
    6. {
    7. if (root == nullptr)
    8. {
    9. return 0;
    10. }
    11. return SizeNode(root->_left) + SizeNode(root->_right) + 1;
    12. }

    clear()接口的实现 

    将树中的节点全都清理掉

    1. void Clear()
    2. {
    3. Destroy(_root);
    4. _root = nullptr;
    5. }
    6. void Destroy(Node* root)
    7. {
    8. if (root == nullptr)
    9. {
    10. return;
    11. }
    12. Destroy(root->_left);
    13. Destroy(root->_right);
    14. delete root;
    15. }

    总结及代码

    map和set就是依靠我们的红黑树实现的,它俩本身就是一个空壳子,就是再对红黑树进行封装。我们同时发现map与set我们都没有进行实现成员函数都用的是默认的成员函数,因为红黑树是set/map里面的自定义类型.eg:我们去调用set/map的构造,但是set/map没有写构造就会调用他们的默认构造函数,默认构造函数对于自定义类型就会去调用红黑树的构造。

    总之默认生成的成员函数就会去调用红黑树成员函数。

    问题:map/set既然是对红黑树的封装,那么他俩为啥不是适配器?

    stack/queue/priority_queue 封装的是deque/vector 他们是适配器,而map/set 封住的是红黑树 他们就不是不是适配器

    这里以stack和map为例

    关键点就在于这个Container,它是可以进行任意替换的,但是map/set就不存在这样的一个Container,简单来说就是stack的底层能改,但是map的底层是改不了的。所以map/set就不是适配器。     

    完整代码 

    RBTree.h

    1. #pragma once
    2. #include<iostream>
    3. #include<vector>
    4. using namespace std;
    5. enum Colour
    6. {
    7. RED,
    8. BLACK
    9. };
    10. template<class T>
    11. struct RBTreeNode
    12. {
    13. RBTreeNode<T>* _left;
    14. RBTreeNode<T>* _right;
    15. RBTreeNode<T>* _parent;
    16. T _data;
    17. Colour _col;
    18. RBTreeNode(const T& data)
    19. :_left(nullptr)
    20. , _right(nullptr)
    21. , _parent(nullptr)
    22. , _col(RED) //红的黑的都无所谓
    23. , _data(data)
    24. {}
    25. };
    26. template<class T, class Ref, class Ptr>
    27. struct RBTreeIterator
    28. {
    29. typedef RBTreeNode<T> Node;
    30. typedef RBTreeIterator<T, Ref, Ptr> Self;
    31. RBTreeIterator(Node* node) //只需要构造函数,迭代器没什么资源要去释放,一个迭代器赋值给另外一个迭代器只需要浅拷贝就可
    32. :_node(node)
    33. {}
    34. Ref operator*() //返回里面的数据
    35. {
    36. return _node->_data;
    37. }
    38. Ptr operator->() //返回地址
    39. {
    40. return &(_node->_data);
    41. }
    42. //前置++
    43. Self& operator ++()
    44. {
    45. Increament();
    46. return *this;
    47. }
    48. Self operator++(int)
    49. {
    50. Self tmp(*this);
    51. Increament();
    52. return tmp;
    53. }
    54. Self& operator--()
    55. {
    56. DeIncreament();
    57. return *this;
    58. }
    59. Self operator--(int)
    60. {
    61. Self tmp(*this);
    62. DeIncreament();
    63. return tmp;
    64. }
    65. bool operator!=(const Self& s) const
    66. {
    67. return _node != s._node;
    68. }
    69. bool operator==(const Self& s) const
    70. {
    71. return _node == s._node;
    72. }
    73. private:
    74. void Increament()
    75. {
    76. if (_node->_right) //访问右子树的最左节点
    77. {
    78. Node* min = _node->_right;
    79. while (min->_left)
    80. {
    81. min = min->_left;
    82. }
    83. _node = min;
    84. }
    85. else
    86. {
    87. Node* cur = _node;
    88. Node* parent = cur->_parent;
    89. while (parent && cur == parent->_right) //parent是进判断根节点的
    90. {
    91. cur = cur->_parent;
    92. parent = parent->_parent;
    93. }
    94. _node = parent;
    95. }
    96. }
    97. void DeIncreament()
    98. {
    99. //右根左,左树不为空就访问左树的最右节点,左树为空就去访问祖先里面
    100. if (_node->_left)
    101. {
    102. Node* max = _node->_left;
    103. while (max->_right)
    104. {
    105. max = max->_right;
    106. }
    107. _node = max;
    108. }
    109. else
    110. {
    111. Node* cur = _node;
    112. Node* parent = cur->_parent;
    113. while (parent && cur == parent->_left)
    114. {
    115. cur = cur->_parent;
    116. parent = parent->_parent;
    117. }
    118. _node = parent;
    119. }
    120. }
    121. Node* _node; //迭代器就是一个节点的指针
    122. };
    123. //set RBTree<K,K,MapKeyOfT>
    124. //map RBTree<K,pair<K,V>,MapKeyOfT>
    125. template<class K, class T, class KeyOfT>
    126. struct RBTree
    127. {
    128. typedef RBTreeNode<T> Node;
    129. public:
    130. typedef RBTreeIterator<T, T&, T*> iterator;
    131. typedef RBTreeIterator<T, const T&, const T*> const_iterator;
    132. iterator begin()
    133. {
    134. Node* min = _root;
    135. while (min && min->_left) //最左节点
    136. {
    137. min = min->_left;
    138. }
    139. return iterator(min);//构造一个迭代器
    140. }
    141. iterator end()
    142. {
    143. return iterator(nullptr); //end也就是最后一个数据的下一个位置,这里我们用nullptr替代
    144. }
    145. iterator Find(const K& key)
    146. {
    147. Node* cur = _root;
    148. KeyOfT kot;
    149. while (cur)
    150. {
    151. if (kot(cur->_data) < key)
    152. {
    153. cur = cur->_right;
    154. }
    155. else if (kot(cur->_data) > key)
    156. {
    157. cur = cur->_left;
    158. }
    159. else
    160. {
    161. return iterator(cur);
    162. }
    163. }
    164. return end();
    165. }
    166. bool Empty()const
    167. {
    168. if (_root == nullptr)
    169. return false;
    170. return true;
    171. }
    172. size_t Size()const
    173. {
    174. return SizeNode(_root);
    175. }
    176. void Clear()
    177. {
    178. Destroy(_root);
    179. _root = nullptr;
    180. }
    181. RBTree()
    182. :_root(nullptr)
    183. {}
    184. RBTree(const RBTree<K, T, KeyOfT>& t)
    185. {
    186. _root = Copy(t._root);
    187. }
    188. RBTree<K, T, KeyOfT>& operator =(RBTree<K, T, KeyOfT>& t)
    189. {
    190. swap(_root, t._root);
    191. return *this;
    192. }
    193. ~RBTree()
    194. {
    195. Destroy(_root);
    196. _root = nullptr;
    197. }
    198. pair<iterator, bool> Insert(const T& data) //如果是set T就是key,如果是map,T就是pair
    199. {
    200. if (_root == nullptr)
    201. {
    202. _root = new Node(data);
    203. _root->_col = BLACK; //将根节点处理成黑色
    204. return make_pair(iterator(_root), true);
    205. }
    206. KeyOfT kot;
    207. Node* parent = nullptr;
    208. Node* cur = _root;
    209. while (cur)
    210. {
    211. if (kot(cur->_data) < kot(data))
    212. {
    213. parent = cur;
    214. cur = cur->_right;
    215. }
    216. else if (kot(cur->_data) > kot(data))
    217. {
    218. parent = cur;
    219. cur = cur->_left;
    220. }
    221. else
    222. {
    223. return make_pair(iterator(cur), false);
    224. }
    225. }
    226. cur = new Node(data);
    227. Node* newnode = cur;
    228. cur->_col = RED; //新增节点处理成红色
    229. if (kot(parent->_data) < kot(data))
    230. {
    231. parent->_right = cur;
    232. cur->_parent = parent; //把三叉链链上
    233. }
    234. else
    235. {
    236. parent->_left = cur;
    237. cur->_parent = parent;
    238. }
    239. //控制平衡
    240. while (parent&& parent->_col == RED) //父亲存在且为红一定不是根
    241. {
    242. Node* grangfather = parent->_parent;
    243. if (parent == grangfather->_left) //父亲在g的左
    244. {
    245. Node* uncle = grangfather->_right;
    246. if (uncle && uncle->_col == RED)//情况一:叔叔存在且为红
    247. {
    248. //变色+继续向上处理
    249. parent->_col = uncle->_col = BLACK;
    250. grangfather->_col = RED;
    251. cur = grangfather;
    252. parent = cur->_parent;
    253. }
    254. else //情况二+三:叔叔存在/叔叔存在且为黑
    255. {
    256. // g
    257. // p
    258. //c
    259. // g
    260. // p
    261. // c
    262. if (cur == parent->_left) //情况二
    263. {
    264. //单旋
    265. RotateR(grangfather);
    266. parent->_col = BLACK;
    267. grangfather->_col = RED;
    268. }
    269. else //情况三
    270. {
    271. //双旋
    272. RotateL(parent);
    273. RotateR(grangfather);
    274. cur->_col = BLACK;
    275. grangfather->_col = RED;
    276. }
    277. break; //我这棵树旋转完成了后,每条路径黑节点的个数没变,不会影响其他路径,这棵字树的根已经是黑色了,与情况一不同
    278. }
    279. }
    280. else//parent == grangfather->_right p在g的右
    281. {
    282. Node* uncle = grangfather->_left;
    283. if (uncle && uncle->_col == RED)//情况一:叔叔存在且为红
    284. {
    285. //变色+继续向上处理
    286. parent->_col = uncle->_col = BLACK;
    287. grangfather->_col = RED;
    288. cur = grangfather;
    289. parent = cur->_parent;
    290. }
    291. else //情况二+三:叔叔存在/叔叔存在且为黑
    292. {
    293. // g
    294. // p
    295. // c
    296. // g
    297. // p
    298. // c
    299. if (cur == parent->_right) //情况二
    300. {
    301. RotateL(grangfather);
    302. parent->_col = BLACK;
    303. grangfather->_col = RED;
    304. }
    305. else //情况三
    306. {
    307. RotateR(parent);
    308. RotateL(grangfather);
    309. cur->_col = BLACK;
    310. grangfather->_col = RED;
    311. }
    312. break; //我这棵树旋转完成了后,每条路径黑节点的个数没变,不会影响其他路径,这棵字树的根已经是黑色了,与情况一不同
    313. }
    314. }
    315. }
    316. _root->_col = BLACK;
    317. return make_pair(iterator(newnode), true);
    318. }
    319. private:
    320. void Destroy(Node* root)
    321. {
    322. if (root == nullptr)
    323. {
    324. return;
    325. }
    326. Destroy(root->_left);
    327. Destroy(root->_right);
    328. delete root;
    329. }
    330. Node* Copy(Node* root)
    331. {
    332. if (root == nullptr)
    333. {
    334. return nullptr;
    335. }
    336. Node* newRoot = new Node(root->_data);
    337. newRoot->_col = root->_col;
    338. newRoot->_left = Copy(root->_left);
    339. newRoot->_right = Copy(root->_right);
    340. //增加上三叉连的链接关系
    341. if (newRoot->_left)
    342. {
    343. newRoot->_left->_parent = newRoot;
    344. }
    345. if (newRoot->_right)
    346. {
    347. newRoot->_right->_parent = newRoot;
    348. }
    349. return newRoot;
    350. }
    351. size_t SizeNode(Node* root) const
    352. {
    353. if (root == nullptr)
    354. {
    355. return 0;
    356. }
    357. return SizeNode(root->_left) + SizeNode(root->_right) + 1;
    358. }
    359. void RotateR(Node* parent)
    360. {
    361. Node* subL = parent->_left;
    362. Node* subLR = subL->_right;
    363. parent->_left = subLR;
    364. if (subLR) //不为空才链接,否则就出现空指针问题
    365. {
    366. subLR->_parent = parent;
    367. }
    368. Node* parentParent = parent->_parent; //提前记录一下parent的父亲
    369. subL->_right = parent;
    370. parent->_parent = subL;
    371. if (parent == _root) //如果是一颗独立的树
    372. {
    373. _root = subL;
    374. _root->_parent = nullptr;
    375. }
    376. else
    377. {
    378. if (parentParent->_left == parent) //改变parent父亲的链接
    379. {
    380. parentParent->_left = subL;
    381. }
    382. else
    383. {
    384. parentParent->_right = subL;
    385. }
    386. subL->_parent = parentParent; //注意三叉链接
    387. }
    388. }
    389. void RotateL(Node* parent)
    390. {
    391. Node* subR = parent->_right;
    392. Node* subRL = subR->_left;
    393. parent->_right = subRL;
    394. if (subRL)
    395. {
    396. subRL->_parent = parent;
    397. }
    398. Node* parentParent = parent->_parent;
    399. subR->_left = parent;
    400. parent->_parent = subR;
    401. if (parent == _root)
    402. {
    403. _root = subR;
    404. _root->_parent = nullptr;
    405. }
    406. else
    407. {
    408. if (parentParent->_left == parent)
    409. {
    410. parentParent->_left = subR;
    411. }
    412. else
    413. {
    414. parentParent->_right = subR;
    415. }
    416. subR->_parent = parentParent;
    417. }
    418. }
    419. private:
    420. Node* _root; //内置类型
    421. };

    MySet.h

    1. #pragma once
    2. #include"RBTree.h"
    3. namespace pxl
    4. {
    5. template<class K>
    6. class set
    7. {
    8. public:
    9. struct SetKeyOfT
    10. {
    11. const K& operator()(const K& k)
    12. {
    13. return k;
    14. }
    15. };
    16. typedef typename RBTree<K, K, SetKeyOfT>::iterator iterator;
    17. iterator begin()
    18. {
    19. return _t.begin();
    20. }
    21. iterator end()
    22. {
    23. return _t.end();
    24. }
    25. pair<iterator, bool> insert(const K& key)
    26. {
    27. return _t.Insert(key);
    28. }
    29. iterator find(const K& key)
    30. {
    31. return _t.Find(key);
    32. }
    33. bool empty()const
    34. {
    35. return _t.Empty();
    36. }
    37. size_t size()const
    38. {
    39. return _t.Size();
    40. }
    41. void clear()
    42. {
    43. _t.Clear();
    44. }
    45. private:
    46. RBTree<K, K, SetKeyOfT> _t; //自定义类型,调用它的拷贝构造,但是红黑树的拷贝构造也没写
    47. //红黑树是set/map里面的自定义类型,我们去调用set的构造,但是set没有写构造,就会去调用红黑树的构造
    48. //总之默认生成的成员函数就会去调用红黑树成员函数
    49. };
    50. void test_set()
    51. {
    52. set<int> s;
    53. s.insert(1);
    54. s.insert(4);
    55. s.insert(2);
    56. s.insert(6);
    57. set<int>::iterator it = s.begin();
    58. while (it != s.end())
    59. {
    60. cout << *it <<" ";
    61. ++it;
    62. }
    63. cout << endl;
    64. set<int> copy(s);
    65. for (auto e : copy)
    66. {
    67. cout << e << " ";
    68. }
    69. }
    70. }

    MyMap.h

    1. #pragma once
    2. #include"RBTree.h"
    3. namespace pxl
    4. {
    5. template<class K, class V>
    6. class map
    7. {
    8. public:
    9. struct MapKeyOfT
    10. {
    11. const K& operator()(const pair<K, V>& kv)
    12. {
    13. return kv.first;
    14. }
    15. };
    16. typedef typename RBTree<K, pair<K, V>, MapKeyOfT>::iterator iterator;
    17. //对类模板里面的内嵌类型进行typedef
    18. iterator begin()
    19. {
    20. return _t.begin();
    21. }
    22. iterator end()
    23. {
    24. return _t.end();
    25. }
    26. pair<iterator, bool> insert(const pair<K, V>& kv)
    27. {
    28. return _t.Insert(kv);
    29. }
    30. iterator find(const K& key)
    31. {
    32. return _t.Find(key);
    33. }
    34. V& operator[](const K& key)
    35. {
    36. auto ret = _t.Insert(make_pair(key, V()));
    37. return ret.first->second;
    38. }
    39. bool empty()const
    40. {
    41. return _t.Empty();
    42. }
    43. size_t size()const
    44. {
    45. return _t.Size();
    46. }
    47. void clear()
    48. {
    49. _t.Clear();
    50. }
    51. private:
    52. RBTree<K, pair<K, V>, MapKeyOfT> _t;
    53. };
    54. void test_map()
    55. {
    56. map<int, int> m;
    57. m.insert(make_pair(3, 3));
    58. m.insert(make_pair(5, 5));
    59. m.insert(make_pair(1, 1));
    60. m.insert(make_pair(8, 8));
    61. m[7];
    62. m[8] = 88;
    63. map<int,int>::iterator it = m.begin();
    64. while (it != m.end())
    65. {
    66. cout << it->first << ":" << it->second << endl;
    67. ++it;
    68. }
    69. cout << endl;
    70. }
    71. }

  • 相关阅读:
    终极篇章1——(16000字)SpringBoot启动原理分析(第一部分)
    Talk预告 | 北京大学杨灵:扩散生成模型的方法、关联与应用
    C++ STL标准模板库(一)
    Python基本功
    策略模式实现方式之Map<K,Function>
    Hyperf基础使用
    阿里在开源领域又有哪些新动向?来首届阿里开源开放周找答案!
    实时语音通讯技术:多人通话和语音识别
    K8S的控制器Deployment,ReplicaSet,StatefulSet,CronJob,最小单位pod
    【C语言进阶】文件操作(二)
  • 原文地址:https://blog.csdn.net/qq_52433890/article/details/124942770