rbtree_algorithms.hpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Olaf Krzikalla 2004-2006.
  4. // (C) Copyright Ion Gaztanaga 2006-2014.
  5. //
  6. // Distributed under the Boost Software License, Version 1.0.
  7. // (See accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. // See http://www.boost.org/libs/intrusive for documentation.
  11. //
  12. /////////////////////////////////////////////////////////////////////////////
  13. //
  14. // The tree destruction algorithm is based on Julienne Walker and The EC Team code:
  15. //
  16. // This code is in the public domain. Anyone may use it or change it in any way that
  17. // they see fit. The author assumes no responsibility for damages incurred through
  18. // use of the original code or any variations thereof.
  19. //
  20. // It is requested, but not required, that due credit is given to the original author
  21. // and anyone who has modified the code through a header comment, such as this one.
  22. #ifndef BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP
  23. #define BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP
  24. #include <boost/intrusive/detail/config_begin.hpp>
  25. #include <boost/intrusive/intrusive_fwd.hpp>
  26. #include <cstddef>
  27. #include <boost/intrusive/detail/assert.hpp>
  28. #include <boost/intrusive/detail/algo_type.hpp>
  29. #include <boost/intrusive/bstree_algorithms.hpp>
  30. #include <boost/intrusive/detail/ebo_functor_holder.hpp>
  31. #if defined(BOOST_HAS_PRAGMA_ONCE)
  32. # pragma once
  33. #endif
  34. namespace boost {
  35. namespace intrusive {
  36. #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  37. template<class NodeTraits, class F>
  38. struct rbtree_node_cloner
  39. //Use public inheritance to avoid MSVC bugs with closures
  40. : public detail::ebo_functor_holder<F>
  41. {
  42. typedef typename NodeTraits::node_ptr node_ptr;
  43. typedef detail::ebo_functor_holder<F> base_t;
  44. explicit rbtree_node_cloner(F f)
  45. : base_t(f)
  46. {}
  47. node_ptr operator()(const node_ptr & p)
  48. {
  49. node_ptr n = base_t::get()(p);
  50. NodeTraits::set_color(n, NodeTraits::get_color(p));
  51. return n;
  52. }
  53. };
  54. namespace detail {
  55. template<class ValueTraits, class NodePtrCompare, class ExtraChecker>
  56. struct rbtree_node_checker
  57. : public bstree_node_checker<ValueTraits, NodePtrCompare, ExtraChecker>
  58. {
  59. typedef bstree_node_checker<ValueTraits, NodePtrCompare, ExtraChecker> base_checker_t;
  60. typedef ValueTraits value_traits;
  61. typedef typename value_traits::node_traits node_traits;
  62. typedef typename node_traits::const_node_ptr const_node_ptr;
  63. typedef typename node_traits::node_ptr node_ptr;
  64. struct return_type
  65. : public base_checker_t::return_type
  66. {
  67. return_type() : black_count_(0) {}
  68. std::size_t black_count_;
  69. };
  70. rbtree_node_checker(const NodePtrCompare& comp, ExtraChecker extra_checker)
  71. : base_checker_t(comp, extra_checker)
  72. {}
  73. void operator () (const const_node_ptr& p,
  74. const return_type& check_return_left, const return_type& check_return_right,
  75. return_type& check_return)
  76. {
  77. if (node_traits::get_color(p) == node_traits::red()){
  78. //Red nodes have black children
  79. const node_ptr p_left(node_traits::get_left(p)); (void)p_left;
  80. const node_ptr p_right(node_traits::get_right(p)); (void)p_right;
  81. BOOST_INTRUSIVE_INVARIANT_ASSERT(!p_left || node_traits::get_color(p_left) == node_traits::black());
  82. BOOST_INTRUSIVE_INVARIANT_ASSERT(!p_right || node_traits::get_color(p_right) == node_traits::black());
  83. //Red node can't be root
  84. BOOST_INTRUSIVE_INVARIANT_ASSERT(node_traits::get_parent(node_traits::get_parent(p)) != p);
  85. }
  86. //Every path to p contains the same number of black nodes
  87. const std::size_t l_black_count = check_return_left.black_count_;
  88. BOOST_INTRUSIVE_INVARIANT_ASSERT(l_black_count == check_return_right.black_count_);
  89. check_return.black_count_ = l_black_count +
  90. static_cast<std::size_t>(node_traits::get_color(p) == node_traits::black());
  91. base_checker_t::operator()(p, check_return_left, check_return_right, check_return);
  92. }
  93. };
  94. } // namespace detail
  95. #endif //#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  96. //! rbtree_algorithms provides basic algorithms to manipulate
  97. //! nodes forming a red-black tree. The insertion and deletion algorithms are
  98. //! based on those in Cormen, Leiserson, and Rivest, Introduction to Algorithms
  99. //! (MIT Press, 1990), except that
  100. //!
  101. //! (1) the header node is maintained with links not only to the root
  102. //! but also to the leftmost node of the tree, to enable constant time
  103. //! begin(), and to the rightmost node of the tree, to enable linear time
  104. //! performance when used with the generic set algorithms (set_union,
  105. //! etc.);
  106. //!
  107. //! (2) when a node being deleted has two children its successor node is
  108. //! relinked into its place, rather than copied, so that the only
  109. //! pointers invalidated are those referring to the deleted node.
  110. //!
  111. //! rbtree_algorithms is configured with a NodeTraits class, which encapsulates the
  112. //! information about the node to be manipulated. NodeTraits must support the
  113. //! following interface:
  114. //!
  115. //! <b>Typedefs</b>:
  116. //!
  117. //! <tt>node</tt>: The type of the node that forms the binary search tree
  118. //!
  119. //! <tt>node_ptr</tt>: A pointer to a node
  120. //!
  121. //! <tt>const_node_ptr</tt>: A pointer to a const node
  122. //!
  123. //! <tt>color</tt>: The type that can store the color of a node
  124. //!
  125. //! <b>Static functions</b>:
  126. //!
  127. //! <tt>static node_ptr get_parent(const_node_ptr n);</tt>
  128. //!
  129. //! <tt>static void set_parent(node_ptr n, node_ptr parent);</tt>
  130. //!
  131. //! <tt>static node_ptr get_left(const_node_ptr n);</tt>
  132. //!
  133. //! <tt>static void set_left(node_ptr n, node_ptr left);</tt>
  134. //!
  135. //! <tt>static node_ptr get_right(const_node_ptr n);</tt>
  136. //!
  137. //! <tt>static void set_right(node_ptr n, node_ptr right);</tt>
  138. //!
  139. //! <tt>static color get_color(const_node_ptr n);</tt>
  140. //!
  141. //! <tt>static void set_color(node_ptr n, color c);</tt>
  142. //!
  143. //! <tt>static color black();</tt>
  144. //!
  145. //! <tt>static color red();</tt>
  146. template<class NodeTraits>
  147. class rbtree_algorithms
  148. #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  149. : public bstree_algorithms<NodeTraits>
  150. #endif
  151. {
  152. public:
  153. typedef NodeTraits node_traits;
  154. typedef typename NodeTraits::node node;
  155. typedef typename NodeTraits::node_ptr node_ptr;
  156. typedef typename NodeTraits::const_node_ptr const_node_ptr;
  157. typedef typename NodeTraits::color color;
  158. /// @cond
  159. private:
  160. typedef bstree_algorithms<NodeTraits> bstree_algo;
  161. /// @endcond
  162. public:
  163. //! This type is the information that will be
  164. //! filled by insert_unique_check
  165. typedef typename bstree_algo::insert_commit_data insert_commit_data;
  166. #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  167. //! @copydoc ::boost::intrusive::bstree_algorithms::get_header(const const_node_ptr&)
  168. static node_ptr get_header(const const_node_ptr & n);
  169. //! @copydoc ::boost::intrusive::bstree_algorithms::begin_node
  170. static node_ptr begin_node(const const_node_ptr & header);
  171. //! @copydoc ::boost::intrusive::bstree_algorithms::end_node
  172. static node_ptr end_node(const const_node_ptr & header);
  173. //! @copydoc ::boost::intrusive::bstree_algorithms::swap_tree
  174. static void swap_tree(const node_ptr & header1, const node_ptr & header2);
  175. #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  176. //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(const node_ptr&,const node_ptr&)
  177. static void swap_nodes(const node_ptr & node1, const node_ptr & node2)
  178. {
  179. if(node1 == node2)
  180. return;
  181. node_ptr header1(bstree_algo::get_header(node1)), header2(bstree_algo::get_header(node2));
  182. swap_nodes(node1, header1, node2, header2);
  183. }
  184. //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(const node_ptr&,const node_ptr&,const node_ptr&,const node_ptr&)
  185. static void swap_nodes(const node_ptr & node1, const node_ptr & header1, const node_ptr & node2, const node_ptr & header2)
  186. {
  187. if(node1 == node2) return;
  188. bstree_algo::swap_nodes(node1, header1, node2, header2);
  189. //Swap color
  190. color c = NodeTraits::get_color(node1);
  191. NodeTraits::set_color(node1, NodeTraits::get_color(node2));
  192. NodeTraits::set_color(node2, c);
  193. }
  194. //! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(const node_ptr&,const node_ptr&)
  195. static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & new_node)
  196. {
  197. if(node_to_be_replaced == new_node)
  198. return;
  199. replace_node(node_to_be_replaced, bstree_algo::get_header(node_to_be_replaced), new_node);
  200. }
  201. //! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(const node_ptr&,const node_ptr&,const node_ptr&)
  202. static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & header, const node_ptr & new_node)
  203. {
  204. bstree_algo::replace_node(node_to_be_replaced, header, new_node);
  205. NodeTraits::set_color(new_node, NodeTraits::get_color(node_to_be_replaced));
  206. }
  207. //! @copydoc ::boost::intrusive::bstree_algorithms::unlink(const node_ptr&)
  208. static void unlink(const node_ptr& node)
  209. {
  210. node_ptr x = NodeTraits::get_parent(node);
  211. if(x){
  212. while(!is_header(x))
  213. x = NodeTraits::get_parent(x);
  214. erase(x, node);
  215. }
  216. }
  217. #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  218. //! @copydoc ::boost::intrusive::bstree_algorithms::unlink_leftmost_without_rebalance
  219. static node_ptr unlink_leftmost_without_rebalance(const node_ptr & header);
  220. //! @copydoc ::boost::intrusive::bstree_algorithms::unique(const const_node_ptr&)
  221. static bool unique(const const_node_ptr & node);
  222. //! @copydoc ::boost::intrusive::bstree_algorithms::size(const const_node_ptr&)
  223. static std::size_t size(const const_node_ptr & header);
  224. //! @copydoc ::boost::intrusive::bstree_algorithms::next_node(const node_ptr&)
  225. static node_ptr next_node(const node_ptr & node);
  226. //! @copydoc ::boost::intrusive::bstree_algorithms::prev_node(const node_ptr&)
  227. static node_ptr prev_node(const node_ptr & node);
  228. //! @copydoc ::boost::intrusive::bstree_algorithms::init(const node_ptr&)
  229. static void init(const node_ptr & node);
  230. #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  231. //! @copydoc ::boost::intrusive::bstree_algorithms::init_header(const node_ptr&)
  232. static void init_header(const node_ptr & header)
  233. {
  234. bstree_algo::init_header(header);
  235. NodeTraits::set_color(header, NodeTraits::red());
  236. }
  237. //! @copydoc ::boost::intrusive::bstree_algorithms::erase(const node_ptr&,const node_ptr&)
  238. static node_ptr erase(const node_ptr & header, const node_ptr & z)
  239. {
  240. typename bstree_algo::data_for_rebalance info;
  241. bstree_algo::erase(header, z, info);
  242. color new_z_color;
  243. if(info.y != z){
  244. new_z_color = NodeTraits::get_color(info.y);
  245. NodeTraits::set_color(info.y, NodeTraits::get_color(z));
  246. }
  247. else{
  248. new_z_color = NodeTraits::get_color(z);
  249. }
  250. //Rebalance rbtree if needed
  251. if(new_z_color != NodeTraits::red()){
  252. rebalance_after_erasure(header, info.x, info.x_parent);
  253. }
  254. return z;
  255. }
  256. //! @copydoc ::boost::intrusive::bstree_algorithms::clone(const const_node_ptr&,const node_ptr&,Cloner,Disposer)
  257. template <class Cloner, class Disposer>
  258. static void clone
  259. (const const_node_ptr & source_header, const node_ptr & target_header, Cloner cloner, Disposer disposer)
  260. {
  261. rbtree_node_cloner<NodeTraits, Cloner> new_cloner(cloner);
  262. bstree_algo::clone(source_header, target_header, new_cloner, disposer);
  263. }
  264. #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  265. //! @copydoc ::boost::intrusive::bstree_algorithms::clear_and_dispose(const node_ptr&,Disposer)
  266. template<class Disposer>
  267. static void clear_and_dispose(const node_ptr & header, Disposer disposer);
  268. //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
  269. template<class KeyType, class KeyNodePtrCompare>
  270. static node_ptr lower_bound
  271. (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
  272. //! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
  273. template<class KeyType, class KeyNodePtrCompare>
  274. static node_ptr upper_bound
  275. (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
  276. //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare)
  277. template<class KeyType, class KeyNodePtrCompare>
  278. static node_ptr find
  279. (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
  280. //! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
  281. template<class KeyType, class KeyNodePtrCompare>
  282. static std::pair<node_ptr, node_ptr> equal_range
  283. (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
  284. //! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool)
  285. template<class KeyType, class KeyNodePtrCompare>
  286. static std::pair<node_ptr, node_ptr> bounded_range
  287. (const const_node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp
  288. , bool left_closed, bool right_closed);
  289. //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
  290. template<class KeyType, class KeyNodePtrCompare>
  291. static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
  292. #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  293. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_upper_bound(const node_ptr&,const node_ptr&,NodePtrCompare)
  294. template<class NodePtrCompare>
  295. static node_ptr insert_equal_upper_bound
  296. (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp)
  297. {
  298. bstree_algo::insert_equal_upper_bound(h, new_node, comp);
  299. rebalance_after_insertion(h, new_node);
  300. return new_node;
  301. }
  302. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_lower_bound(const node_ptr&,const node_ptr&,NodePtrCompare)
  303. template<class NodePtrCompare>
  304. static node_ptr insert_equal_lower_bound
  305. (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp)
  306. {
  307. bstree_algo::insert_equal_lower_bound(h, new_node, comp);
  308. rebalance_after_insertion(h, new_node);
  309. return new_node;
  310. }
  311. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal(const node_ptr&,const node_ptr&,const node_ptr&,NodePtrCompare)
  312. template<class NodePtrCompare>
  313. static node_ptr insert_equal
  314. (const node_ptr & header, const node_ptr & hint, const node_ptr & new_node, NodePtrCompare comp)
  315. {
  316. bstree_algo::insert_equal(header, hint, new_node, comp);
  317. rebalance_after_insertion(header, new_node);
  318. return new_node;
  319. }
  320. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_before(const node_ptr&,const node_ptr&,const node_ptr&)
  321. static node_ptr insert_before
  322. (const node_ptr & header, const node_ptr & pos, const node_ptr & new_node)
  323. {
  324. bstree_algo::insert_before(header, pos, new_node);
  325. rebalance_after_insertion(header, new_node);
  326. return new_node;
  327. }
  328. //! @copydoc ::boost::intrusive::bstree_algorithms::push_back(const node_ptr&,const node_ptr&)
  329. static void push_back(const node_ptr & header, const node_ptr & new_node)
  330. {
  331. bstree_algo::push_back(header, new_node);
  332. rebalance_after_insertion(header, new_node);
  333. }
  334. //! @copydoc ::boost::intrusive::bstree_algorithms::push_front(const node_ptr&,const node_ptr&)
  335. static void push_front(const node_ptr & header, const node_ptr & new_node)
  336. {
  337. bstree_algo::push_front(header, new_node);
  338. rebalance_after_insertion(header, new_node);
  339. }
  340. #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  341. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const const_node_ptr&,const KeyType&,KeyNodePtrCompare,insert_commit_data&)
  342. template<class KeyType, class KeyNodePtrCompare>
  343. static std::pair<node_ptr, bool> insert_unique_check
  344. (const const_node_ptr & header, const KeyType &key
  345. ,KeyNodePtrCompare comp, insert_commit_data &commit_data);
  346. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const const_node_ptr&,const node_ptr&,const KeyType&,KeyNodePtrCompare,insert_commit_data&)
  347. template<class KeyType, class KeyNodePtrCompare>
  348. static std::pair<node_ptr, bool> insert_unique_check
  349. (const const_node_ptr & header, const node_ptr &hint, const KeyType &key
  350. ,KeyNodePtrCompare comp, insert_commit_data &commit_data);
  351. #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  352. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_commit(const node_ptr&,const node_ptr&,const insert_commit_data&)
  353. static void insert_unique_commit
  354. (const node_ptr & header, const node_ptr & new_value, const insert_commit_data &commit_data)
  355. {
  356. bstree_algo::insert_unique_commit(header, new_value, commit_data);
  357. rebalance_after_insertion(header, new_value);
  358. }
  359. //! @copydoc ::boost::intrusive::bstree_algorithms::is_header
  360. static bool is_header(const const_node_ptr & p)
  361. {
  362. return NodeTraits::get_color(p) == NodeTraits::red() &&
  363. bstree_algo::is_header(p);
  364. }
  365. /// @cond
  366. private:
  367. static void rebalance_after_erasure(const node_ptr & header, node_ptr x, node_ptr x_parent)
  368. {
  369. while(1){
  370. if(x_parent == header || (x && NodeTraits::get_color(x) != NodeTraits::black())){
  371. break;
  372. }
  373. //Don't cache x_is_leftchild or similar because x can be null and
  374. //equal to both x_parent_left and x_parent_right
  375. const node_ptr x_parent_left(NodeTraits::get_left(x_parent));
  376. if(x == x_parent_left){ //x is left child
  377. node_ptr w = NodeTraits::get_right(x_parent);
  378. BOOST_INTRUSIVE_INVARIANT_ASSERT(w);
  379. if(NodeTraits::get_color(w) == NodeTraits::red()){
  380. NodeTraits::set_color(w, NodeTraits::black());
  381. NodeTraits::set_color(x_parent, NodeTraits::red());
  382. bstree_algo::rotate_left(x_parent, w, NodeTraits::get_parent(x_parent), header);
  383. w = NodeTraits::get_right(x_parent);
  384. BOOST_INTRUSIVE_INVARIANT_ASSERT(w);
  385. }
  386. node_ptr const w_left (NodeTraits::get_left(w));
  387. node_ptr const w_right(NodeTraits::get_right(w));
  388. if((!w_left || NodeTraits::get_color(w_left) == NodeTraits::black()) &&
  389. (!w_right || NodeTraits::get_color(w_right) == NodeTraits::black())){
  390. NodeTraits::set_color(w, NodeTraits::red());
  391. x = x_parent;
  392. x_parent = NodeTraits::get_parent(x_parent);
  393. }
  394. else {
  395. if(!w_right || NodeTraits::get_color(w_right) == NodeTraits::black()){
  396. NodeTraits::set_color(w_left, NodeTraits::black());
  397. NodeTraits::set_color(w, NodeTraits::red());
  398. bstree_algo::rotate_right(w, w_left, NodeTraits::get_parent(w), header);
  399. w = NodeTraits::get_right(x_parent);
  400. BOOST_INTRUSIVE_INVARIANT_ASSERT(w);
  401. }
  402. NodeTraits::set_color(w, NodeTraits::get_color(x_parent));
  403. NodeTraits::set_color(x_parent, NodeTraits::black());
  404. const node_ptr new_wright(NodeTraits::get_right(w));
  405. if(new_wright)
  406. NodeTraits::set_color(new_wright, NodeTraits::black());
  407. bstree_algo::rotate_left(x_parent, NodeTraits::get_right(x_parent), NodeTraits::get_parent(x_parent), header);
  408. break;
  409. }
  410. }
  411. else {
  412. // same as above, with right_ <-> left_.
  413. node_ptr w = x_parent_left;
  414. if(NodeTraits::get_color(w) == NodeTraits::red()){
  415. NodeTraits::set_color(w, NodeTraits::black());
  416. NodeTraits::set_color(x_parent, NodeTraits::red());
  417. bstree_algo::rotate_right(x_parent, w, NodeTraits::get_parent(x_parent), header);
  418. w = NodeTraits::get_left(x_parent);
  419. BOOST_INTRUSIVE_INVARIANT_ASSERT(w);
  420. }
  421. node_ptr const w_left (NodeTraits::get_left(w));
  422. node_ptr const w_right(NodeTraits::get_right(w));
  423. if((!w_right || NodeTraits::get_color(w_right) == NodeTraits::black()) &&
  424. (!w_left || NodeTraits::get_color(w_left) == NodeTraits::black())){
  425. NodeTraits::set_color(w, NodeTraits::red());
  426. x = x_parent;
  427. x_parent = NodeTraits::get_parent(x_parent);
  428. }
  429. else {
  430. if(!w_left || NodeTraits::get_color(w_left) == NodeTraits::black()){
  431. NodeTraits::set_color(w_right, NodeTraits::black());
  432. NodeTraits::set_color(w, NodeTraits::red());
  433. bstree_algo::rotate_left(w, w_right, NodeTraits::get_parent(w), header);
  434. w = NodeTraits::get_left(x_parent);
  435. BOOST_INTRUSIVE_INVARIANT_ASSERT(w);
  436. }
  437. NodeTraits::set_color(w, NodeTraits::get_color(x_parent));
  438. NodeTraits::set_color(x_parent, NodeTraits::black());
  439. const node_ptr new_wleft(NodeTraits::get_left(w));
  440. if(new_wleft)
  441. NodeTraits::set_color(new_wleft, NodeTraits::black());
  442. bstree_algo::rotate_right(x_parent, NodeTraits::get_left(x_parent), NodeTraits::get_parent(x_parent), header);
  443. break;
  444. }
  445. }
  446. }
  447. if(x)
  448. NodeTraits::set_color(x, NodeTraits::black());
  449. }
  450. static void rebalance_after_insertion(const node_ptr & header, node_ptr p)
  451. {
  452. NodeTraits::set_color(p, NodeTraits::red());
  453. while(1){
  454. node_ptr p_parent(NodeTraits::get_parent(p));
  455. const node_ptr p_grandparent(NodeTraits::get_parent(p_parent));
  456. if(p_parent == header || NodeTraits::get_color(p_parent) == NodeTraits::black() || p_grandparent == header){
  457. break;
  458. }
  459. NodeTraits::set_color(p_grandparent, NodeTraits::red());
  460. node_ptr const p_grandparent_left (NodeTraits::get_left (p_grandparent));
  461. bool const p_parent_is_left_child = p_parent == p_grandparent_left;
  462. node_ptr const x(p_parent_is_left_child ? NodeTraits::get_right(p_grandparent) : p_grandparent_left);
  463. if(x && NodeTraits::get_color(x) == NodeTraits::red()){
  464. NodeTraits::set_color(x, NodeTraits::black());
  465. NodeTraits::set_color(p_parent, NodeTraits::black());
  466. p = p_grandparent;
  467. }
  468. else{ //Final step
  469. const bool p_is_left_child(NodeTraits::get_left(p_parent) == p);
  470. if(p_parent_is_left_child){ //p_parent is left child
  471. if(!p_is_left_child){ //p is right child
  472. bstree_algo::rotate_left_no_parent_fix(p_parent, p);
  473. //No need to link p and p_grandparent:
  474. // [NodeTraits::set_parent(p, p_grandparent) + NodeTraits::set_left(p_grandparent, p)]
  475. //as p_grandparent is not the header, another rotation is coming and p_parent
  476. //will be the left child of p_grandparent
  477. p_parent = p;
  478. }
  479. bstree_algo::rotate_right(p_grandparent, p_parent, NodeTraits::get_parent(p_grandparent), header);
  480. }
  481. else{ //p_parent is right child
  482. if(p_is_left_child){ //p is left child
  483. bstree_algo::rotate_right_no_parent_fix(p_parent, p);
  484. //No need to link p and p_grandparent:
  485. // [NodeTraits::set_parent(p, p_grandparent) + NodeTraits::set_right(p_grandparent, p)]
  486. //as p_grandparent is not the header, another rotation is coming and p_parent
  487. //will be the right child of p_grandparent
  488. p_parent = p;
  489. }
  490. bstree_algo::rotate_left(p_grandparent, p_parent, NodeTraits::get_parent(p_grandparent), header);
  491. }
  492. NodeTraits::set_color(p_parent, NodeTraits::black());
  493. break;
  494. }
  495. }
  496. NodeTraits::set_color(NodeTraits::get_parent(header), NodeTraits::black());
  497. }
  498. /// @endcond
  499. };
  500. /// @cond
  501. template<class NodeTraits>
  502. struct get_algo<RbTreeAlgorithms, NodeTraits>
  503. {
  504. typedef rbtree_algorithms<NodeTraits> type;
  505. };
  506. template <class ValueTraits, class NodePtrCompare, class ExtraChecker>
  507. struct get_node_checker<RbTreeAlgorithms, ValueTraits, NodePtrCompare, ExtraChecker>
  508. {
  509. typedef detail::rbtree_node_checker<ValueTraits, NodePtrCompare, ExtraChecker> type;
  510. };
  511. /// @endcond
  512. } //namespace intrusive
  513. } //namespace boost
  514. #include <boost/intrusive/detail/config_end.hpp>
  515. #endif //BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP