rbtree_algorithms.hpp 23 KB

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