当前位置:   article > 正文

C++ 模拟实现 STL 中的 set、map 与 multiset、multimap

C++ 模拟实现 STL 中的 set、map 与 multiset、multimap

目录

一,RB_tree 的实现

1,节点,数据结构,一些简单的辅助功能

2,迭代器

3,构造、拷贝、析构

4,查找与范围查找

5,插入与删除

二,set、multiset 与 map、multimap

1,set 与 multiset

2,map 与 multimap

三,简单的测试

1,对 set、multiset 的测试

2,对 map、multimap 的测试

四,RB_tree 的完整代码


set 与 map 是 STL 中的关联式容器,这俩容器与它们的衍生体 multiset 与 multimap 的底层都是由 RB_tree(红黑树)来实现的,虽然红黑树也是一个独立的容器,但是 STL 并没有将其开放给外界使用。关于 set、map 与 multiset、multimap 的使用方法这里就不介绍了,此文主要是简单的模拟实现。

在实现这两大容器之前,我们需要先实现它们的底层容器:红黑树;如果不清楚什么是红黑树或者不清楚红黑树的底层是怎么实现的,可以看看我之前写的这篇博客:

红黑树详解(C++ 实现)-CSDN博客文章浏览阅读871次,点赞23次,收藏18次。红黑树,是一种,每个结点上都有一个存储位以表示结点的颜色(红或黑)。通过对任何一条从根到叶子的路径上各个结点的着色方式的限制,它能够在插入和删除节点时自动调整树的结构,以保持树的平衡,从而保证查找、插入和删除操作的时间复杂度始终为O(logN)。https://blog.csdn.net/qq_41521068/article/details/134833750?spm=1001.2014.3001.5501

这里就默认大家都比较熟悉红黑树的底层实现了。下面此文将基于上面这篇博客所实现的红黑树来进行亿点小小的改造,使其能够为 set、map 与 multiset、multimap 所用。为了方便表述,本文将把上面博客实现的红黑树叫做 “原始红黑树”,将改造后的红黑树叫做 “RB_tree”

一,RB_tree 的实现

1,节点,数据结构,一些简单的辅助功能

节点的设计与原始红黑树一样:

  1. enum Color { Red, Black };
  2. template<class T>
  3. struct RBTreeNode {
  4. Color color;
  5. T val;
  6. RBTreeNode* left, * right, * parent;
  7. RBTreeNode(T val_, Color color_ = Red)
  8. :val(val_), color(color_), left(nullptr), right(nullptr), parent(nullptr) {}
  9. };

RB_tree 的数据结构与原始红黑树有两个很大的区别:

① RB_tree 维护了一个头节点(head),我们让 head->left 指向整个树中最靠左边的节点,让 head->right 指向整个树中最靠右边的节点,而 head->parent 则指向根节点,

root->parent 要指向 head(头节点与根节点的 parent 互相指向对方)。我们需要在每一次插入以及删除时动态的去维护这个 head 节点。

② RB_tree 模板参数比原始红黑树要复杂一点,RB_tree 需要 Key, Val, KeyOfVal, Compare 四个参数(这里偷一下懒,空间配置器就直接省略了)。KeyOfVal 与 Compare 都是函数类型,它们具体是用来干什么的,我们稍后再说~

a29f7f376c104418a32940b9c5f35c98.jpeg

设计一个头节点可以更好的辅助我们处理边界情况,尤其是在处理迭代器的 ++ 与 -- 操作的时候,稍后我们实现迭代器时就能感受到了。

RB_tree 的结构

  1. template<class Key, class Val, class KeyOfVal, class Compare>
  2. class RBTree {
  3. // ...
  4. private:
  5. typedef RBTreeNode<Val> Node;
  6. typedef Node* link_type;
  7. KeyOfVal _kov;
  8. Compare _cmp;
  9. private:
  10. // 主要的成员变量
  11. size_t _size = 0;
  12. link_type _head = nullptr;
  13. // ...
  14. };

现在我们来说说 KeyOfValCompare

Ⅰ,Compare

  • Compare 的作用是定义了元素之间的比较规则,从而决定了红黑树中元素的排序方式,这样能方便我们更灵活的使用红黑树

Ⅱ,KeyOfVal

  1. KeyOfVal 的作用是从存储的元素中提取出键值。红黑树存储的元素通常是键值对,它就是用来告诉红黑树如何从这些元素中提取出键值,以便进行比较和排序。
  2. 红黑树中存储的元素可能是键值对,也可能仅仅只是单键( set 中存的是单键, map 中存的是键值对)。在红黑树中,只要涉及到比较就一定会使用到键,KeyOfVal 就是为了统一单键与键值对这两种情况而设计的。
  3. 在上面代码中的模板参数中,Key 表示键,Val 表示储存的元素;如果是 map,Val 表示一个 pair<key,val>键值对, 如果是 set,Val 表示 Key。而 KeyOfVal 就是从 Val 中取出 Key

为了更好的进行一些操作,这里提供一些简单的辅助功能:

  1. private:
  2. // 一些简单的功能
  3. link_type& root()const { return _head->parent; }
  4. static bool is_black(link_type node) { return node == nullptr or node->color == Black; }
  5. static bool is_red(link_type node) { return node != nullptr and node->color == Red; }
  6. // 为了方便比较键值 key 而设计的函数
  7. bool key_compare(link_type node, const Key& key)const {
  8. return _cmp(_kov(node->val), key);
  9. }
  10. bool key_equal(link_type node, const Key& key)const {
  11. return !_cmp(_kov(node->val), key) and !_cmp(key, _kov(node->val));
  12. }
  13. public:
  14. // 一些简单的功能
  15. bool empty()const { return _size == 0; }
  16. size_t size()const { return _size; }

2,迭代器

要想将 RB_tree 实现成一个泛型容器,设计一个迭代器是至关重要的一步。如果不清楚什么是迭代器或者是不清楚要怎么为容器设计一个迭代器,可以看看我写的另一篇博客:

C++ 迭代器与反向迭代器-CSDN博客

以下是 RB_tree 迭代器所实现的功能:

  1. template<class T, class Ref, class Ptr> // Ref: 引用类型 , Ptr: 指针类型
  2. struct RBTreeIterator {
  3. typedef T value_type;
  4. typedef Ref reference;
  5. typedef Ptr pointer;
  6. typedef RBTreeIterator<T, Ref, Ptr> self; //当前迭代器
  7. typedef RBTreeIterator<T, T&, T*> iterator; //普通迭代器
  8. typedef RBTreeNode<T> Node;
  9. typedef Node* link_type;
  10. link_type _node; // 迭代器所对应的节点类型
  11. RBTreeIterator(const iterator& iter) :_node(iter._node) {} //普通迭代器构造当前迭代器
  12. RBTreeIterator(link_type node) :_node(node) {} //红黑树节点构造迭代器
  13. reference operator*() { return _node->val; }
  14. pointer operator->() { return &(operator*()); }
  15. bool operator==(self iter) { return _node == iter._node; }
  16. bool operator!=(self iter) { return not(*this == iter); }
  17. self operator++();
  18. self operator++(int);
  19. self operator--();
  20. self operator--(int);
  21. };

这里的重点是 operator++(前进) 与 operator--(后退)的实现。这里是按照的时中序遍历的顺序(即按照 左 -> 根 -> 右 的顺序)来进行前进或后退。

先来看看 operator++

  1. template<class T, class Ref, class Ptr> // Ref: 引用类型 , Ptr: 指针类型
  2. struct RBTreeIterator {
  3. // ...
  4. self operator++() {
  5. // 如果有右节点我们就一直走到整个右子树的最左端
  6. if (_node->right) {
  7. link_type node = _node->right;
  8. while (node->left) {
  9. node = node->left;
  10. }
  11. _node = node;
  12. }
  13. else { // 如果没有右节点, 我们就向上回溯, 直到当前节点不是右节点
  14. link_type parent = _node->parent;
  15. link_type cur = _node;
  16. while (cur == parent->right) {
  17. cur = cur->parent;
  18. parent = cur->parent;
  19. }
  20. _node = cur;
  21. // 注意一下这个 if 语句, 这是一个特殊的情况, 稍后再画图解释
  22. // 我们在这标记为 情况一
  23. if (cur->right != parent)
  24. _node = parent;
  25. }
  26. return *this;
  27. }
  28. self operator++(int) {
  29. self res = *this;
  30. ++(*this);
  31. return res;
  32. }
  33. // ...
  34. }

再来看看 operator--

  1. template<class T, class Ref, class Ptr> // Ref: 引用类型 , Ptr: 指针类型
  2. struct RBTreeIterator {
  3. // ...
  4. self operator--() {
  5. // 注意一下这条 if 语句, 这是一个特殊情况, 稍后再画图演示
  6. // 我们在这标记为 情况二
  7. if (_node->color == Red and _node->parent->parent == _node) {
  8. _node = _node->right;
  9. }
  10. else if (_node->left) { // 如果有左节点我们就一直走到整个左子树的最右端
  11. link_type node = _node->left;
  12. while (node->right) {
  13. node = node->right;
  14. }
  15. _node = node;
  16. }
  17. else { //如果没有左节点, 我们就向上回溯, 直到当前节点不是左节点
  18. link_type parent = _node->parent;
  19. link_type cur = _node;
  20. while (cur == parent->left) {
  21. cur = cur->parent;
  22. parent = cur->parent;
  23. }
  24. _node = parent;
  25. }
  26. return *this;
  27. }
  28. self operator--(int) {
  29. self res = *this;
  30. --(*this);
  31. return res;
  32. }
  33. // ...
  34. }

operator-- 操作与 operator++ 操作基本上是对称的,除了我们刚刚在注释中特别标明的特殊情况。

8578fee4834a4b01a288c17119100185.jpeg

3607f3b77e1e420d8a93b56a65d6ba6c.jpeg

看到这里你也许就会体会到:我们只需要为我们的原始红黑树添加一个头节点就可以比较方便的处理迭代器 ++ 与 -- 中的特殊情况啦。

RB_tree 中的迭代器操作:

  1. public:
  2. // 迭代器类型
  3. typedef RBTreeIterator<Val, Val&, Val*> iterator;
  4. typedef RBTreeIterator<Val, const Val&, const Val*> const_iterator;
  5. typedef Reverse_Iterator<iterator> reverse_iterator;
  6. typedef Reverse_Iterator<const_iterator> const_reverse_iterator;
  7. // begin 与 end 操作
  8. iterator begin() { return _head->left; }
  9. iterator end() { return _head; }
  10. const_iterator begin()const { return _head->left; }
  11. const_iterator end()const { return _head; }
  12. reverse_iterator rbegin() { return end(); }
  13. reverse_iterator rend() { return begin(); }
  14. const_reverse_iterator rbegin()const { return end(); }
  15. const_reverse_iterator rend()const { return begin(); }

3,构造、拷贝、析构

这里实现的 RB_tree 允许树中有重复的元素存在,为了更好的适配 set、map 以及 multiset、multimap,所以 RB_tree 只提供空构造(整颗树为空,只有头节点)以及拷贝构造,其他的构造方式就由它的上层容器来扩展。

下面是一些用来辅助构造、拷贝以及析构的函数:

  1. private:
  2. // 辅助 构造 拷贝 析构 的功能
  3. // 初始化
  4. void initialize() {
  5. _head = new Node(Val(), Red); // 为了与根节点区分,使用红色标记
  6. _head->left = _head; // 初始化将 _head 的左节点与右节点都指向自己
  7. _head->right = _head;
  8. root() = nullptr;
  9. _size = 0;
  10. }
  11. // 拷贝红黑树
  12. void copy(const RBTree& rbt) {
  13. initialize();
  14. root() = dfs_copy(rbt.root());
  15. root()->parent = _head;
  16. _head->left = left_most(root());
  17. _head->right = right_most(root());
  18. _size = rbt.size();
  19. }
  20. // 将 node 之下的节点全部拷贝
  21. static link_type dfs_copy(link_type node) {
  22. if (node == nullptr) return nullptr;
  23. Node* newNode = new Node(node->val, node->color);
  24. newNode->left = dfs_copy(node->left);
  25. newNode->right = dfs_copy(node->right);
  26. if (newNode->left) newNode->left->parent = newNode;
  27. if (newNode->right) newNode->right->parent = newNode;
  28. return newNode;
  29. }
  30. // 将 node 之下的所有节点删除
  31. static void dfs_clear(link_type node) {
  32. if (node == nullptr) return;
  33. dfs_clear(node->left);
  34. dfs_clear(node->right);
  35. delete node;
  36. }
  37. public:
  38. // 清空
  39. void clear() {
  40. dfs_clear(root());
  41. _size = 0;
  42. _head->left = _head->right = _head;
  43. root() = nullptr;
  44. }
  45. // 交换
  46. void swap(RBTree& rbt) {
  47. std::swap(_size, rbt._size);
  48. std::swap(_head, rbt._head);
  49. }

下面是构造,析构与拷贝函数:

  1. public:
  2. // 构造与析构
  3. RBTree() { initialize(); }
  4. ~RBTree() {
  5. if (not empty()) {
  6. clear();
  7. }
  8. if (_head) {
  9. delete _head;
  10. _head = nullptr;
  11. }
  12. }
  13. public:
  14. // 拷贝
  15. RBTree(const RBTree& rbt) { copy(rbt); }
  16. RBTree& operator=(RBTree rbt) {
  17. swap(rbt);
  18. return *this;
  19. }
  20. RBTree(RBTree&& rbt) { swap(rbt); }

4,查找与范围查找

红黑树是二叉搜索树,可以说是专门用来查找的数据结构了;前面有提到 RB_tree 允许树中有重复的元素存在,并且红黑树中的元素是有序的,所以 RB_tree 中的查找不仅仅只有针对单个值的查找,还有按照范围来进行的查找,请看下列代码:

  1. public:
  2. // 查找函数
  3. iterator find(const Key& key) { return find_impli<iterator>(key); }
  4. const_iterator find(const Key& key)const { return find_impli<const_iterator>(key); }
  5. iterator lower_bound(const Key& key) { return lower_bound_impli<iterator>(key); }
  6. const_iterator lower_bound(const Key& key)const { return lower_bound_impli<const_iterator>(key); }
  7. iterator upper_bound(const Key& key) { return upper_bound_impli<iterator>(key); }
  8. const_iterator upper_bound(const Key& key)const { return upper_bound_impli<const_iterator>(key); }
  9. pair<iterator, iterator> equal_range(const Key& key){
  10. return equal_range_impli<iterator>(key);
  11. }
  12. pair<const_iterator, const_iterator> equal_range(const Key& key)const{
  13. return equal_range_impli<const_iterator>(key);
  14. }

为了统一 const 和 非const 的情况,减少代码的重复,使其能够更简洁一点,这里提供了下面的这些统一的查找函数:

  1. private:
  2. // 查找的辅助函数
  3. template<class Iter_Type>
  4. Iter_Type find_impli(const Key& key)const {
  5. link_type cur = root();
  6. while (cur) {
  7. if (key_equal(cur, key)) return cur;
  8. cur = key_compare(cur, key) ? cur->right : cur->left;
  9. }
  10. return _head;
  11. }
  12. template<class Iter_Type>
  13. Iter_Type lower_bound_impli(const Key& key)const {
  14. link_type cur = root();
  15. link_type res = _head;
  16. while (cur) {
  17. if (key_compare(cur, key))
  18. cur = cur->right;
  19. else {
  20. res = cur;
  21. cur = cur->left;
  22. }
  23. }
  24. return res;
  25. }
  26. template<class Iter_Type>
  27. Iter_Type upper_bound_impli(const Key& key)const {
  28. link_type cur = root();
  29. link_type res = _head;
  30. while (cur) {
  31. if (key_compare(cur, key) or key_equal(cur, key))
  32. cur = cur->right;
  33. else {
  34. res = cur;
  35. cur = cur->left;
  36. }
  37. }
  38. return res;
  39. }
  40. template<class Iter_Type>
  41. pair<Iter_Type, Iter_Type> equal_range_impli(const Key& key)const {
  42. return make_pair(lower_bound_impli<Iter_Type>(key), upper_bound_impli<Iter_Type>(key));
  43. }

5,插入与删除

关于红黑树具体的插入、删除逻辑以及旋转操作这里就不再多说了,文章开头推出的博客中有详细的演示与说明,关于插入的调整操作以及删除的调整操作(insert_adjust() 与 erase_adjust())这里就不详细列出了,在文章的最后再一并给出完整代码。

先来说说 RB_tree 中的 插入操作,RB_tree 中提供两种不同的插入方式:一种是 insert_unique(),表示插入的元素必须是树中不存在的元素;另一种是 insert_equal(),这个操作可以将重复的元素插入树中。这两种插入方式分别会被 set、map 与 multiset、multimap 调用。

具体代码:

  1. public:
  2. // 插入与删除
  3. iterator insert_equal(const Val& val) {
  4. link_type parent = _head;
  5. link_type cur = root();
  6. while (cur) {
  7. parent = cur;
  8. cur = key_compare(cur, _kov(val)) ? cur->right : cur->left;
  9. }
  10. return insert_assist(parent, val);
  11. }
  12. pair<iterator, bool> insert_unique(const Val& val) {
  13. link_type parent = _head;
  14. link_type cur = root();
  15. while (cur) {
  16. if (key_equal(cur, _kov(val)))
  17. return make_pair(iterator(cur), false);
  18. parent = cur;
  19. cur = key_compare(cur, _kov(val)) ? cur->right : cur->left;
  20. }
  21. return make_pair(insert_assist(parent, val), true);
  22. }

这两种插入方式在具体实现上十分相似,它们在最后都会调用 insert_assist(),其实 insert_unique() 与 insert_equal() 更多的是负责查找或检查的工作,真正的插入逻辑是靠 insert_assist() 去实现:

  1. private:
  2. // 一些重要且复杂的函数
  3. // 插入的辅助函数
  4. iterator insert_assist(link_type parent, const Val& val) {
  5. link_type newNode = new Node(val, Red);
  6. newNode->parent = parent;
  7. if (parent == _head) {
  8. root() = newNode;
  9. root()->color = Black;
  10. }
  11. else {
  12. // 将parent与新插入进来的节点进行连接
  13. if (key_compare(parent, _kov(val)))
  14. parent->right = newNode;
  15. else
  16. parent->left = newNode;
  17. // 修正节点
  18. if (is_red(parent))
  19. insert_adjust(newNode);
  20. }
  21. ++_size;
  22. // 维护head节点
  23. _head->left = left_most(root());
  24. _head->right = right_most(root());
  25. return iterator(newNode);
  26. }

接下来是 erase:

  1. public:
  2. // 将树中的所有键值为 Key 的节点删除
  3. size_t erase(const Key& key) {
  4. int cnt = 0;
  5. while (erase_assist(key)) ++cnt;
  6. return cnt;
  7. }

与 insert 操作类似,真正的删除逻辑是靠 erase_assist 去实现

  1. private:
  2. // 删除的辅助函数
  3. size_t erase_assist(const Key& key) {
  4. link_type node = root(); // node 将表示为要被删去的节点
  5. link_type child = nullptr; // child 是替换被删除节点的位置的节点
  6. while (node != nullptr) {
  7. if (_kov(node->val) == key) {
  8. // 被删除的节点有左子节点也有右子节点的情况
  9. if (node->left and node->right) {
  10. link_type next = left_most(node->right); // node 的后继节点
  11. // 注意一下下面三行语句,稍后会解释为什么要这样写
  12. //node->val = next->val; // 这样写会报错
  13. node->val.~Val(); //
  14. new (&node->val) Val(next->val); //
  15. node = next;
  16. }
  17. child = node->left ? node->left : node->right;
  18. break;
  19. }
  20. else if (_cmp(_kov(node->val), key))
  21. node = node->right;
  22. else
  23. node = node->left;
  24. }
  25. if (node == nullptr)
  26. return 0;
  27. // 将 child 与 node->parent 链接
  28. if (child != nullptr)
  29. child->parent = node->parent;
  30. if (node == root())
  31. root() = child;
  32. else {
  33. if (node == node->parent->left)
  34. node->parent->left = child;
  35. else
  36. node->parent->right = child;
  37. }
  38. // 调整
  39. if (is_black(node))
  40. erase_adjust(child, node->parent);
  41. delete node;
  42. --_size;
  43. // 维护head节点
  44. _head->left = left_most(root());
  45. _head->right = right_most(root());
  46. return 1;
  47. }

这里在代码中标注了三条语句:

  1. //node->val = next->val; // 这样写会报错
  2. node->val.~Val(); //
  3. new (&node->val) Val(next->val); //

这里来解释一下:在 STL 的 map、multimap 实现中,键值对类型是 pair<const Key, Val>。由于 pair 的第一个元素是 const 类型,标准的赋值操作符 operator= 不允许修改第一个元素的值,这就是为什么直接使用 node->val = next->val 会导致编译器报错。解决这个问题的一种方法是使用 “placement new”显式的析构函数调用来替换节点的值,而不是直接赋值,这样可以绕过 const 限制。

二,set、multiset 与 map、multimap

1,set 与 multiset

set 与 multiset 中的所有元素会根据元素的键值自动的排序,set 中的每一个元素都是独一无二的,而 multiset 允许出现重复的元素。set 与 multiset 不允许修改容器中的任何元素,因为如果修改了键值的大小,那么容器中的元素就不一定有序了。因此 set 系列的中的 iterator 被定义为 const_iterator,reverse_iterator 被定义成 const_reverse_iterator。

set 与 multiset 在具体的实现中几乎一致,最大的不同就是 set 的插入操作是去调用 insert_unique(),而 multiset 的插入操作是去调用 insert_equal()。

下面是具体的代码实现

① set

  1. namespace mySTL {
  2. template<class Key, class Compare = less<Key>>
  3. class set {
  4. private:
  5. struct KeyOfVal {
  6. const Key& operator()(const Key& key)const { return key; }
  7. };
  8. typedef RBTree<Key, Key, KeyOfVal, Compare> RBTree;
  9. RBTree _rbt;
  10. public:
  11. // 迭代器
  12. typedef typename RBTree::const_iterator iterator;
  13. typedef typename RBTree::const_iterator const_iterator;
  14. typedef typename RBTree::const_reverse_iterator reverse_iterator;
  15. typedef typename RBTree::const_reverse_iterator const_reverse_iterator;
  16. iterator begin()const { return _rbt.begin(); }
  17. iterator end()const { return _rbt.end(); }
  18. reverse_iterator rbegin()const { return _rbt.rbegin(); }
  19. reverse_iterator rend()const { return _rbt.rend(); }
  20. public:
  21. // 构造与析构
  22. set() {}
  23. ~set() {}
  24. set(const std::initializer_list<Key>& init_list) {
  25. for (const Key& key : init_list) {
  26. insert(key);
  27. }
  28. }
  29. template<class input_iter>
  30. set(input_iter begin, input_iter end) {
  31. while (begin != end) {
  32. insert(*(begin++));
  33. }
  34. }
  35. public:
  36. // 拷贝
  37. set(const set& st) {_rbt = st._rbt;}
  38. set& operator=(set st) {
  39. swap(st);
  40. return *this;
  41. }
  42. set(set&& st) { swap(st); }
  43. public:
  44. // 查找
  45. iterator find(const Key& key)const { return _rbt.find(key); }
  46. iterator lower_bound(const Key& key)const { return _rbt.lower_bound(key); }
  47. iterator upper_bound(const Key& key)const { return _rbt.upper_bound(key); }
  48. pair<iterator, iterator> equal_range(const Key& key)const { return _rbt.equal_range(key); }
  49. public:
  50. // 插入 删除
  51. pair<iterator, bool> insert(const Key& key) {
  52. return _rbt.insert_unique(key);
  53. }
  54. size_t erase(const Key& key) { return _rbt.erase(key); }
  55. // 辅助功能
  56. void clear() { _rbt.clear(); }
  57. bool empty() { return _rbt.empty(); }
  58. size_t size() { return _rbt.size(); }
  59. void swap(set& st) { _rbt.swap(st._rbt); }
  60. bool valid_RBTree() { return _rbt.is_RBTree(); }
  61. };
  62. }

② multiset

  1. namespace mySTL{
  2. template<class Key, class Compare = less<Key>>
  3. class multiset {
  4. private:
  5. struct KeyOfVal {
  6. const Key& operator()(const Key& key)const { return key; }
  7. };
  8. typedef RBTree<Key, Key, KeyOfVal, Compare> RBTree;
  9. RBTree _rbt;
  10. public:
  11. // 迭代器
  12. typedef typename RBTree::const_iterator iterator;
  13. typedef typename RBTree::const_iterator const_iterator;
  14. typedef typename RBTree::const_reverse_iterator reverse_iterator;
  15. typedef typename RBTree::const_reverse_iterator const_reverse_iterator;
  16. iterator begin()const { return _rbt.begin(); }
  17. iterator end()const { return _rbt.end(); }
  18. reverse_iterator rbegin()const { return _rbt.rbegin(); }
  19. reverse_iterator rend()const { return _rbt.rend(); }
  20. public:
  21. // 构造与析构
  22. multiset() {}
  23. ~multiset() {}
  24. multiset(const std::initializer_list<Key>& init_list) {
  25. for (const Key& key : init_list) {
  26. insert(key);
  27. }
  28. }
  29. template<class input_iter>
  30. multiset(input_iter begin, input_iter end) {
  31. while (begin != end) {
  32. insert(*(begin++));
  33. }
  34. }
  35. public:
  36. // 拷贝
  37. multiset(const multiset& st) {
  38. _rbt = st._rbt;
  39. }
  40. multiset& operator=(multiset st) {
  41. swap(st);
  42. return *this;
  43. }
  44. multiset(multiset&& st) { swap(st); }
  45. public:
  46. // 查找
  47. iterator find(const Key& key)const { return _rbt.find(key); }
  48. iterator lower_bound(const Key& key)const { return _rbt.lower_bound(key); }
  49. iterator upper_bound(const Key& key)const { return _rbt.upper_bound(key); }
  50. pair<iterator, iterator> equal_range(const Key& key)const { return _rbt.equal_range(key); }
  51. public:
  52. // 插入 删除
  53. iterator insert(const Key& key) {
  54. return _rbt.insert_equal(key);
  55. }
  56. size_t erase(const Key& key) { return _rbt.erase(key); }
  57. // 辅助功能
  58. void clear() { _rbt.clear(); }
  59. bool empty() { return _rbt.empty(); }
  60. size_t size() { return _rbt.size(); }
  61. void swap(multiset& st) { _rbt.swap(st._rbt); }
  62. bool valid_RBTree() { return _rbt.is_RBTree(); }
  63. };
  64. }

2,map 与 multimap

map、multimap 也会根据元素的键值自动进行排序,这两个容器中的元素都是 pair<key, val> 键值对。map 不允许两个元素有相同的键,multimap 允许出现重复的键。map、multimap 不允许修改键值,但是可以修改实值(不能修改 key,可以修改 val),因为容器中元素的排列规则是依靠 key 来比较,val 并不会影响这个规则。

map 与 multimap 在实现中也几乎一致,最大的不同还是在于 map 的插入操作调用的是 insert_unique(),而 multimap 的插入操作调用的是 insert_equal()。还有一点需要注意的是 multimap 中并没有重载 operator[]。

下面是具体的代码实现:

