当前位置:   article > 正文

C++ 红黑树_c++ 红黑树在哪个库里

c++ 红黑树在哪个库里

红黑树的概念:

红黑树 ,一种 二叉搜索树 在每个结点上增加一个存储位表示结点的颜色,可以是 Red Black 。 通过着色方式的限制,可以确保没有一条路径会比其他路径的俩 倍还长 ,保证树是 接近平衡 的。
红黑树的性质:
1. 每个结点不是红色就是黑色
2. 根节点是黑色的 
3. 如果一个节点是红色的,则它的两个孩子结点是黑色的 
4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点 
5. 每个叶子结点都是黑色的 ( 指空结点)
定义红黑树节点:
  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. Colour _col;
  13. pair<K, V> _kv;
  14. RBTreeNode(const pair<K, V>& kv)
  15. :_left(nullptr)
  16. , _right(nullptr)
  17. , _parent(nullptr)
  18. , _col(RED)
  19. , _kv(kv)
  20. {}
  21. };

插入节点:

红黑树插入节点会发生增加节点后破坏了红黑树的性质的情况,需要变更某些节点的颜色,有时还要通过旋转改变红黑树的结构才能达到保持性质的目的。

插入节点时,先根据二叉搜索树的性质由节点定义知,新增节点默认为红色,如果新节点的父节点为黑色,已经满足性质不需要调整,如果父节点为红色,出现了连续的红色节点,需要调整,当前节点的叔叔节点对调整方式有很大影响,读者可在下文体会到。

具体分为下边这几种处理方式:

定义: 

             cur 为当前节点

             p为父节点

             g为爷节点

             u为叔节点

情况①:p,u为红,g为黑

p,u改为黑,g改为红,cur指向g,继续向上调整

情况②: p为红,g为黑,u不存在/u为黑  , p为g的左(右),cur为p的左(右)

u不存在时,cur为新增,以g为中心右(左)单旋   ,p,g都变色

u为黑时,cur不是新增,而是情况①变色导致的

情况③:p为红,g为黑,u不存在/u为黑  , p为g的左(右),cur为p的右(左)

以p为中心左(右)单旋,再执行情况②

最后要把根节点置为黑色,旋转的程序可参考这里

红黑树插入节点程序如下:

  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. // 新增节点,颜色是红色,可能破坏规则3,产生连续红色节点
  29. cur = new Node(kv);
  30. cur->_col = RED;
  31. if (parent->_kv.first < kv.first)
  32. {
  33. parent->_right = cur;
  34. cur->_parent = parent;
  35. }
  36. else
  37. {
  38. parent->_left = cur;
  39. cur->_parent = parent;
  40. }
  41. // 控制近似平衡
  42. while (parent && parent->_col == RED)
  43. {
  44. Node* grandfather = parent->_parent;
  45. if (parent == grandfather->_left)
  46. {
  47. Node* uncle = grandfather->_right;
  48. // 情况一:uncle存在且为红,进行变色处理,并继续往上更新处理
  49. if (uncle && uncle->_col == RED)
  50. {
  51. parent->_col = uncle->_col = BLACK;
  52. grandfather->_col = RED;
  53. cur = grandfather;
  54. parent = cur->_parent;
  55. } // 情况二+三:uncle不存在,或者存在且为黑,需要旋转+变色处理
  56. else
  57. {
  58. // 情况二:单旋+变色
  59. if (cur == parent->_left)
  60. {
  61. RotateR(grandfather);
  62. parent->_col = BLACK;
  63. grandfather->_col = RED;
  64. }
  65. else // 情况三:双旋 + 变色
  66. {
  67. RotateL(parent);
  68. RotateR(grandfather);
  69. cur->_col = BLACK;
  70. grandfather->_col = RED;
  71. }
  72. break;
  73. }
  74. }
  75. else // (parent == grandfather->_right)
  76. {
  77. Node* uncle = grandfather->_left;
  78. if (uncle && uncle->_col == RED)
  79. {
  80. parent->_col = uncle->_col = BLACK;
  81. grandfather->_col = RED;
  82. cur = grandfather;
  83. parent = cur->_parent;
  84. }
  85. else
  86. {
  87. if (parent->_right == cur)
  88. {
  89. RotateL(grandfather);
  90. parent->_col = BLACK;
  91. grandfather->_col = RED;
  92. }
  93. else
  94. {
  95. RotateR(parent);
  96. RotateL(grandfather);
  97. cur->_col = BLACK;
  98. grandfather->_col = RED;
  99. }
  100. break;
  101. }
  102. }
  103. }
  104. _root->_col = BLACK;
  105. return true;
  106. }

红黑树和AVL树的比较:

红黑树和 AVL 树都是高效的平衡二叉树,增删查改的时间复杂度都是 O(logn ) ,红黑树不追求绝对平衡,其 只需保证最长路径不超过最短路径的 2 倍,相对而言,降低了插入和旋转的次数,所以在经常进行增删的结构 中性能比 AVL 树更优,而且红黑树实现比较简单,占用的内存也少一些,所以实际运用红黑树更多。而AVL树对平衡的要求更加严格,所以查询的效率可能相对稍微快一些,在查询和修改频率比较均衡的情况下可以考虑使用。
红黑树的一些应用:
1. C++ STL -- map/set mutil_map/mutil_set
2. Java
3. Linux 内核

 

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

闽ICP备14008679号