当前位置:   article > 正文

【C++】-- STL之用红黑树模拟实现map和set_stl 红黑树

stl 红黑树

目录

一、map和set类模板​​​​​​

二、红黑树节点定义

1.红黑树的节点修改 

2.仿函数 

(1)节点比较大小时存在的问题 

(2)仿函数

(3)修改红黑树定义

(4)修改红黑树插入

(5)修改红黑树查找

三、红黑树迭代器

1.红黑树中迭代器重命名

2.正向迭代器定义

3.迭代器构造 

4.正向迭代器重载* 

5.正向迭代器重载-> 

6.正向迭代器重载==

7.正向迭代器重载!=

8.正向迭代器++

9.正向迭代器--

10.红黑树中实现迭代器

四、set模拟实现

五、map模拟实现

六、红黑树完整代码段


一、map和set类模板​​​​​​

【C++】-- STL之map和set详解一文中提到,set用value标识元素(value就是key,类型为T),并且每个value必须唯一 。

template < class Key>//set

在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起,为其取别名称为pair:

typedef pair<const Key, T> value_type;
template < class Key, class T>//map

 用红黑树同时封装出set和map时,set传给value的是一个value,map传给value的是一个pair,set和map传给红黑树的value决定了这棵树里面存的节点值类型。上层容器不同,底层红黑树的Key和T也不同。

 ​​​​​​

在上层容器set中,K和T都代表Key,底层红黑树节点当中存储K和T都是一样的;map中,K代表键值Key,T代表由Key和Value构成的键值对,底层红黑树中只能存储T。所以红黑树为了满足同时支持set和map,节点当中存储T。

这就要对红黑树进行改动。

二、红黑树节点定义

1.红黑树的节点修改 

【C++】-- 红黑树详解的红黑树节点定义由类模板

template<class K,class V>

修改为

template<class T>

 那么节点定义就修改为

  1. //红黑树节点定义
  2. template<class T>
  3. struct RBTreeNode
  4. {
  5. RBTreeNode<T>* _left;//节点的左孩子
  6. RBTreeNode<T>* _right;//节点的右孩子
  7. RBTreeNode<T>* _parent;//节点的父亲
  8. T _data;//节点的值,_data里面存的是K就传K,存的是pair就传pair
  9. Colour _col;//节点颜色
  10. RBTreeNode(const T& x)
  11. :_left(nullptr)
  12. , _right(nullptr)
  13. , _parent(nullptr)
  14. , _data(x)
  15. , _col(RED)
  16. {}
  17. };

由于红黑树不知道上层传的是K还是pair,这是由上层传递的模板参数T决定的,上层是封装我的map和set。

2.仿函数 

(1)节点比较大小时存在的问题 

红黑树插入节点时,需要比较节点的大小,kv需要改成_data:

  1. //插入
  2. pair<Node*, bool> Insert(const T& data)
  3. {
  4. if (_root == nullptr)
  5. {
  6. _root = new Node(data);
  7. _root->_col = BLACK;
  8. return make_pair(_root, true);
  9. }
  10. //1.先看树中,kv是否存在
  11. Node* parent = nullptr;
  12. Node* cur = _root;
  13. while (cur)
  14. {
  15. if (cur->_data < data)
  16. {
  17. //kv比当前节点值大,向右走
  18. parent = cur;
  19. cur = cur->_right;
  20. }
  21. else if (cur->_data > data)
  22. {
  23. //kv比当前节点值小,向左走
  24. parent = cur;
  25. cur = cur->_left;
  26. }
  27. else
  28. {
  29. //kv和当前节点值相等,已存在,插入失败
  30. return make_pair(cur, false);
  31. }
  32. }
  33. //2.走到这里,说明kv在树中不存在,需要插入kv,并且cur已经为空,parent已经是叶子节点了
  34. Node* newNode = new Node(kv);
  35. newNode->_col = RED;
  36. if (parent->_data < data)
  37. {
  38. //kv比parent值大,插入到parent的右边
  39. parent->_right = newNode;
  40. newNode->_parent = parent;
  41. }
  42. else
  43. {
  44. //kv比parent值小,插入到parent的左边
  45. parent->_left = newNode;
  46. newNode->_parent = parent;
  47. }
  48. cur = newNode;
  49. //如果父亲存在,且父亲颜色为红就要处理
  50. while (parent && parent->_col == RED)
  51. {
  52. //情况一和情况二、三的区别关键看叔叔
  53. Node* grandfather = parent->_parent;//当父亲是红色时,根据规则(2)根节点一定是黑色,祖父一定存在
  54. if (parent == grandfather->_left)//父亲是祖父的左子树
  55. {
  56. Node* uncle = grandfather->_right;
  57. //情况一:叔叔存在且为红
  58. if (uncle->_col == RED)
  59. {
  60. parent->_col = uncle->_col = BLACK;
  61. grandfather->_col = RED;
  62. //继续向上调整
  63. cur = grandfather;
  64. parent = cur->_parent;
  65. }
  66. else//情况二+情况三:叔叔不存在或叔叔存在且为黑
  67. {
  68. //情况二:单旋
  69. if (cur == parent->_left)
  70. {
  71. RotateR(grandfather);
  72. parent->_col = BLACK;
  73. grandfather->_col = RED;
  74. }
  75. else//情况三:双旋
  76. {
  77. RotateL(parent);
  78. RotateR(grandfather);
  79. cur->_col = BLACK;
  80. grandfather->_col = RED;
  81. }
  82. break;//插入结束
  83. }
  84. }
  85. else//父亲是祖父的右子树
  86. {
  87. Node* uncle = grandfather->_left;
  88. //情况一:叔叔存在且为红
  89. if (uncle && uncle->_col == RED)
  90. {
  91. parent->_col = uncle->_col = BLACK;
  92. grandfather->_col = RED;
  93. //继续往上调整
  94. cur = grandfather;
  95. parent = grandfather->_parent;
  96. }
  97. else//情况二+情况三:叔叔不存在或叔叔存在且为黑
  98. {
  99. //情况二:单旋
  100. if (cur == parent->_right)
  101. {
  102. RotateL(grandfather);
  103. parent->_col = BLACK;
  104. grandfather->_col = RED;
  105. }
  106. else//情况三:双旋
  107. {
  108. RotateR(parent);
  109. RotateL(grandfather);
  110. cur->_col = BLACK;
  111. grandfather->_col = RED;
  112. }
  113. break;//插入结束
  114. }
  115. }
  116. }
  117. _root->_col = BLACK;
  118. return make_pair(newNode, true);
  119. }