① map

  1. namespace mySTL {
  2. template<class Key, class Val, class Compare = less<Key>>
  3. class map {
  4. private:
  5. struct KeyOfVal {
  6. Key operator()(const pair<const Key, Val>& p)const {
  7. return p.first;
  8. }
  9. };
  10. typedef RBTree<Key, pair<const Key, Val>, KeyOfVal, Compare> RBTree;
  11. RBTree _rbt;
  12. public:
  13. // 迭代器
  14. typedef typename RBTree::iterator iterator;
  15. typedef typename RBTree::const_iterator const_iterator;
  16. typedef typename RBTree::reverse_iterator reverse_iterator;
  17. typedef typename RBTree::const_reverse_iterator const_reverse_iterator;
  18. iterator begin() { return _rbt.begin(); }
  19. iterator end() { return _rbt.end(); }
  20. const_iterator begin() const { return _rbt.begin(); }
  21. const_iterator end() const { return _rbt.end(); }
  22. reverse_iterator rbegin() { return _rbt.rbegin(); }
  23. reverse_iterator rend() { return _rbt.rend(); }
  24. const_reverse_iterator rbegin()const { return _rbt.rbegin(); }
  25. const_reverse_iterator rend()const { return _rbt.rend(); }
  26. public:
  27. // 构造与析构
  28. map() {}
  29. ~map() {}
  30. map(const std::initializer_list<pair<Key, Val>>& init_list) {
  31. for (const pair<Key, Val>& kv : init_list) {
  32. insert(kv);
  33. }
  34. }
  35. template<class input_iter>
  36. map(input_iter begin, input_iter end) {
  37. while (begin != end) {
  38. insert(*begin);
  39. ++begin;
  40. }
  41. }
  42. public:
  43. // 拷贝
  44. map(const map& mp) { _rbt = mp._rbt; }
  45. map& operator=(map mp) {
  46. swap(mp);
  47. return *this;
  48. }
  49. map(map&& mp) { swap(mp); }
  50. public:
  51. // 查找元素
  52. iterator find(const Key& key) { return _rbt.find(key); }
  53. iterator lower_bound(const Key& key) { return _rbt.lower_bound(key); }
  54. iterator upper_bound(const Key& key) { return _rbt.upper_bound(key); }
  55. pair<iterator, iterator> equal_range(const Key& key) { return _rbt.equal_range(key); }
  56. const_iterator find(const Key& key)const { return _rbt.find(key); }
  57. const_iterator lower_bound(const Key& key)const { return _rbt.lower_bound(key); }
  58. const_iterator upper_bound(const Key& key)const { return _rbt.upper_bound(key); }
  59. pair<const_iterator, const_iterator> equal_range(const Key& key)const{
  60. return _rbt.equal_range(key);
  61. }
  62. public:
  63. // 插入 删除 修改
  64. Val& operator[](const Key& key) {
  65. return insert(make_pair(key, Val())).first->second;
  66. }
  67. pair<iterator, bool> insert(const pair<Key, Val>& kv) {
  68. return _rbt.insert_unique(kv);
  69. }
  70. size_t erase(const Key& key) { return _rbt.erase(key); }
  71. // 辅助功能
  72. bool empty() { return _rbt.empty(); }
  73. size_t size() { return _rbt.size(); }
  74. void swap(map& mp) { _rbt.swap(mp._rbt); }
  75. void clear() { _rbt.clear(); }
  76. bool valid_RBTree() { return _rbt.is_RBTree(); }
  77. };
  78. }

② multimap

  1. namespace mySTL {
  2. template<class Key, class Val, class Compare = less<Key>>
  3. class multimap {
  4. private:
  5. struct KeyOfVal {
  6. Key operator()(const pair<const Key, Val>& p)const {
  7. return p.first;
  8. }
  9. };
  10. typedef RBTree<Key, pair<const Key, Val>, KeyOfVal, Compare> RBTree;
  11. RBTree _rbt;
  12. public:
  13. // 迭代器
  14. typedef typename RBTree::iterator iterator;
  15. typedef typename RBTree::const_iterator const_iterator;
  16. typedef typename RBTree::reverse_iterator reverse_iterator;
  17. typedef typename RBTree::const_reverse_iterator const_reverse_iterator;
  18. iterator begin() { return _rbt.begin(); }
  19. iterator end() { return _rbt.end(); }
  20. const_iterator begin() const { return _rbt.begin(); }
  21. const_iterator end() const { return _rbt.end(); }
  22. reverse_iterator rbegin() { return _rbt.rbegin(); }
  23. reverse_iterator rend() { return _rbt.rend(); }
  24. const_reverse_iterator rbegin()const { return _rbt.rbegin(); }
  25. const_reverse_iterator rend()const { return _rbt.rend(); }
  26. public:
  27. // 构造与析构
  28. multimap() {}
  29. ~multimap() {}
  30. multimap(const std::initializer_list<pair<Key, Val>>& init_list) {
  31. for (const pair<Key, Val>& kv : init_list) {
  32. insert(kv);
  33. }
  34. }
  35. template<class input_iter>
  36. multimap(input_iter begin, input_iter end) {
  37. while (begin != end) {
  38. insert(*begin);
  39. ++begin;
  40. }
  41. }
  42. public:
  43. // 拷贝
  44. multimap(const multimap& mp) { _rbt = mp._rbt; }
  45. multimap& operator=(multimap mp) {
  46. swap(mp);
  47. return *this;
  48. }
  49. multimap(multimap&& mp) { swap(mp); }
  50. public:
  51. // 查找元素
  52. iterator find(const Key& key) { return _rbt.find(key); }
  53. iterator lower_bound(const Key& key) { return _rbt.lower_bound(key); }
  54. iterator upper_bound(const Key& key) { return _rbt.upper_bound(key); }
  55. pair<iterator, iterator> equal_range(const Key& key) { return _rbt.equal_range(key); }
  56. const_iterator find(const Key& key)const { return _rbt.find(key); }
  57. const_iterator lower_bound(const Key& key)const { return _rbt.lower_bound(key); }
  58. const_iterator upper_bound(const Key& key)const { return _rbt.upper_bound(key); }
  59. pair<const_iterator, const_iterator> equal_range(const Key& key)const {
  60. return _rbt.equal_range(key);
  61. }
  62. public:
  63. // 插入 删除 修改
  64. iterator insert(const pair<Key, Val>& kv) {
  65. return _rbt.insert_equal(kv);
  66. }
  67. size_t erase(const Key& key) { return _rbt.erase(key); }
  68. // 辅助功能
  69. void clear() { _rbt.clear(); }
  70. bool empty() { return _rbt.empty(); }
  71. size_t size() { return _rbt.size(); }
  72. void swap(multimap& mp) { _rbt.swap(mp._rbt); }
  73. bool valid_RBTree() { return _rbt.is_RBTree(); }
  74. };
  75. }

三,简单的测试

1,对 set、multiset 的测试

下面这份代码是对 set 进行简单的测试,我们只需要用一下编辑器自带的替换功能将下面代码中的 set 改为 multiset 就能够对 multiset 也进行一下简单的测试了

  1. class test_set {
  2. private:
  3. void test_insert_iter_erase(){
  4. mySTL::set<int> st;
  5. // 随机插入测试插入功能
  6. for (int i = 0;i < 30;++i) {
  7. int num = rand() % 100;
  8. if (not st.valid_RBTree()) {
  9. cout << "false";
  10. return;
  11. }
  12. st.insert(num);
  13. }
  14. // 遍历并打印,测试正向迭代器与反向迭代器功能
  15. for (const auto& data : st) cout << data << " ";
  16. cout << endl;
  17. for (auto rit = st.rbegin(); rit != st.rend(); ++rit) cout << *rit << " ";
  18. cout << endl;
  19. // 测试删除功能
  20. for (int i = 0;i < 30;++i) {
  21. int num = rand() % 1000;
  22. if (not st.valid_RBTree()) {
  23. cout << "false";
  24. return;
  25. }
  26. st.erase(num);
  27. }
  28. st.clear();
  29. if (not st.valid_RBTree()) {
  30. cout << "false";
  31. return;
  32. }
  33. }
  34. void test_construct_copy_find() {
  35. // 测试构造与拷贝
  36. mySTL::set<int> st = { 55,6,97,31,5,44,77,11,11,11,11};
  37. mySTL::set<int> st2(st);
  38. mySTL::set<int> st3;
  39. st3 = st2;
  40. for (const auto& data : st3) cout << data << " ";
  41. cout << endl;
  42. mySTL::set<int> st4(move(st3));
  43. for (const auto& data : st4) cout << data << " ";
  44. cout << endl;
  45. // 测试查找功能
  46. cout << *st.find(31) << endl;
  47. cout << *st.lower_bound(10) << " " << *st.upper_bound(60) << endl;
  48. }
  49. public:
  50. void test(){
  51. test_insert_iter_erase();
  52. cout << endl;
  53. test_construct_copy_find();
  54. }
  55. };

2,对 map、multimap 的测试

  1. class test_map {
  2. private:
  3. void test_insert_iter_erase() {
  4. mySTL::map<std::string, std::string> mp;
  5. mp["test"] = "测试";
  6. mp["test"] = "测试2";
  7. mp["test"] = "测试3";
  8. mp["data_struct"] = "数据结构";
  9. mp["algorithm"] = "算法";
  10. mp["mp_table"] = "哈希表";
  11. if (not mp.valid_RBTree()) {
  12. cout << "false" << endl;
  13. }
  14. for (const auto& [key, val] : mp) {
  15. cout << key << " : " << val << endl;
  16. }
  17. }
  18. void test_construct_copy() {
  19. mySTL::multimap<std::string, std::string> mp = {
  20. {"test","测试"},{"test","测试2"},{"test","测试3"},
  21. {"data_struct","数据结构"},{"algorithm","算法"},{"mp_table","哈希表"}
  22. };
  23. mySTL::multimap<std::string, std::string> mp2(mp);
  24. mySTL::multimap<std::string, std::string> mp3;
  25. mp3 = mp2;
  26. for (const auto& [key, val] : mp3) {
  27. cout << key << " : " << val << endl;
  28. }
  29. cout << endl;
  30. mySTL::multimap<std::string, std::string> mp4 = move(mp3);
  31. for (const auto& [key, val] : mp4) {
  32. cout << key << " : " << val << endl;
  33. }
  34. cout << endl;
  35. }
  36. public:
  37. void test() {
  38. test_insert_iter_erase();
  39. cout << endl;
  40. test_construct_copy();
  41. }
  42. };

四,RB_tree 的完整代码

