• C++库函数——set与map的模拟实现


    目录

    1.红黑树的迭代器与改造

    ①红黑树的迭代器

    ②红黑树的改造

    2.map的模拟实现

    3.set的模拟实现

    4.测试


    1.红黑树的迭代器与改造

    ①红黑树的迭代器

    对于上面这棵红黑树,我们可以很容易得知道begin()是红黑树的最左节点,end()应该是一个空节点。即

    1. iterator begin()
    2. {
    3. Node* cur = _root;
    4. while (cur && cur->_left)
    5. {
    6. cur = cur->_left;
    7. }
    8. return cur;
    9. }
    10. iterator end()
    11. {
    12. return iterator(nullptr);
    13. }

     接下来定义iterator及其具体操作

    1. template<class T>
    2. struct RBTreeIterator
    3. {
    4. typedef RBTreeNode Node;
    5. typedef RBTreeIterator Self;
    6. RBTreeIterator(Node* node)
    7. : _node(node)
    8. {}
    9. // 让迭代器具有类似指针的行为
    10. T& operator*()
    11. {
    12. return _node->_data;
    13. }
    14. T* operator->()
    15. {
    16. return &_node->_data;
    17. }
    18. // 迭代器可以移动:前置/后置++
    19. Self& operator++()
    20. {
    21. // 这里的++是为了找到下一个比当前节点大的位置
    22. // 结合图像具体来看就是两种情况
    23. // 第一种是如果当前节点有右子树,
    24. // 那么下一个节点就是右子树中的最左节点
    25. // 第二种是如果当前节点没有右子树,
    26. // 那么下一个节点就是“当前节点是父亲的左子树”的节点
    27. // 如果不是的话就继续向上更新,直到更新到根节点
    28. if (_node->_right)
    29. {
    30. _node = _node->_right;
    31. while (_node->_left)
    32. {
    33. _node = _node->_left;
    34. }
    35. }
    36. else
    37. {
    38. Node* cur = _node;
    39. Node* parent = cur->_parent;
    40. while (parent && cur == parent->_right)
    41. {
    42. cur = parent;
    43. parent = parent->_parent;
    44. }
    45. if (parent && cur == parent->_left)
    46. _node = parent;
    47. else
    48. _node = nullptr;
    49. }
    50. return *this;
    51. }
    52. Self operator++(int)
    53. {
    54. Self tmp(*this);
    55. ++(*this);
    56. return tmp;
    57. }
    58. // 迭代器可以移动:前置/后置--
    59. Self& operator--()
    60. {
    61. // 这里的大致逻辑与++类似
    62. if (_node->_left)
    63. {
    64. _node = _node->_left;
    65. while (_node->_right)
    66. {
    67. _node = _node->_right;
    68. }
    69. }
    70. else
    71. {
    72. Node* cur = _node;
    73. Node* parent = cur->_parent;
    74. while (parent && cur == parent->_left)
    75. {
    76. cur = parent;
    77. parent = parent->_parent;
    78. }
    79. if (parent && cur == parent->_right)
    80. _node = parent;
    81. else
    82. _node = nullptr;
    83. }
    84. return *this;
    85. }
    86. Self operator--(int)
    87. {
    88. Self tmp(*this);
    89. --(*this);
    90. return tmp;
    91. }
    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. Node* _node;
    102. };

    ②红黑树的改造

    1. // set->RBTree _t;
    2. // map->RBTree, MapKeyOfT> _t;
    3. template<class K, class T, class KeyofT>
    4. class RBTree
    5. {
    6. public:
    7. typedef RBTreeNode Node;
    8. typedef RBTreeIterator iterator;
    9. typedef RBTreeIteratorconst T*, const T&> const_iterator;
    10. iterator begin()
    11. {
    12. Node* cur = _root;
    13. while (cur && cur->_left)
    14. {
    15. cur = cur->_left;
    16. }
    17. return (iterator)cur;
    18. }
    19. iterator end()
    20. {
    21. return iterator(nullptr);
    22. }
    23. const_iterator begin() const
    24. {
    25. Node* cur = _root;
    26. while (cur && cur->_left)
    27. {
    28. cur = cur->_left;
    29. }
    30. return (const_iterator)cur;
    31. }
    32. const_iterator end() const
    33. {
    34. return const_iterator(nullptr);
    35. }
    36. Node* Find(const T& data)
    37. {
    38. KeyofT kot;
    39. Node* cur = _root;
    40. while (cur)
    41. {
    42. if (kot(data) < kot(cur->_data))
    43. {
    44. cur = cur->_left;
    45. }
    46. else if (data > kot(cur->_data))
    47. {
    48. cur = cur->_right;
    49. }
    50. else
    51. {
    52. return cur;
    53. }
    54. }
    55. return nullptr;
    56. }
    57. pairbool> Insert(const T& data)
    58. {
    59. KeyofT kot;
    60. if (_root == nullptr)
    61. {
    62. _root = new Node(data);
    63. _root->_color = BLACK;
    64. return make_pair((iterator)_root, true);
    65. }
    66. Node* cur = _root;
    67. Node* parent = nullptr;
    68. // 寻找要插入的位置
    69. while (cur)
    70. {
    71. if (kot(data) < kot(cur->_data))
    72. {
    73. parent = cur;
    74. cur = cur->_left;
    75. }
    76. else if (kot(data) > kot(cur->_data))
    77. {
    78. parent = cur;
    79. cur = cur->_right;
    80. }
    81. else
    82. {
    83. return make_pair((iterator)cur, false);
    84. }
    85. }
    86. // 到此处cur已经指向了应该插入的位置,
    87. // 然后判断应该插入到parent的哪边
    88. cur = new Node(data);
    89. if (kot(data) > kot(parent->_data))
    90. {
    91. parent->_right = cur;
    92. }
    93. else
    94. {
    95. parent->_left = cur;
    96. }
    97. cur->_parent = parent;
    98. // 插入完成后判断一下
    99. // 若父节点是黑就无需调整
    100. // 而当父节点是红就需要进行调整
    101. while (parent && parent->_color == RED)
    102. {
    103. Node* grandpa = parent->_parent;
    104. if (parent == grandpa->_left)
    105. {
    106. Node* uncle = grandpa->_right;
    107. if (uncle && uncle->_color == RED)
    108. {
    109. uncle->_color = parent->_color = BLACK;
    110. grandpa->_color = RED;
    111. cur = grandpa;
    112. parent = cur->_parent;
    113. }
    114. else
    115. {
    116. if (uncle == nullptr)
    117. {
    118. if (parent->_left == cur)
    119. {
    120. // grandpa
    121. // parent
    122. //cur
    123. RotateR(grandpa);
    124. grandpa->_color = RED;
    125. parent->_color = BLACK;
    126. }
    127. else
    128. {
    129. // grandpa
    130. // parent
    131. // cur
    132. RotateL(parent);
    133. RotateR(grandpa);
    134. cur->_color = BLACK;
    135. grandpa->_color = RED;
    136. }
    137. }
    138. else // uncle存在且为黑
    139. {
    140. if (parent->_left == cur)
    141. {
    142. // grandpa
    143. // parent
    144. //cur
    145. RotateR(grandpa);
    146. grandpa->_color = RED;
    147. parent->_color = BLACK;
    148. }
    149. else
    150. {
    151. // grandpa
    152. // parent
    153. // cur
    154. RotateL(parent);
    155. RotateR(grandpa);
    156. cur->_color = BLACK;
    157. grandpa->_color = RED;
    158. }
    159. }
    160. break;
    161. }
    162. }
    163. else // parent == grandpa->_right
    164. {
    165. Node* uncle = grandpa->_left;
    166. if (uncle && uncle->_color == RED)
    167. {
    168. uncle->_color = parent->_color = BLACK;
    169. grandpa->_color = RED;
    170. cur = grandpa;
    171. parent = cur->_parent;
    172. }
    173. else
    174. {
    175. if (uncle == nullptr)
    176. {
    177. if (parent->_left == cur)
    178. {
    179. //grandpa
    180. // parent
    181. //cur
    182. RotateR(parent);
    183. RotateL(grandpa);
    184. cur->_color = BLACK;
    185. grandpa->_color = RED;
    186. }
    187. else
    188. {
    189. //grandpa
    190. // parent
    191. // cur
    192. RotateL(grandpa);
    193. grandpa->_color = RED;
    194. parent->_color = BLACK;
    195. }
    196. }
    197. else // uncle存在且为黑
    198. {
    199. if (parent->_left == cur)
    200. {
    201. //grandpa
    202. // parent
    203. //cur
    204. RotateR(parent);
    205. RotateL(grandpa);
    206. cur->_color = BLACK;
    207. grandpa->_color = RED;
    208. }
    209. else
    210. {
    211. //grandpa
    212. // parent
    213. // cur
    214. RotateL(grandpa);
    215. grandpa->_color = RED;
    216. parent->_color = BLACK;
    217. }
    218. }
    219. break;
    220. }
    221. }
    222. }
    223. if (cur->_parent == nullptr)
    224. {
    225. cur->_color = BLACK;
    226. }
    227. return make_pair((iterator)cur, true);
    228. }
    229. void RotateL(Node* parent)
    230. {
    231. Node* cur = parent->_right; // 记录当前节点
    232. Node* curleft = cur->_left; // 记录当前节点的左节点
    233. // 如果当前节点的左节点为空说明是h为0的情况
    234. // 不为空时就要进行节点间的连接
    235. if (curleft)
    236. {
    237. curleft->_parent = parent;
    238. }
    239. parent->_right = curleft;
    240. cur->_left = parent;
    241. // 此时需要确定parent是否属于子树
    242. if (parent == _root)
    243. {
    244. _root = cur;
    245. cur->_parent = nullptr;
    246. }
    247. else // 此时parent以下的节点属于子树
    248. {
    249. cur->_parent = parent->_parent;
    250. // 确认parent与其父节点间的关系
    251. // 然后将cur与parent的父节点连接起来
    252. if (parent->_parent->_left == parent)
    253. {
    254. parent->_parent->_left = cur;
    255. }
    256. else
    257. {
    258. parent->_parent->_right = cur;
    259. }
    260. }
    261. parent->_parent = cur;
    262. }
    263. void RotateR(Node* parent)
    264. {
    265. Node* cur = parent->_left; // 记录当前节点
    266. Node* curright = cur->_right; // 记录当前节点的右节点
    267. // 如果当前节点的右节点为空说明是h为0的情况
    268. // 不为空时就要进行节点间的连接
    269. if (curright)
    270. {
    271. curright->_parent = parent;
    272. }
    273. parent->_left = curright;
    274. cur->_right = parent;
    275. // 此时需要确定parent是否属于子树
    276. if (parent == _root)
    277. {
    278. _root = cur;
    279. cur->_parent = nullptr;
    280. }
    281. else // 此时parent以下的节点属于子树
    282. {
    283. cur->_parent = parent->_parent;
    284. // 确认parent与其父节点间的关系
    285. // 然后将cur与parent的父节点连接起来
    286. if (parent->_parent->_left == parent)
    287. {
    288. parent->_parent->_left = cur;
    289. }
    290. else
    291. {
    292. parent->_parent->_right = cur;
    293. }
    294. }
    295. parent->_parent = cur;
    296. }
    297. private:
    298. Node* _root = nullptr;
    299. };

    2.map的模拟实现

    1. namespace my_map
    2. {
    3. template<class K, class V>
    4. class map
    5. {
    6. struct MapKeyOfT
    7. {
    8. const K& operator()(const pair& kv)
    9. {
    10. return kv.first;
    11. }
    12. };
    13. public:
    14. typedef typename RBTreeconst K, V>, MapKeyOfT>::iterator iterator;
    15. typedef typename RBTreeconst K, V>, MapKeyOfT>::const_iterator const_iterator;
    16. iterator begin()
    17. {
    18. return _t.begin();
    19. }
    20. iterator end()
    21. {
    22. return _t.end();
    23. }
    24. const_iterator begin() const
    25. {
    26. return _t.begin();
    27. }
    28. const_iterator end() const
    29. {
    30. return _t.end();
    31. }
    32. V& operator[](const K& key)
    33. {
    34. pairbool> ret = _t.Insert(make_pair(key, V()));
    35. return ret.first->second;
    36. }
    37. pairbool> insert(const pair& kv)
    38. {
    39. return _t.Insert(kv);
    40. }
    41. private:
    42. RBTreeconst K, V>, MapKeyOfT> _t;
    43. };
    44. }

    3.set的模拟实现

    1. namespace my_set
    2. {
    3. template<class K>
    4. class set
    5. {
    6. struct SetKeyOfT
    7. {
    8. const K& operator()(const K& key)
    9. {
    10. return key;
    11. }
    12. };
    13. public:
    14. typedef typename RBTree::const_iterator iterator;
    15. typedef typename RBTree::const_iterator const_iterator;
    16. const_iterator begin() const
    17. {
    18. return _t.begin();
    19. }
    20. const_iterator end() const
    21. {
    22. return _t.end();
    23. }
    24. // 使用iterator RBTree::const_iterator时,有
    25. // 无法从“std::pair,bool>”
    26. // 转换为“std::pair,bool>”
    27. // pair insert(const K& key)
    28. // {
    29. // return _t.Insert(key);
    30. // }
    31. pairbool> insert(const K& key)
    32. {
    33. // 将插入后的结果用一个key类型的pair接收
    34. pair<typename RBTree::iterator, bool> ret = _t.Insert(key);
    35. // 用ret的的元素构造key的特定pair
    36. // 目的:这里的iterator实际是const_iterator,
    37. // 转换之后可以使key的第一个元素不被修改
    38. return pairbool>(ret.first, ret.second);
    39. }
    40. private:
    41. RBTree _t;
    42. };
    43. }

    4.测试

    1. #include "my_map.h"
    2. #include
    3. #include
    4. #include "my_set.h"
    5. //int main()
    6. //{
    7. // RBTree> t;
    8. // for (int i = 0; i < 100; i++)
    9. // {
    10. // t.Insert(i);
    11. // }
    12. //
    13. // RBTree>::iterator it = t.begin();
    14. // while (it != t.end())
    15. // {
    16. // cout << *it << " ";
    17. // it++;
    18. // }
    19. //
    20. // return 0;
    21. //}
    22. //int main()
    23. //{
    24. // my_set::set st;
    25. // for (int i = 0; i < 10; i++)
    26. // {
    27. // st.insert(i);
    28. // }
    29. //
    30. // auto it = st.begin();
    31. // while (it != st.end())
    32. // {
    33. // cout << *it << " ";
    34. // ++it;
    35. // }
    36. //
    37. // return 0;
    38. //}
    39. //int main()
    40. //{
    41. // my_set::set st;
    42. // for (int i = 0; i < 10; i++)
    43. // {
    44. // st.insert(i);
    45. // }
    46. //
    47. // my_set::set::iterator it = st.begin();
    48. // while (it != st.end())
    49. // {
    50. // //if (*it % 2 == 0)
    51. // //{
    52. // // *it += 10;
    53. // //}
    54. // cout << *it << " ";
    55. // ++it;
    56. // }
    57. //
    58. // return 0;
    59. //}
    60. //int main()
    61. //{
    62. // my_map::map st;
    63. // string s1 = "a";
    64. // string s2 = "b";
    65. // for (int i = 0; i < 10; i++)
    66. // {
    67. // st.insert(make_pair(s1, s2));
    68. // s1[0]++;
    69. // s2[0]++;
    70. // }
    71. //
    72. // my_map::map::iterator it = st.begin();
    73. // while (it != st.end())
    74. // {
    75. // //if (*it % 2 == 0)
    76. // //{
    77. // // *it += 10;
    78. // //}
    79. // cout << (*it).first << ":"<< (*it).second << " "<
    80. // ++it;
    81. // }
    82. //
    83. // return 0;
    84. //}
    85. int main()
    86. {
    87. my_map::map dict;
    88. dict.insert(make_pair("sort", "xxx"));
    89. dict["left"]; // 插入
    90. for (const auto& kv : dict)
    91. {
    92. cout << kv.first << ":" << kv.second << endl;
    93. }
    94. cout << endl;
    95. dict["left"] = "左边"; // 修改
    96. dict["sort"] = "排序"; // 修改
    97. dict["right"] = "右边"; // 插入+修改
    98. for (const auto& kv : dict)
    99. {
    100. cout << kv.first << ":" << kv.second << endl;
    101. }
    102. cout << endl;
    103. return 0;
    104. }
  • 相关阅读:
    【信息论与编码基础】第3章 离散信道
    无需编程经验,也能制作租车预约微信小程序,快速上手
    vue3环境搭建
    跨域的五种解决方案
    码蹄集 - MT2322 - 还是跑图:还是简单图问题
    写组件的过程中没写过的vue3写法
    神经网络和深度学习-处理多维特征的输入
    ImageProvider工作流程和AssetImage 加载流程
    经济数据预测 | Python实现ARIMA时间序列金融市场预测
    杏仁损伤检测器——基于CNN的图像分类
  • 原文地址:https://blog.csdn.net/qq_73201597/article/details/133151950