但是以上代码在插入新节和查找节点时,当和当前节点比较大小时,Key可以比较,但是pair比较不了,也就是set可以比较,但是map比较不了。这就需要写一个仿函数,如果是map就取_data里面的first也就是Key进行比较,通过泛型解决红黑树里面存的是什么。所以上层容器map需要向底层的红黑树提供仿函数来获取T里面的Key,这样无论上层容器是set还是map,都可以用统一的方式进行比较了。

(2)仿函数

仿函数让一个类的使用看上去像个函数。仿函数是在类中实现了一个operator( ),是一个类的对象,这个类就有了类似函数的行为,所以这个类就是一个仿函数类,目的是为了让函数拥有类的性质。

这个类的对象即仿函数,可以当作一般函数去用,只不过仿函数的功能是在一个类中的运算符operator()中实现的,使用的时候把函数作为参进行传递即可。更详细的理解请参考【C++】-- STL容器适配器之priority_queue第三节第1小节的内容。

set有set的仿函数,map有map的仿函数,尽管set的仿函数看起来没有什么作用,但是,必须要把它传给底层红黑树,这样红黑树就能根据仿函数分别获取set的key和map的first。

 ①set的仿函数

  1. namespace delia
  2. {
  3. template<class K>
  4. class set
  5. {
  6. //仿函数,获取set的key
  7. struct SetKeyOfT
  8. {
  9. const K& operator()(const K& key)
  10. {
  11. return key;
  12. }
  13. };
  14. public:
  15. bool insert(const K& k)
  16. {
  17. _t.Insert(k);
  18. return true;
  19. }
  20. private:
  21. RBTree<K, K,SetKeyOfT> _t;
  22. };
  23. }

 ②map的仿函数

  1. namespace delia
  2. {
  3. template<class K,class V>
  4. class map
  5. {
  6. //仿函数,获取map的first
  7. struct MapKeyOfT
  8. {
  9. const K& operator()(const pair<const K, V>& kv)
  10. {
  11. return kv.first;
  12. }
  13. };
  14. public:
  15. //插入
  16. bool insert(const pair<const K, V>& kv)
  17. {
  18. _t.Insert(kv);
  19. return true;
  20. }
  21. private:
  22. RBTree<K, pair<const K, V>, MapKeyOfT> _t;
  23. };
  24. }

 有了仿函数红黑树的类在实现时,就要在模板参数中增加KeyOfT仿函数。

(3)修改红黑树定义

  1. template<class K, class T, class KeyOfT>
  2. class RBTree
  3. {
  4. typedef RBTreeNode<T> Node;
  5. private:
  6. Node* _root;
  7. };