因为代码比较长,如果对实现的细节不感兴趣,直接跳过就好啦。

  1. namespace mySTL {
  2. enum Color { Red, Black };
  3. template<class T>
  4. struct RBTreeNode {
  5. Color color;
  6. T val;
  7. RBTreeNode* left, * right, * parent;
  8. RBTreeNode(T val_, Color color_ = Red)
  9. :val(val_), color(color_), left(nullptr), right(nullptr), parent(nullptr) {}
  10. };
  11. template<class T, class Ref, class Ptr> // Ref: 引用类型 , Ptr: 指针类型
  12. struct RBTreeIterator {
  13. typedef T value_type;
  14. typedef Ref reference;
  15. typedef Ptr pointer;
  16. typedef RBTreeIterator<T, Ref, Ptr> self; //当前迭代器
  17. typedef RBTreeIterator<T, T&, T*> iterator; //普通迭代器
  18. typedef RBTreeNode<T> Node;
  19. typedef Node* link_type;
  20. link_type _node;
  21. RBTreeIterator(const iterator& iter) :_node(iter._node) {} //普通迭代器构造当前迭代器
  22. RBTreeIterator(link_type node) :_node(node) {} //红黑树节点构造迭代器
  23. reference operator*() { return _node->val; }
  24. pointer operator->() { return &(operator*()); }
  25. bool operator==(self iter) { return _node == iter._node; }
  26. bool operator!=(self iter) { return not(*this == iter); }
  27. self operator++() {
  28. if (_node->right) {
  29. link_type node = _node->right;
  30. while (node->left) {
  31. node = node->left;
  32. }
  33. _node = node;
  34. }
  35. else {
  36. link_type parent = _node->parent;
  37. link_type cur = _node;
  38. while (cur == parent->right) {
  39. cur = cur->parent;
  40. parent = cur->parent;
  41. }
  42. _node = cur;
  43. // 注意
  44. if (cur->right != parent)
  45. _node = parent;
  46. }
  47. return *this;
  48. }
  49. self operator++(int) {
  50. self res = *this;
  51. ++(*this);
  52. return res;
  53. }
  54. self operator--() {
  55. // 注意
  56. if (_node->color == Red and _node->parent->parent == _node) {
  57. _node = _node->right;
  58. }
  59. else if (_node->left) {
  60. link_type node = _node->left;
  61. while (node->right) {
  62. node = node->right;
  63. }
  64. _node = node;
  65. }
  66. else {
  67. link_type parent = _node->parent;
  68. link_type cur = _node;
  69. while (cur == parent->left) {
  70. cur = cur->parent;
  71. parent = cur->parent;
  72. }
  73. _node = parent;
  74. }
  75. return *this;
  76. }
  77. self operator--(int) {
  78. self res = *this;
  79. --(*this);
  80. return res;
  81. }
  82. };
  83. template<class Key, class Val, class KeyOfVal, class Compare>
  84. class RBTree {
  85. private:
  86. typedef RBTreeNode<Val> Node;
  87. typedef Node* link_type;
  88. KeyOfVal _kov;
  89. Compare _cmp;
  90. private:
  91. // 主要的成员变量
  92. size_t _size = 0;
  93. link_type _head = nullptr;
  94. public:
  95. // 迭代器类型
  96. typedef RBTreeIterator<Val, Val&, Val*> iterator;
  97. typedef RBTreeIterator<Val, const Val&, const Val*> const_iterator;
  98. typedef Reverse_Iterator<iterator> reverse_iterator;
  99. typedef Reverse_Iterator<const_iterator> const_reverse_iterator;
  100. // begin 与 end 操作
  101. iterator begin() { return _head->left; }
  102. iterator end() { return _head; }
  103. const_iterator begin()const { return _head->left; }
  104. const_iterator end()const { return _head; }
  105. reverse_iterator rbegin() { return end(); }
  106. reverse_iterator rend() { return begin(); }
  107. const_reverse_iterator rbegin()const { return end(); }
  108. const_reverse_iterator rend()const { return begin(); }
  109. private:
  110. // 一些简单的功能
  111. link_type& root()const { return _head->parent; }
  112. static bool is_black(link_type node) { return node == nullptr or node->color == Black; }
  113. static bool is_red(link_type node) { return node != nullptr and node->color == Red; }
  114. // 为了方便比较键值 key 而设计的函数
  115. bool key_compare(link_type node, const Key& key)const {
  116. return _cmp(_kov(node->val), key);
  117. }
  118. bool key_equal(link_type node, const Key& key)const {
  119. return !_cmp(_kov(node->val), key) and !_cmp(key, _kov(node->val));
  120. }
  121. public:
  122. // 一些简单的功能
  123. bool empty()const { return _size == 0; }
  124. size_t size()const { return _size; }
  125. private:
  126. // 辅助 构造 拷贝 析构 的功能
  127. // 初始化
  128. void initialize() {
  129. _head = new Node(Val(), Red); // 为了与根节点区分,使用红色标记
  130. _head->left = _head; // 初始化将 _head 的左节点与右节点都指向自己
  131. _head->right = _head;
  132. root() = nullptr;
  133. _size = 0;
  134. }
  135. void copy(const RBTree& rbt) {
  136. initialize();
  137. root() = dfs_copy(rbt.root());
  138. root()->parent = _head;
  139. _head->left = left_most(root());
  140. _head->right = right_most(root());
  141. _size = rbt.size();
  142. }
  143. // 将 node 之下的节点全部拷贝
  144. static link_type dfs_copy(link_type node) {
  145. if (node == nullptr) return nullptr;
  146. Node* newNode = new Node(node->val, node->color);
  147. newNode->left = dfs_copy(node->left);
  148. newNode->right = dfs_copy(node->right);
  149. if (newNode->left) newNode->left->parent = newNode;
  150. if (newNode->right) newNode->right->parent = newNode;
  151. return newNode;
  152. }
  153. // 将 node 之下的所有节点删除
  154. static void dfs_clear(link_type node) {
  155. if (node == nullptr) return;
  156. dfs_clear(node->left);
  157. dfs_clear(node->right);
  158. delete node;
  159. }
  160. public:
  161. // 清空
  162. void clear() {
  163. dfs_clear(root());
  164. _size = 0;
  165. _head->left = _head->right = _head;
  166. root() = nullptr;
  167. }
  168. // 交换
  169. void swap(RBTree& rbt) {
  170. std::swap(_size, rbt._size);
  171. std::swap(_head, rbt._head);
  172. }
  173. public:
  174. // 构造与析构
  175. RBTree() { initialize(); }
  176. ~RBTree() {
  177. if (not empty()) {
  178. clear();
  179. }
  180. if (_head) {
  181. delete _head;
  182. _head = nullptr;
  183. }
  184. }
  185. public:
  186. // 拷贝
  187. RBTree(const RBTree& rbt) { copy(rbt); }
  188. RBTree& operator=(RBTree rbt) {
  189. swap(rbt);
  190. return *this;
  191. }
  192. RBTree(RBTree&& rbt) { swap(rbt); }
  193. public:
  194. // 查找函数
  195. iterator find(const Key& key) { return find_impli<iterator>(key); }
  196. const_iterator find(const Key& key)const { return find_impli<const_iterator>(key); }
  197. iterator lower_bound(const Key& key) { return lower_bound_impli<iterator>(key); }
  198. const_iterator lower_bound(const Key& key)const { return lower_bound_impli<const_iterator>(key); }
  199. iterator upper_bound(const Key& key) { return upper_bound_impli<iterator>(key); }
  200. const_iterator upper_bound(const Key& key)const { return upper_bound_impli<const_iterator>(key); }
  201. pair<iterator, iterator> equal_range(const Key& key){
  202. return equal_range_impli<iterator>(key);
  203. }
  204. pair<const_iterator, const_iterator> equal_range(const Key& key)const{
  205. return equal_range_impli<const_iterator>(key);
  206. }
  207. private:
  208. // 查找的辅助函数
  209. template<class Iter_Type>
  210. Iter_Type find_impli(const Key& key)const {
  211. link_type cur = root();
  212. while (cur) {
  213. if (key_equal(cur, key)) return cur;
  214. cur = key_compare(cur, key) ? cur->right : cur->left;
  215. }
  216. return _head;
  217. }
  218. template<class Iter_Type>
  219. Iter_Type lower_bound_impli(const Key& key)const {
  220. link_type cur = root();
  221. link_type res = _head;
  222. while (cur) {
  223. if (key_compare(cur, key))
  224. cur = cur->right;
  225. else {
  226. res = cur;
  227. cur = cur->left;
  228. }
  229. }
  230. return res;
  231. }
  232. template<class Iter_Type>
  233. Iter_Type upper_bound_impli(const Key& key)const {
  234. link_type cur = root();
  235. link_type res = _head;
  236. while (cur) {
  237. if (key_compare(cur, key) or key_equal(cur, key))
  238. cur = cur->right;
  239. else {
  240. res = cur;
  241. cur = cur->left;
  242. }
  243. }
  244. return res;
  245. }
  246. template<class Iter_Type>
  247. pair<Iter_Type, Iter_Type> equal_range_impli(const Key& key)const {
  248. return make_pair(lower_bound_impli<Iter_Type>(key), upper_bound_impli<Iter_Type>(key));
  249. }
  250. public:
  251. // 插入与删除
  252. iterator insert_equal(const Val& val) {
  253. link_type parent = _head;
  254. link_type cur = root();
  255. while (cur) {
  256. parent = cur;
  257. cur = key_compare(cur, _kov(val)) ? cur->right : cur->left;
  258. }
  259. return insert_assist(parent, val);
  260. }
  261. pair<iterator, bool> insert_unique(const Val& val) {
  262. link_type parent = _head;
  263. link_type cur = root();
  264. while (cur) {
  265. if (key_equal(cur, _kov(val)))
  266. return make_pair(iterator(cur), false);
  267. parent = cur;
  268. cur = key_compare(cur, _kov(val)) ? cur->right : cur->left;
  269. }
  270. return make_pair(insert_assist(parent, val), true);
  271. }
  272. size_t erase(const Key& key) {
  273. int cnt = 0;
  274. while (erase_assist(key)) ++cnt;
  275. return cnt;
  276. }
  277. public:
  278. //检查是否是正确的红黑树
  279. bool is_RBTree()const {
  280. //根节点为红色直接返回false
  281. if (is_red(root())) return false;
  282. // 判断每条路径的黑节点数量以及红节点的child的颜色是否符合红黑树的性质
  283. std::function<pair<bool, int>(link_type)> cnt_color = [&](link_type node) {
  284. // first:判断结果 second:黑节点的数量
  285. if (node == nullptr) {
  286. return make_pair(true, 1);
  287. }
  288. if (is_red(node) and is_red(node->parent)) {
  289. return make_pair(false, -1);
  290. }
  291. auto [left_is, cnt1] = cnt_color(node->left);
  292. auto [right_is, cnt2] = cnt_color(node->right);
  293. return left_is and right_is and cnt1 == cnt2 ?
  294. make_pair(true, cnt1 + is_black(node)) :
  295. make_pair(false, -1);
  296. };
  297. // 判断中序遍历是否有序
  298. std::function<bool()> inorder = [&]() {
  299. std::vector<Key> ino;
  300. function<void(link_type)> inside_inorder = [&](link_type node) {
  301. if (node) {
  302. inside_inorder(node->left);
  303. // ino.push_back(KeyOfVal()(node->val));
  304. ino.push_back(_kov(node->val));
  305. inside_inorder(node->right);
  306. }
  307. };
  308. inside_inorder(root());
  309. for (int i = 0;i < ino.size();++i) {
  310. if (i > 0 and _cmp(ino[i], ino[i - 1]) and ino[i] != ino[i - 1])
  311. return false;
  312. // 这里可以控制是否输出中序遍历的结果
  313. // cout << ino[i] << ' ';
  314. }
  315. return true;
  316. };
  317. return cnt_color(root()).first and inorder();
  318. }
  319. private:
  320. // 一些辅助用的函数
  321. // 左旋
  322. void rotate_left(link_type node) {
  323. link_type right = node->right;
  324. node->right = right->left;
  325. right->left = node;
  326. if (node->right) node->right->parent = node;
  327. link_type parent = node->parent;
  328. right->parent = parent;
  329. node->parent = right;
  330. if (parent == _head) root() = right; //更新root()节点
  331. else if (parent->left == node) parent->left = right;
  332. else parent->right = right;
  333. }
  334. // 右旋
  335. void rotate_right(link_type node) {
  336. link_type left = node->left;
  337. node->left = left->right;
  338. left->right = node;
  339. if (node->left) node->left->parent = node;
  340. link_type parent = node->parent;
  341. left->parent = parent;
  342. node->parent = left;
  343. if (parent == _head) root() = left;
  344. else if (parent->left == node) parent->left = left;
  345. else parent->right = left;
  346. }
  347. // 最左边的节点
  348. link_type left_most(link_type node) {
  349. if (node == nullptr)
  350. return _head;
  351. while (node->left) {
  352. node = node->left;
  353. }
  354. return node;
  355. }
  356. // 最右边的节点
  357. link_type right_most(link_type node) {
  358. if (node == nullptr)
  359. return _head;
  360. while (node->right) {
  361. node = node->right;
  362. }
  363. return node;
  364. }
  365. private:
  366. // 一些重要且复杂的函数
  367. // 插入的辅助函数
  368. iterator insert_assist(link_type parent, const Val& val) {
  369. link_type newNode = new Node(val, Red);
  370. newNode->parent = parent;
  371. if (parent == _head) {
  372. root() = newNode;
  373. root()->color = Black;
  374. }
  375. else {
  376. // 将parent与新插入进来的节点进行连接
  377. if (key_compare(parent, _kov(val)))
  378. parent->right = newNode;
  379. else
  380. parent->left = newNode;
  381. // 修正节点
  382. if (is_red(parent))
  383. insert_adjust(newNode);
  384. }
  385. ++_size;
  386. // 维护head节点
  387. _head->left = left_most(root());
  388. _head->right = right_most(root());
  389. return iterator(newNode);
  390. }
  391. // 插入的调节
  392. void insert_adjust(link_type node) {
  393. link_type parent = node->parent;
  394. while (parent != _head and parent->color == Red) {
  395. link_type grand = parent->parent; //这里的grand是一定存在的
  396. // 当前的节点在 grand 的左边
  397. if (parent == grand->left) {
  398. link_type uncle = grand->right;
  399. // 情况一
  400. // uncle存在且为红色
  401. if (is_red(uncle)) {
  402. parent->color = uncle->color = Black;
  403. grand->color = Red;
  404. //继续向上调整
  405. }
  406. // 情况二与情况三
  407. //uncle不存在或uncle为黑色
  408. else {
  409. // 将情况三转为情况二
  410. if (node == parent->right) {
  411. rotate_left(parent);
  412. //注意:这里旋转完后parent与node的父子关系交换了,所以要swap回来
  413. std::swap(parent, node);
  414. }
  415. rotate_right(grand);
  416. parent->color = Black;
  417. grand->color = Red;
  418. //调整结束
  419. break;
  420. }
  421. }
  422. // 当前的节点在 grand 的右边
  423. // parent==grand->right 与 parent==grand->left 的情况类似
  424. else {
  425. link_type uncle = grand->left;
  426. if (is_red(uncle)) {
  427. parent->color = uncle->color = Black;
  428. grand->color = Red;
  429. }
  430. else {
  431. if (node == parent->left) {
  432. rotate_right(parent);
  433. std::swap(parent, node);
  434. }
  435. rotate_left(grand);
  436. parent->color = Black;
  437. grand->color = Red;
  438. break;
  439. }
  440. }
  441. //将node更新为当前的祖父节点,继续循环调整
  442. node = grand;
  443. parent = node->parent;
  444. }
  445. //保证根节点必须是黑色
  446. root()->color = Black;
  447. }
  448. // 删除的辅助函数
  449. size_t erase_assist(const Key& key) {
  450. link_type node = root(); // node 将表示为要被删去的节点
  451. link_type child = nullptr; // child 是替换被删除节点的位置的节点
  452. while (node != nullptr) {
  453. if (_kov(node->val) == key) {
  454. // 被删除的节点有左子节点也有右子节点的情况
  455. if (node->left and node->right) {
  456. link_type next = left_most(node->right); // node 的后继节点
  457. // 注意一下下面三行语句,稍后会解释为什么要这样写
  458. //node->val = next->val; // 这样写会报错
  459. node->val.~Val(); //
  460. new (&node->val) Val(next->val); //
  461. node = next;
  462. }
  463. child = node->left ? node->left : node->right;
  464. break;
  465. }
  466. else if (_cmp(_kov(node->val), key))
  467. node = node->right;
  468. else
  469. node = node->left;
  470. }
  471. if (node == nullptr)
  472. return 0;
  473. // 将 child 与 node->parent 链接
  474. if (child != nullptr)
  475. child->parent = node->parent;
  476. if (node == root())
  477. root() = child;
  478. else {
  479. if (node == node->parent->left)
  480. node->parent->left = child;
  481. else
  482. node->parent->right = child;
  483. }
  484. // 调整
  485. if (is_black(node))
  486. erase_adjust(child, node->parent);
  487. delete node;
  488. --_size;
  489. // 维护head节点
  490. _head->left = left_most(root());
  491. _head->right = right_most(root());
  492. return 1;
  493. }
  494. // 删除的调节
  495. void erase_adjust(link_type node, link_type parent) {
  496. //cout << "start ";
  497. while (node != root() and is_black(node)) {
  498. // 当前的节点再 parent 的左边
  499. if (node == parent->left) {
  500. link_type sibling = parent->right;
  501. // 情况一
  502. if (is_red(sibling)) {
  503. //cout << "case1 ";
  504. rotate_left(parent);
  505. sibling->color = Black;
  506. parent->color = Red;
  507. sibling = parent->right;
  508. }
  509. // 情况二
  510. if (is_black(sibling->left) and is_black(sibling->right)) {
  511. //cout << "case2 ";
  512. sibling->color = Red;
  513. node = parent;
  514. parent = node->parent;
  515. continue;
  516. }
  517. else {
  518. // 情况三
  519. if (is_black(sibling->right)) {
  520. //cout << "case3 ";
  521. rotate_right(sibling);
  522. sibling->color = Red;
  523. parent->right->color = Black;
  524. sibling = parent->right;
  525. // 此时我们已将情况三转换为情况四
  526. }
  527. // 情况四
  528. //cout << "case4 ";
  529. sibling->color = parent->color;
  530. rotate_left(parent);
  531. parent->color = Black;
  532. sibling->right->color = Black;
  533. break;
  534. }
  535. }
  536. // 与上面的情况对称
  537. else {
  538. link_type sibling = parent->left;
  539. // 情况一
  540. if (is_red(sibling)) {
  541. //cout << "case1 ";
  542. rotate_right(parent);
  543. sibling->color = Black;
  544. parent->color = Red;
  545. sibling = parent->left;
  546. }
  547. // 情况二
  548. if (is_black(sibling->right) and is_black(sibling->left)) {
  549. //cout << "case2 ";
  550. sibling->color = Red;
  551. node = parent;
  552. parent = node->parent;
  553. continue;
  554. }
  555. else {
  556. // 情况三
  557. if (is_black(sibling->left)) {
  558. //cout << "case3 ";
  559. rotate_left(sibling);
  560. sibling->color = Red;
  561. parent->left->color = Black;
  562. sibling = parent->left;
  563. // 此时我们已将情况三转换为情况四
  564. }
  565. // 情况四
  566. //cout << "case4 ";
  567. sibling->color = parent->color;
  568. rotate_right(parent);
  569. parent->color = Black;
  570. sibling->left->color = Black;
  571. break;
  572. }
  573. }
  574. }
  575. //cout << "end ";
  576. if (node) node->color = Black;
  577. }
  578. };
  579. }

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

闽ICP备14008679号