• 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* _left;
    10. RBTreeNode* _right;
    11. RBTreeNode* _parent;
    12. pair _kv;
    13. Colour _col;
    14. RBTreeNode(const pair& 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& 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里再深入探究

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

  • 相关阅读:
    Objective-C对象dealloc过程
    接口测试框架实战(四)| 搞定 Schema 断言
    Postman 支持 gRPC 了,继续领先 ~
    Web应用的工作原理
    wxpython 1-应用App(PyApp)
    python在centos7.x下建立虚拟环境
    使用EMD分解进行去噪
    MySQL学习(四)
    PyTorch安装以及VsCode重新连接矩池云时Tumx的使用问题
    【GoWeb项目-个人Blog】初始化数据库和日志
  • 原文地址:https://blog.csdn.net/2301_80764270/article/details/136669485