(4)修改红黑树插入

  1. //插入
  2. pair<Node*, bool> Insert(const pair<K, V>& kv)
  3. {
  4. if (_root == nullptr)
  5. {
  6. _root = new Node(kv);
  7. _root->_col = BLACK;
  8. return make_pair(_root, true);
  9. }
  10. KeyOfT kot;
  11. //1.先看树中,kv是否存在
  12. Node* parent = nullptr;
  13. Node* cur = _root;
  14. while (cur)
  15. {
  16. if (kot(cur->_data) < kot(data))
  17. {
  18. //kv比当前节点值大,向右走
  19. parent = cur;
  20. cur = cur->_right;
  21. }
  22. else if (kot(cur->_data) > kot(data))
  23. {
  24. //kv比当前节点值小,向左走
  25. parent = cur;
  26. cur = cur->_left;
  27. }
  28. else
  29. {
  30. //kv和当前节点值相等,已存在,插入失败
  31. return make_pair(cur, false);
  32. }
  33. }
  34. //2.走到这里,说明kv在树中不存在,需要插入kv,并且cur已经为空,parent已经是叶子节点了
  35. Node* newNode = new Node(kv);
  36. newNode->_col = RED;
  37. if (kot(parent->_data) < kot(data))
  38. {
  39. //kv比parent值大,插入到parent的右边
  40. parent->_right = newNode;
  41. newNode->_parent = parent;
  42. }
  43. else
  44. {
  45. //kv比parent值小,插入到parent的左边
  46. parent->_left = newNode;
  47. newNode->_parent = parent;
  48. }
  49. cur = newNode;
  50. //如果父亲存在,且父亲颜色为红就要处理
  51. while (parent && parent->_col == RED)
  52. {
  53. //情况一和情况二、三的区别关键看叔叔
  54. Node* grandfather = parent->_parent;//当父亲是红色时,根据规则(2)根节点一定是黑色,祖父一定存在
  55. if (parent == grandfather->_left)//父亲是祖父的左子树
  56. {
  57. Node* uncle = grandfather->_right;
  58. //情况一:叔叔存在且为红
  59. if (uncle->_col == RED)
  60. {
  61. parent->_col = uncle->_col = BLACK;
  62. grandfather->_col = RED;
  63. //继续向上调整
  64. cur = grandfather;
  65. parent = cur->_parent;
  66. }
  67. else//情况二+情况三:叔叔不存在或叔叔存在且为黑
  68. {
  69. //情况二:单旋
  70. if (cur == parent->_left)
  71. {
  72. RotateR(grandfather);
  73. parent->_col = BLACK;
  74. grandfather->_col = RED;
  75. }
  76. else//情况三:双旋
  77. {
  78. RotateL(parent);
  79. RotateR(grandfather);
  80. cur->_col = BLACK;
  81. grandfather->_col = RED;
  82. }
  83. break;//插入结束
  84. }
  85. }
  86. else//父亲是祖父的右子树
  87. {
  88. Node* uncle = grandfather->_left;
  89. //情况一:叔叔存在且为红
  90. if (uncle && uncle->_col == RED)
  91. {
  92. parent->_col = uncle->_col = BLACK;
  93. grandfather->_col = RED;
  94. //继续往上调整
  95. cur = grandfather;
  96. parent = grandfather->_parent;
  97. }
  98. else//情况二+情况三:叔叔不存在或叔叔存在且为黑
  99. {
  100. //情况二:单旋
  101. if (cur == parent->_right)
  102. {
  103. RotateL(grandfather);
  104. parent->_col = BLACK;
  105. grandfather->_col = RED;
  106. }
  107. else//情况三:双旋
  108. {
  109. RotateR(parent);
  110. RotateL(grandfather);
  111. cur->_col = BLACK;
  112. grandfather->_col = RED;
  113. }
  114. break;//插入结束
  115. }
  116. }
  117. }
  118. _root->_col = BLACK;
  119. return make_pair(newNode, true);
  120. }
  121. void RotateR(Node* parent)
  122. {
  123. Node* subL = parent->_left;
  124. Node* subLR = nullptr;
  125. if (subL)
  126. {
  127. subLR = subL->_right;
  128. }
  129. //1.左子树的右子树变我的左子树
  130. parent->_left = subLR;
  131. if (subLR)
  132. {
  133. subLR->_parent = parent;
  134. }
  135. //左子树变父亲
  136. subL->_right = parent;
  137. Node* parentParent = parent->_parent;
  138. parent->_parent = subL;
  139. if (parent == _root)//parent是根
  140. {
  141. _root = subL;
  142. _root->_parent = nullptr;
  143. }
  144. else//parent不是根,是子树
  145. {
  146. if (parentParent->_left == parent)
  147. {
  148. //parent是自己父亲的左子树,将subL作为parent父亲的左孩子
  149. parentParent->_left = subL;
  150. }
  151. else
  152. {
  153. //parent是自己父亲的右子树,将subL作为parent父亲的右孩子
  154. parentParent->_right = subL;
  155. }
  156. //subL的父亲就是parent的父亲
  157. subL->_parent = parentParent;
  158. }
  159. }
  160. void RotateL(Node* parent)
  161. {
  162. Node* subR = parent->_right;
  163. Node* subRL = nullptr;
  164. if (subR)
  165. {
  166. subRL = subR->_left;
  167. }
  168. //1.右子树的左子树变我的右子树
  169. parent->_right = subRL;
  170. if (subRL)
  171. {
  172. subRL->_parent = parent;
  173. }
  174. //2.右子树变父亲
  175. subR->_left = parent;
  176. Node* parentParent = parent->_parent;
  177. parent->_parent = subR;
  178. if (parent == _root)//parent是根
  179. {
  180. _root = parent;
  181. _root->_parent = nullptr;
  182. }
  183. else//parent不是根,是子树
  184. {
  185. if (parentParent->_left == parent)
  186. {
  187. //parent是自己父亲的左子树,将subR作为parent父亲的左孩子
  188. parentParent->_left = subR;
  189. }
  190. else
  191. {
  192. //parent是自己父亲的右子树,将subR作为parent父亲的右孩子
  193. parentParent->_right = subR;
  194. }
  195. //subR的父亲就是parent的父亲
  196. subR->_parent = parentParent;
  197. }
  198. }

