当前位置:   article > 正文

C++从零开始(day50)——RBTree模拟实现

C++从零开始(day50)——RBTree模拟实现

这是关于一个普通双非本科大一学生的C++的学习记录贴

在此前,我学了一点点C语言还有简单的数据结构,如果有小伙伴想和我一起学习的,可以私信我交流分享学习资料

那么开启正题

今天分享的是关于RBTree模拟实现

1.RBTree概念

RBTree(红黑树),是一种二叉搜索树,在每个结点增加一个存储标识结点颜色,可以是RED或者BLACK(因而得名),通过对任意一条叶子路径上的各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因而使近似平衡

2.RBTree的性质

1.根节点是黑色的 

2.没有相邻的红结点

3. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点 

4. 每个空结点都是黑色的

3.RBTree结点的定义

RBTree结点是一种三岔链,不仅存储了左右子树结点的指针,还要存储父亲结点的指针,当然还要存储结点颜色以及pair

  1. enum Colour
  2. {
  3. BLACK,
  4. RED
  5. };
  6. template<class K, class V>
  7. struct RBTreeNode
  8. {
  9. RBTreeNode<K, V>* _left;
  10. RBTreeNode<K, V>* _right;
  11. RBTreeNode<K, V>* _parent;
  12. pair<K, V> _kv;
  13. Colour _col;
  14. RBTreeNode(const pair<K, V>& kv)
  15. :_left(nullptr)
  16. , _right(nullptr)
  17. , _parent(nullptr)
  18. , _col(RED)
  19. , _kv(kv)
  20. {}
  21. };

4.RBLTree的插入

4.1插入流程

RBTree树插入数据可以分为两步

1.按照二叉搜索树的方式插入新结点

2.调整结点的颜色

在调节颜色时,有时需要旋转处理,旋转方式和我们刚学的AVLTree旋转方式一样

4.2插入情况

先按照二叉搜索树进行插入,当然注意颜色的处理

  1. bool Insert(const pair<K, V>& kv)
  2. {
  3. if (_root == nullptr)
  4. {
  5. _root = new Node(kv);
  6. _root->_col = BLACK;
  7. return true;
  8. }
  9. Node* parent = nullptr;
  10. Node* cur = _root;
  11. while (cur)
  12. {
  13. if (cur->_kv.first < kv.first)
  14. {
  15. parent = cur;
  16. cur = cur->_right;
  17. }
  18. else if (cur->_kv.first > kv.first)
  19. {
  20. parent = cur;
  21. cur = cur->_left;
  22. }
  23. else
  24. {
  25. return false;
  26. }
  27. }
  28. cur = new Node(kv);
  29. cur->_col = RED;
  30. if (parent->_kv.first < kv.first)
  31. {
  32. parent->_right = cur;
  33. cur->_parent = parent;
  34. }
  35. else
  36. {
  37. parent->_left = cur;
  38. cur->_parent = parent;
  39. }
  40. //。。。。。
  41. _root->_col = BLACK;
  42. return true;
  43. }

4.2.1叔叔为红色

当叔叔为红色时,把叔叔父亲变为黑,祖父变为红,往上继续迭代即可

4.2.1叔叔为黑色或不存在

当叔叔叔叔为黑色或不存在时,要进行旋转,旋转完成调色后,退出循环

  1. while (parent && parent->_col == RED)
  2. {
  3. Node* grandfater = parent->_parent;
  4. if (parent == grandfater->_left)
  5. {
  6. Node* uncle = grandfater->_right;
  7. // 情况一 uncle存在且为红
  8. if (uncle && uncle->_col == RED)
  9. {
  10. parent->_col = uncle->_col = BLACK;
  11. grandfater->_col = RED;
  12. cur = grandfater;
  13. parent = cur->_parent;
  14. }
  15. else
  16. {
  17. if (cur == parent->_left)
  18. {
  19. // 情况二
  20. RotateR(grandfater);
  21. parent->_col = BLACK;
  22. grandfater->_col = RED;
  23. }
  24. else
  25. {
  26. // 情况三
  27. RotateL(parent);
  28. RotateR(grandfater);
  29. cur->_col = BLACK;
  30. grandfater->_col = RED;
  31. }
  32. break;
  33. }
  34. }
  35. else // (parent == grandfater->_right)
  36. {
  37. Node* uncle = grandfater->_left;
  38. if (uncle && uncle->_col == RED)
  39. {
  40. parent->_col = uncle->_col = BLACK;
  41. grandfater->_col = RED;
  42. cur = grandfater;
  43. parent = cur->_parent;
  44. }
  45. else
  46. {
  47. // g
  48. // p
  49. // c
  50. if (cur == parent->_right)
  51. {
  52. RotateL(grandfater);
  53. parent->_col = BLACK;
  54. grandfater->_col = RED;
  55. }
  56. else
  57. {
  58. // g
  59. // p
  60. // c
  61. RotateR(parent);
  62. RotateL(grandfater);
  63. cur->_col = BLACK;
  64. grandfater->_col = RED;
  65. }
  66. break;
  67. }
  68. }
  69. }

注意::完成后,根可能为红色(违反红黑树性质),要处理为黑色

当然红黑树还有其他函数,以及迭代器,这些在后面模拟实现map和set里再深入探究

新手写博客,有不对的位置希望大佬们能够指出,也谢谢大家能看到这里,让我们一起学习进步吧!

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

闽ICP备14008679号