(5)修改红黑树查找

  1. //查找
  2. Node* Find(const K& key)
  3. {
  4. KeyOfT kot;
  5. Node* cur = _root;
  6. while (cur)
  7. {
  8. if (kot(cur->_data) < key)
  9. {
  10. cur = cur->_right;
  11. }
  12. else if (kot(cur->_data) > key)
  13. {
  14. cur = cur->_left;
  15. }
  16. else
  17. {
  18. return cur;
  19. }
  20. }
  21. return nullptr;//空树,直接返回
  22. }

三、红黑树迭代器

map和set的迭代器的实现其实本质上是红黑树迭代器的实现,迭代器的实现需要定义模板类型、模板类型引用、模板类型指针。 

1.红黑树中迭代器重命名

 在红黑树中重命名模板类型、模板类型引用、模板类型指针,定义为public,外部就能使用iterator了:

  1. template<class K, class T, class KeyOfT>
  2. class RBTree
  3. {
  4. typedef RBTreeNode<T> Node;
  5. public:
  6. typedef __TreeIterator<T, T&, T*> iterator;//模板类型、模板类型引用、模板类型指针
  7. //红黑树函数...
  8. private:
  9. Node* _root;
  10. };

2.正向迭代器定义

红黑树的迭代器的本质是对节点指针进行封装,所以迭代器中只有封装红黑树节点指针这一个成员变量 。正向迭代器:

  1. template<class T,class Ref,class ptr>
  2. struct __TreeIterator
  3. {
  4. typedef RBTreeNode<T> Node;
  5. typedef __TreeIterator<T, Ref, ptr> Self;
  6. Node* _node;//成员变量
  7. };

3.迭代器构造 

用节点指针构造正向迭代器:

  1. //构造函数
  2. __TreeIterator(Node* node)
  3. :_node(node)
  4. {}

4.正向迭代器重载* 

Ref对正向迭代器解引用,返回节点数据引用:

  1. //* 解引用,返回节点数据
  2. Ref Operator*()
  3. {
  4. return _node->_data;
  5. }

5.正向迭代器重载-> 

Ptr对正向迭代器使用->,返回节点数据指针:

  1. //-> 返回节点数据地址
  2. Ptr Operator->()
  3. {
  4. return &_node->_data;
  5. }

6.正向迭代器重载==

判断节点是否相同 

  1. //判断两个迭代器是否相同
  2. bool operator==(const Self& s)
  3. {
  4. return _node == s._node;//判断节点是否相同
  5. }

7.正向迭代器重载!=

判断节点是否不同 

  1. //判断两个迭代器是否不同
  2. bool operator!=(const Self& s)
  3. {
  4. return _node != s._node;//判断节点是否不同
  5. }

8.正向迭代器++

 ①当节点的右子树不为空时,++就要走到右子树的最左节点

 ②当节点的右子树为空时,++就要走到节点的父亲

  1. //红黑树迭代器的++也就是红黑树的++
  2. Self operator++()
  3. {
  4. //1.右子树不为空
  5. if (_node->_right)
  6. {
  7. //下一个访问的是右树的中序第一个节点(即右子树最左节点)。
  8. Node* left = _node->_right;
  9. //找最左节点
  10. while (left->_left)
  11. {
  12. left = left->_left;
  13. }
  14. _node = left;
  15. }
  16. else//2.右子树为空,下一个访问的就是当前节点的父亲
  17. {
  18. Node* cur = _node;
  19. Node* parent = cur->_parent;
  20. while (parent && cur == parent->_right)
  21. {
  22. cur = cur->_parent;
  23. parent = parent->_parent;
  24. }
  25. _node = parent;
  26. }
  27. return *this;
  28. }
  29. };

9.正向迭代器--

 ①当节点的左子树不为空时,++就要走到左子树的最右节点

 ②当节点的左子树为空时,++就要走到节点的父亲

  1. //红黑树迭代器的--也就是红黑树的--
  2. Self operator--()
  3. {
  4. //1.左子树不为空
  5. if (_node->_left)
  6. {
  7. //下一个访问的是左树的中序左后节点(即做子树最右节点)。
  8. Node* right = _node->_left;
  9. //找最右节点
  10. while (right->_right)
  11. {
  12. right = right->_right;
  13. }
  14. _node = right;
  15. }
  16. else//2.左子树为空,下一个访问的就是当前节点的父亲
  17. {
  18. Node* cur = _node;
  19. Node* parent = cur->_parent;
  20. while (parent && cur == parent->_left)
  21. {
  22. cur = cur->_parent;
  23. parent = parent->_parent;
  24. }
  25. _node = parent;
  26. }
  27. return *this;
  28. }

10.红黑树中实现迭代器

 实现begin( )找最左节点,end( )最后一个节点的下一个位置

  1. template<class K, class T, class KeyOfT>
  2. class RBTree
  3. {
  4. typedef RBTreeNode<T> Node;
  5. public:
  6. typedef __TreeIterator<T, T&, T*> iterator;//模板类型、模板类型引用、模板类型指针
  7. //找最左节点
  8. iterator begin()
  9. {
  10. Node* left = _root;
  11. while (left && left->_left)
  12. {
  13. left = left->_left;
  14. }
  15. return iterator(left)//返回最左节点的正向迭代器
  16. }
  17. //结束
  18. iterator end()
  19. {
  20. return iterator(nullptr);
  21. }
  22. private:
  23. Node* _root;
  24. };

四、set模拟实现

调用红黑树对应接口实现set,插入和查找函数返回值当中的节点指针改为迭代器:

  1. #pragma once
  2. #include "RBTree.h"
  3. namespace delia
  4. {
  5. template<class K>
  6. class set
  7. {
  8. //仿函数,获取set的key
  9. struct SetKeyOfT
  10. {
  11. const K& operator()(const K& key)
  12. {
  13. return key;
  14. }
  15. };
  16. public:
  17. typedef typename RBTree<K, K, SetKeyOfT>::iterator iterator;
  18. //迭代器开始
  19. iterator begin()
  20. {
  21. return _t.begin();
  22. }
  23. //迭代器结束
  24. iterator end()
  25. {
  26. return _t.end();
  27. }
  28. //插入函数
  29. pair<iterator,bool> insert(const K& key)
  30. {
  31. return _t.Insert(key);
  32. }
  33. //查找
  34. iterator find(const K& key)
  35. {
  36. return _t.find(key);
  37. }
  38. private:
  39. RBTree<K, K, SetKeyOfT> _t;
  40. };
  41. }

五、map模拟实现

调用红黑树对应接口实现map,插入和查找函数返回值当中的节点指针改为迭代器,增加operator[ ]的重载:

  1. #pragma once
  2. #include "RBTree.h"
  3. namespace delia
  4. {
  5. template<class K, class V>
  6. class map
  7. {
  8. //仿函数,获取map的first
  9. struct MapKeyOfT
  10. {
  11. const K& operator()(const pair<const K, V>& kv)
  12. {
  13. return kv.first;
  14. }
  15. };
  16. public:
  17. typedef typename RBTree<K, K, MapKeyOfT>::iterator iterator;
  18. //迭代器开始
  19. iterator begin()
  20. {
  21. return _t.begin();
  22. }
  23. //迭代器结束
  24. iterator end()
  25. {
  26. return _t.end();
  27. }
  28. //插入
  29. pair<iterator, bool> insert(const pair<const K, V>& kv)
  30. {
  31. return _t.Insert(kv);
  32. }
  33. //重载operator[]
  34. V& operator[](const K& key)
  35. {
  36. pair<iterator, bool> ret = insert(make_pair(key, V()));
  37. iterator it = ret.first;
  38. return it->second;
  39. }
  40. //查找
  41. iterator find(const K& key)
  42. {
  43. return _t.find(key);
  44. }
  45. private:
  46. RBTree<K, pair<const K, V>, MapKeyOfT> _t;
  47. };
  48. }

六、红黑树完整代码段

  1. #pragma once
  2. #include<iostream>
  3. using namespace std;
  4. //节点颜色
  5. enum Colour
  6. {
  7. RED,
  8. BLACK,
  9. };
  10. //红黑树节点定义
  11. template<class T>
  12. struct RBTreeNode
  13. {
  14. RBTreeNode<T>* _left;//节点的左孩子
  15. RBTreeNode<T>* _right;//节点的右孩子
  16. RBTreeNode<T>* _parent;//节点的父亲
  17. T _data;//节点的值
  18. Colour _col;//节点颜色
  19. RBTreeNode(const T& x)
  20. :_left(nullptr)
  21. , _right(nullptr)
  22. , _parent(nullptr)
  23. , _data(x)
  24. , _col(RED)
  25. {}
  26. };
  27. template<class T,class Ref,class ptr>
  28. struct __TreeIterator
  29. {
  30. typedef RBTreeNode<T> Node;
  31. typedef __TreeIterator<T, Ref, ptr> Self;
  32. Node* _node;
  33. //构造函数
  34. __TreeIterator(Node* node)
  35. :_node(node)
  36. {}
  37. //* 解引用,返回节点数据
  38. Ref operator*()
  39. {
  40. return _node->_data;
  41. }
  42. //-> 返回节点数据地址
  43. //Ptr operator->()
  44. //{
  45. // return &_node->_data;
  46. //}
  47. //判断两个迭代器是否相同
  48. bool operator==(const Self& s)
  49. {
  50. return _node == s._node;
  51. }
  52. //判断两个迭代器是否不同
  53. bool operator!=(const Self& s)
  54. {
  55. return _node != s._node;
  56. }
  57. //红黑树迭代器的++也就是红黑树的++
  58. Self operator++()
  59. {
  60. //1.右子树不为空
  61. if (_node->_right)
  62. {
  63. //下一个访问的是右树的中序第一个节点(即右子树最左节点)。
  64. Node* left = _node->_right;
  65. //找最左节点
  66. while (left->_left)
  67. {
  68. left = left->_left;
  69. }
  70. _node = left;
  71. }
  72. else//2.右子树为空,下一个访问的就是当前节点的父亲
  73. {
  74. Node* cur = _node;
  75. Node* parent = cur->_parent;
  76. while (parent && cur == parent->_right)
  77. {
  78. cur = cur->_parent;
  79. parent = parent->_parent;
  80. }
  81. _node = parent;
  82. }
  83. return *this;
  84. }
  85. //红黑树迭代器的--也就是红黑树的--
  86. Self operator--()
  87. {
  88. //1.左子树不为空
  89. if (_node->_left)
  90. {
  91. //下一个访问的是左树的中序左后节点(即做子树最右节点)。
  92. Node* right = _node->_left;
  93. //找最右节点
  94. while (right->_right)
  95. {
  96. right = right->_right;
  97. }
  98. _node = right;
  99. }
  100. else//2.左子树为空,下一个访问的就是当前节点的父亲
  101. {
  102. Node* cur = _node;
  103. Node* parent = cur->_parent;
  104. while (parent && cur == parent->_left)
  105. {
  106. cur = cur->_parent;
  107. parent = parent->_parent;
  108. }
  109. _node = parent;
  110. }
  111. return *this;
  112. }
  113. };
  114. //插入节点颜色是红色好,还是黑色好,红色
  115. //因为插入红色节点,可能破坏规则3,影响不大
  116. //插入黑色节点,一定破坏规则4 ,并且影响其他路径,影响很大
  117. template<class K, class T, class KeyOfT>
  118. class RBTree
  119. {
  120. typedef RBTreeNode<T> Node;
  121. public:
  122. typedef __TreeIterator<T, T&, T*> iterator;//模板类型、模板类型引用、模板类型指针
  123. //构造函数
  124. RBTree()
  125. :_root(nullpte)
  126. {}
  127. //析构
  128. ~RBTree()
  129. {
  130. _Destroy(_root);
  131. _root = nullptr;
  132. }
  133. void _Destroy(Node* root)
  134. {
  135. if (root == nullptr)
  136. {
  137. return;
  138. }
  139. _Destroy(root->_left);
  140. _Destroy(root->_right);
  141. delete root;
  142. }
  143. //找最左节点
  144. iterator begin()
  145. {
  146. Node* left = _root;
  147. while (left && left->_left)
  148. {
  149. left = left->_left;
  150. }
  151. return iterator(left);//返回最左节点的正向迭代器
  152. }
  153. //结束
  154. iterator end()
  155. {
  156. return iterator(nullptr);
  157. }
  158. //构造函数
  159. RBTree()
  160. :_root(nullptr)
  161. {}
  162. void Destroy(Node* root)
  163. {
  164. if (root == nullptr)
  165. {
  166. return;
  167. }
  168. Destroy(root->_left);
  169. Destroy(root->_right);
  170. }
  171. ~RBTree()
  172. {
  173. Destroy(_root);
  174. _root = nullptr;
  175. }
  176. //插入
  177. pair<Node*, bool> Insert(const T& data)
  178. {
  179. if (_root == nullptr)
  180. {
  181. _root = new Node(data);
  182. _root->_col = BLACK;
  183. return make_pair(_root, true);
  184. }
  185. KeyOfT kot;
  186. //1.先看树中,kv是否存在
  187. Node* parent = nullptr;
  188. Node* cur = _root;
  189. while (cur)
  190. {
  191. if (kot(cur->_data) < kot(data))
  192. {
  193. //kv比当前节点值大,向右走
  194. parent = cur;
  195. cur = cur->_right;
  196. }
  197. else if (kot(cur->_data) > kot(data))
  198. {
  199. //kv比当前节点值小,向左走
  200. parent = cur;
  201. cur = cur->_left;
  202. }
  203. else
  204. {
  205. //kv和当前节点值相等,已存在,插入失败
  206. return make_pair(cur, false);
  207. }
  208. }
  209. //2.走到这里,说明kv在树中不存在,需要插入kv,并且cur已经为空,parent已经是叶子节点了
  210. Node* newNode = new Node(data);
  211. newNode->_col = RED;
  212. if (kot(parent->_data) < kot(data))
  213. {
  214. //kv比parent值大,插入到parent的右边
  215. parent->_right = newNode;
  216. newNode->_parent = parent;
  217. }
  218. else
  219. {
  220. //kv比parent值小,插入到parent的左边
  221. parent->_left = newNode;
  222. newNode->_parent = parent;
  223. }
  224. cur = newNode;
  225. //如果父亲存在,且父亲颜色为红就要处理
  226. while (parent && parent->_col == RED)
  227. {
  228. //情况一和情况二、三的区别关键看叔叔
  229. Node* grandfather = parent->_parent;//当父亲是红色时,根据规则(2)根节点一定是黑色,祖父一定存在
  230. if (parent == grandfather->_left)//父亲是祖父的左子树
  231. {
  232. Node* uncle = grandfather->_right;
  233. //情况一:叔叔存在且为红
  234. if (uncle->_col == RED)
  235. {
  236. parent->_col = uncle->_col = BLACK;
  237. grandfather->_col = RED;
  238. //继续向上调整
  239. cur = grandfather;
  240. parent = cur->_parent;
  241. }
  242. else//情况二+情况三:叔叔不存在或叔叔存在且为黑
  243. {
  244. //情况二:单旋
  245. if (cur == parent->_left)
  246. {
  247. RotateR(grandfather);
  248. parent->_col = BLACK;
  249. grandfather->_col = RED;
  250. }
  251. else//情况三:双旋
  252. {
  253. RotateL(parent);
  254. RotateR(grandfather);
  255. cur->_col = BLACK;
  256. grandfather->_col = RED;
  257. }
  258. break;//插入结束
  259. }
  260. }
  261. else//父亲是祖父的右子树
  262. {
  263. Node* uncle = grandfather->_left;
  264. //情况一:叔叔存在且为红
  265. if (uncle && uncle->_col == RED)
  266. {
  267. parent->_col = uncle->_col = BLACK;
  268. grandfather->_col = RED;
  269. //继续往上调整
  270. cur = grandfather;
  271. parent = grandfather->_parent;
  272. }
  273. else//情况二+情况三:叔叔不存在或叔叔存在且为黑
  274. {
  275. //情况二:单旋
  276. if (cur == parent->_right)
  277. {
  278. RotateL(grandfather);
  279. parent->_col = BLACK;
  280. grandfather->_col = RED;
  281. }
  282. else//情况三:双旋
  283. {
  284. RotateR(parent);
  285. RotateL(grandfather);
  286. cur->_col = BLACK;
  287. grandfather->_col = RED;
  288. }
  289. break;//插入结束
  290. }
  291. }
  292. }
  293. _root->_col = BLACK;
  294. return make_pair(newNode, true);
  295. }
  296. void RotateR(Node* parent)
  297. {
  298. Node* subL = parent->_left;
  299. Node* subLR = nullptr;
  300. if (subL)
  301. {
  302. subLR = subL->_right;
  303. }
  304. //1.左子树的右子树变我的左子树
  305. parent->_left = subLR;
  306. if (subLR)
  307. {
  308. subLR->_parent = parent;
  309. }
  310. //左子树变父亲
  311. subL->_right = parent;
  312. Node* parentParent = parent->_parent;
  313. parent->_parent = subL;
  314. if (parent == _root)//parent是根
  315. {
  316. _root = subL;
  317. _root->_parent = nullptr;
  318. }
  319. else//parent不是根,是子树
  320. {
  321. if (parentParent->_left == parent)
  322. {
  323. //parent是自己父亲的左子树,将subL作为parent父亲的左孩子
  324. parentParent->_left = subL;
  325. }
  326. else
  327. {
  328. //parent是自己父亲的右子树,将subL作为parent父亲的右孩子
  329. parentParent->_right = subL;
  330. }
  331. //subL的父亲就是parent的父亲
  332. subL->_parent = parentParent;
  333. }
  334. }
  335. void RotateL(Node* parent)
  336. {
  337. Node* subR = parent->_right;
  338. Node* subRL = nullptr;
  339. if (subR)
  340. {
  341. subRL = subR->_left;
  342. }
  343. //1.右子树的左子树变我的右子树
  344. parent->_right = subRL;
  345. if (subRL)
  346. {
  347. subRL->_parent = parent;
  348. }
  349. //2.右子树变父亲
  350. subR->_left = parent;
  351. Node* parentParent = parent->_parent;
  352. parent->_parent = subR;
  353. if (parent == _root)//parent是根
  354. {
  355. _root = parent;
  356. _root->_parent = nullptr;
  357. }
  358. else//parent不是根,是子树
  359. {
  360. if (parentParent->_left == parent)
  361. {
  362. //parent是自己父亲的左子树,将subR作为parent父亲的左孩子
  363. parentParent->_left = subR;
  364. }
  365. else
  366. {
  367. //parent是自己父亲的右子树,将subR作为parent父亲的右孩子
  368. parentParent->_right = subR;
  369. }
  370. //subR的父亲就是parent的父亲
  371. subR->_parent = parentParent;
  372. }
  373. }
  374. //查找
  375. Node* Find(const K& key)
  376. {
  377. KeyOfT kot;
  378. Node* cur = _root;
  379. while (cur)
  380. {
  381. if (kot(cur->_data) < key)
  382. {
  383. cur = cur->_right;
  384. }
  385. else if (kot(cur->_data) > key)
  386. {
  387. cur = cur->_left;
  388. }
  389. else
  390. {
  391. return cur;
  392. }
  393. }
  394. return nullptr;//空树,直接返回
  395. }
  396. bool _CheckBalance(Node* root, int blackNum, int count)
  397. {
  398. if (root == nullptr)
  399. {
  400. if (count != blackNum)
  401. {
  402. cout << "黑色节点数量不相等" << endl;
  403. return false;
  404. }
  405. return true;
  406. }
  407. if (root->_col == RED && root->_parent->_col == RED)
  408. {
  409. cout << "存在连续红色节点" << endl;
  410. return false;
  411. }
  412. if (root->_col == BLACK)
  413. {
  414. count++;
  415. }
  416. return _CheckBalance(root->_left, blackNum, count)
  417. && _CheckBalance(root->_right, blackNum, count);
  418. }
  419. //检查是否平衡
  420. bool CheckBalance()
  421. {
  422. if (_root == nullptr)
  423. {
  424. return true;
  425. }
  426. if (_root->_col == RED)
  427. {
  428. cout << "根节点为红色" << endl;
  429. return false;
  430. }
  431. //找最左路径做黑色节点数量参考值
  432. int blackNum = 0;
  433. Node* left = _root;
  434. while (left)
  435. {
  436. if (left->_col == BLACK)
  437. {
  438. blackNum++;
  439. }
  440. left = left->_left;
  441. }
  442. int count = 0;
  443. return _CheckBalance(_root, blackNum, count);
  444. }
  445. //遍历
  446. void _InOrder(Node* root)
  447. {
  448. if (root == nullptr)
  449. {
  450. return;
  451. }
  452. _InOrder(root->_left);
  453. cout << root->_kv.first << ":" << root->_kv.second << endl;
  454. _InOrder(root->_right);
  455. }
  456. void InOrder()
  457. {
  458. _InOrder(_root);
  459. cout << endl;
  460. }
  461. private:
  462. Node* _root;
  463. };

验证代码:

  1. #pragma once
  2. #include "RBTree.h"
  3. #include <vector>
  4. #include <stdlib.h>
  5. #include <time.h>
  6. #include "Map.h"
  7. #include "Set.h"
  8. int main()
  9. {
  10. delia::map<int, int> m;
  11. m.insert(make_pair(1, 1));
  12. m.insert(make_pair(3, 3));
  13. m.insert(make_pair(0, 0));
  14. m.insert(make_pair(9, 9));
  15. delia::set<int> s;
  16. s.insert(1);
  17. s.insert(5);
  18. s.insert(2);
  19. s.insert(1);
  20. s.insert(13);
  21. s.insert(0);
  22. s.insert(15);
  23. s.insert(18);
  24. delia::set<int>::iterator sit = s.begin();
  25. while (sit != s.end())
  26. {
  27. cout << *sit << " ";
  28. ++sit;
  29. }
  30. cout << endl;
  31. return 0;
  32. }

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

闽ICP备14008679号