rbtree_algorithms.hpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  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. BOOST_INTRUSIVE_FORCEINLINE node_ptr operator()(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(node_ptr header1, node_ptr header2);
  175. #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  176. //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(node_ptr,node_ptr)
  177. static void swap_nodes(node_ptr node1, 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(node_ptr,node_ptr,node_ptr,node_ptr)
  185. static void swap_nodes(node_ptr node1, node_ptr header1, node_ptr node2, 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(node_ptr,node_ptr)
  195. static void replace_node(node_ptr node_to_be_replaced, 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(node_ptr,node_ptr,node_ptr)
  202. static void replace_node(node_ptr node_to_be_replaced, node_ptr header, 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(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(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(node_ptr)
  232. BOOST_INTRUSIVE_FORCEINLINE static void init_header(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(node_ptr,node_ptr)
  238. static node_ptr erase(node_ptr header, node_ptr z)
  239. {
  240. typename bstree_algo::data_for_rebalance info;
  241. bstree_algo::erase(header, z, info);
  242. rebalance_after_erasure(header, z, info);
  243. return z;
  244. }
  245. //! @copydoc ::boost::intrusive::bstree_algorithms::transfer_unique
  246. template<class NodePtrCompare>
  247. static bool transfer_unique
  248. (node_ptr header1, NodePtrCompare comp, node_ptr header2, node_ptr z)
  249. {
  250. typename bstree_algo::data_for_rebalance info;
  251. bool const transferred = bstree_algo::transfer_unique(header1, comp, header2, z, info);
  252. if(transferred){
  253. rebalance_after_erasure(header2, z, info);
  254. rebalance_after_insertion(header1, z);
  255. }
  256. return transferred;
  257. }
  258. //! @copydoc ::boost::intrusive::bstree_algorithms::transfer_equal
  259. template<class NodePtrCompare>
  260. static void transfer_equal
  261. (node_ptr header1, NodePtrCompare comp, node_ptr header2, node_ptr z)
  262. {
  263. typename bstree_algo::data_for_rebalance info;
  264. bstree_algo::transfer_equal(header1, comp, header2, z, info);
  265. rebalance_after_erasure(header2, z, info);
  266. rebalance_after_insertion(header1, z);
  267. }
  268. //! @copydoc ::boost::intrusive::bstree_algorithms::clone(const const_node_ptr&,node_ptr,Cloner,Disposer)
  269. template <class Cloner, class Disposer>
  270. static void clone
  271. (const_node_ptr source_header, node_ptr target_header, Cloner cloner, Disposer disposer)
  272. {
  273. rbtree_node_cloner<NodeTraits, Cloner> new_cloner(cloner);
  274. bstree_algo::clone(source_header, target_header, new_cloner, disposer);
  275. }
  276. #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  277. //! @copydoc ::boost::intrusive::bstree_algorithms::clear_and_dispose(const node_ptr&,Disposer)
  278. template<class Disposer>
  279. static void clear_and_dispose(const node_ptr & header, Disposer disposer);
  280. //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
  281. template<class KeyType, class KeyNodePtrCompare>
  282. static node_ptr lower_bound
  283. (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
  284. //! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
  285. template<class KeyType, class KeyNodePtrCompare>
  286. static node_ptr upper_bound
  287. (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
  288. //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare)
  289. template<class KeyType, class KeyNodePtrCompare>
  290. static node_ptr find
  291. (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
  292. //! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
  293. template<class KeyType, class KeyNodePtrCompare>
  294. static std::pair<node_ptr, node_ptr> equal_range
  295. (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
  296. //! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool)
  297. template<class KeyType, class KeyNodePtrCompare>
  298. static std::pair<node_ptr, node_ptr> bounded_range
  299. (const const_node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp
  300. , bool left_closed, bool right_closed);
  301. //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
  302. template<class KeyType, class KeyNodePtrCompare>
  303. static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
  304. #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  305. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_upper_bound(node_ptr,node_ptr,NodePtrCompare)
  306. template<class NodePtrCompare>
  307. static node_ptr insert_equal_upper_bound
  308. (node_ptr h, node_ptr new_node, NodePtrCompare comp)
  309. {
  310. bstree_algo::insert_equal_upper_bound(h, new_node, comp);
  311. rebalance_after_insertion(h, new_node);
  312. return new_node;
  313. }
  314. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_lower_bound(node_ptr,node_ptr,NodePtrCompare)
  315. template<class NodePtrCompare>
  316. static node_ptr insert_equal_lower_bound
  317. (node_ptr h, node_ptr new_node, NodePtrCompare comp)
  318. {
  319. bstree_algo::insert_equal_lower_bound(h, new_node, comp);
  320. rebalance_after_insertion(h, new_node);
  321. return new_node;
  322. }
  323. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal(node_ptr,node_ptr,node_ptr,NodePtrCompare)
  324. template<class NodePtrCompare>
  325. static node_ptr insert_equal
  326. (node_ptr header, node_ptr hint, node_ptr new_node, NodePtrCompare comp)
  327. {
  328. bstree_algo::insert_equal(header, hint, new_node, comp);
  329. rebalance_after_insertion(header, new_node);
  330. return new_node;
  331. }
  332. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_before(node_ptr,node_ptr,node_ptr)
  333. static node_ptr insert_before
  334. (node_ptr header, node_ptr pos, node_ptr new_node)
  335. {
  336. bstree_algo::insert_before(header, pos, new_node);
  337. rebalance_after_insertion(header, new_node);
  338. return new_node;
  339. }
  340. //! @copydoc ::boost::intrusive::bstree_algorithms::push_back(node_ptr,node_ptr)
  341. static void push_back(node_ptr header, node_ptr new_node)
  342. {
  343. bstree_algo::push_back(header, new_node);
  344. rebalance_after_insertion(header, new_node);
  345. }
  346. //! @copydoc ::boost::intrusive::bstree_algorithms::push_front(node_ptr,node_ptr)
  347. static void push_front(node_ptr header, node_ptr new_node)
  348. {
  349. bstree_algo::push_front(header, new_node);
  350. rebalance_after_insertion(header, new_node);
  351. }
  352. #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  353. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const const_node_ptr&,const KeyType&,KeyNodePtrCompare,insert_commit_data&)
  354. template<class KeyType, class KeyNodePtrCompare>
  355. static std::pair<node_ptr, bool> insert_unique_check
  356. (const_node_ptr header, const KeyType &key
  357. ,KeyNodePtrCompare comp, insert_commit_data &commit_data);
  358. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const const_node_ptr&,const node_ptr&,const KeyType&,KeyNodePtrCompare,insert_commit_data&)
  359. template<class KeyType, class KeyNodePtrCompare>
  360. static std::pair<node_ptr, bool> insert_unique_check
  361. (const_node_ptr header, node_ptr hint, const KeyType &key
  362. ,KeyNodePtrCompare comp, insert_commit_data &commit_data);
  363. #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  364. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_commit(node_ptr,node_ptr,const insert_commit_data&)
  365. static void insert_unique_commit
  366. (node_ptr header, node_ptr new_value, const insert_commit_data &commit_data)
  367. {
  368. bstree_algo::insert_unique_commit(header, new_value, commit_data);
  369. rebalance_after_insertion(header, new_value);
  370. }
  371. //! @copydoc ::boost::intrusive::bstree_algorithms::is_header
  372. static bool is_header(const const_node_ptr & p)
  373. {
  374. return NodeTraits::get_color(p) == NodeTraits::red() &&
  375. bstree_algo::is_header(p);
  376. }
  377. /// @cond
  378. private:
  379. static void rebalance_after_erasure
  380. ( node_ptr header, node_ptr z, const typename bstree_algo::data_for_rebalance &info)
  381. {
  382. color new_z_color;
  383. if(info.y != z){
  384. new_z_color = NodeTraits::get_color(info.y);
  385. NodeTraits::set_color(info.y, NodeTraits::get_color(z));
  386. }
  387. else{
  388. new_z_color = NodeTraits::get_color(z);
  389. }
  390. //Rebalance rbtree if needed
  391. if(new_z_color != NodeTraits::red()){
  392. rebalance_after_erasure_restore_invariants(header, info.x, info.x_parent);
  393. }
  394. }
  395. static void rebalance_after_erasure_restore_invariants(node_ptr header, node_ptr x, node_ptr x_parent)
  396. {
  397. while(1){
  398. if(x_parent == header || (x && NodeTraits::get_color(x) != NodeTraits::black())){
  399. break;
  400. }
  401. //Don't cache x_is_leftchild or similar because x can be null and
  402. //equal to both x_parent_left and x_parent_right
  403. const node_ptr x_parent_left(NodeTraits::get_left(x_parent));
  404. if(x == x_parent_left){ //x is left child
  405. node_ptr w = NodeTraits::get_right(x_parent);
  406. BOOST_INTRUSIVE_INVARIANT_ASSERT(w);
  407. if(NodeTraits::get_color(w) == NodeTraits::red()){
  408. NodeTraits::set_color(w, NodeTraits::black());
  409. NodeTraits::set_color(x_parent, NodeTraits::red());
  410. bstree_algo::rotate_left(x_parent, w, NodeTraits::get_parent(x_parent), header);
  411. w = NodeTraits::get_right(x_parent);
  412. BOOST_INTRUSIVE_INVARIANT_ASSERT(w);
  413. }
  414. node_ptr const w_left (NodeTraits::get_left(w));
  415. node_ptr const w_right(NodeTraits::get_right(w));
  416. if((!w_left || NodeTraits::get_color(w_left) == NodeTraits::black()) &&
  417. (!w_right || NodeTraits::get_color(w_right) == NodeTraits::black())){
  418. NodeTraits::set_color(w, NodeTraits::red());
  419. x = x_parent;
  420. x_parent = NodeTraits::get_parent(x_parent);
  421. }
  422. else {
  423. if(!w_right || NodeTraits::get_color(w_right) == NodeTraits::black()){
  424. NodeTraits::set_color(w_left, NodeTraits::black());
  425. NodeTraits::set_color(w, NodeTraits::red());
  426. bstree_algo::rotate_right(w, w_left, NodeTraits::get_parent(w), header);
  427. w = NodeTraits::get_right(x_parent);
  428. BOOST_INTRUSIVE_INVARIANT_ASSERT(w);
  429. }
  430. NodeTraits::set_color(w, NodeTraits::get_color(x_parent));
  431. NodeTraits::set_color(x_parent, NodeTraits::black());
  432. const node_ptr new_wright(NodeTraits::get_right(w));
  433. if(new_wright)
  434. NodeTraits::set_color(new_wright, NodeTraits::black());
  435. bstree_algo::rotate_left(x_parent, NodeTraits::get_right(x_parent), NodeTraits::get_parent(x_parent), header);
  436. break;
  437. }
  438. }
  439. else {
  440. // same as above, with right_ <-> left_.
  441. node_ptr w = x_parent_left;
  442. if(NodeTraits::get_color(w) == NodeTraits::red()){
  443. NodeTraits::set_color(w, NodeTraits::black());
  444. NodeTraits::set_color(x_parent, NodeTraits::red());
  445. bstree_algo::rotate_right(x_parent, w, NodeTraits::get_parent(x_parent), header);
  446. w = NodeTraits::get_left(x_parent);
  447. BOOST_INTRUSIVE_INVARIANT_ASSERT(w);
  448. }
  449. node_ptr const w_left (NodeTraits::get_left(w));
  450. node_ptr const w_right(NodeTraits::get_right(w));
  451. if((!w_right || NodeTraits::get_color(w_right) == NodeTraits::black()) &&
  452. (!w_left || NodeTraits::get_color(w_left) == NodeTraits::black())){
  453. NodeTraits::set_color(w, NodeTraits::red());
  454. x = x_parent;
  455. x_parent = NodeTraits::get_parent(x_parent);
  456. }
  457. else {
  458. if(!w_left || NodeTraits::get_color(w_left) == NodeTraits::black()){
  459. NodeTraits::set_color(w_right, NodeTraits::black());
  460. NodeTraits::set_color(w, NodeTraits::red());
  461. bstree_algo::rotate_left(w, w_right, NodeTraits::get_parent(w), header);
  462. w = NodeTraits::get_left(x_parent);
  463. BOOST_INTRUSIVE_INVARIANT_ASSERT(w);
  464. }
  465. NodeTraits::set_color(w, NodeTraits::get_color(x_parent));
  466. NodeTraits::set_color(x_parent, NodeTraits::black());
  467. const node_ptr new_wleft(NodeTraits::get_left(w));
  468. if(new_wleft)
  469. NodeTraits::set_color(new_wleft, NodeTraits::black());
  470. bstree_algo::rotate_right(x_parent, NodeTraits::get_left(x_parent), NodeTraits::get_parent(x_parent), header);
  471. break;
  472. }
  473. }
  474. }
  475. if(x)
  476. NodeTraits::set_color(x, NodeTraits::black());
  477. }
  478. static void rebalance_after_insertion(node_ptr header, node_ptr p)
  479. {
  480. NodeTraits::set_color(p, NodeTraits::red());
  481. while(1){
  482. node_ptr p_parent(NodeTraits::get_parent(p));
  483. const node_ptr p_grandparent(NodeTraits::get_parent(p_parent));
  484. if(p_parent == header || NodeTraits::get_color(p_parent) == NodeTraits::black() || p_grandparent == header){
  485. break;
  486. }
  487. NodeTraits::set_color(p_grandparent, NodeTraits::red());
  488. node_ptr const p_grandparent_left (NodeTraits::get_left (p_grandparent));
  489. bool const p_parent_is_left_child = p_parent == p_grandparent_left;
  490. node_ptr const x(p_parent_is_left_child ? NodeTraits::get_right(p_grandparent) : p_grandparent_left);
  491. if(x && NodeTraits::get_color(x) == NodeTraits::red()){
  492. NodeTraits::set_color(x, NodeTraits::black());
  493. NodeTraits::set_color(p_parent, NodeTraits::black());
  494. p = p_grandparent;
  495. }
  496. else{ //Final step
  497. const bool p_is_left_child(NodeTraits::get_left(p_parent) == p);
  498. if(p_parent_is_left_child){ //p_parent is left child
  499. if(!p_is_left_child){ //p is right child
  500. bstree_algo::rotate_left_no_parent_fix(p_parent, p);
  501. //No need to link p and p_grandparent:
  502. // [NodeTraits::set_parent(p, p_grandparent) + NodeTraits::set_left(p_grandparent, p)]
  503. //as p_grandparent is not the header, another rotation is coming and p_parent
  504. //will be the left child of p_grandparent
  505. p_parent = p;
  506. }
  507. bstree_algo::rotate_right(p_grandparent, p_parent, NodeTraits::get_parent(p_grandparent), header);
  508. }
  509. else{ //p_parent is right child
  510. if(p_is_left_child){ //p is left child
  511. bstree_algo::rotate_right_no_parent_fix(p_parent, p);
  512. //No need to link p and p_grandparent:
  513. // [NodeTraits::set_parent(p, p_grandparent) + NodeTraits::set_right(p_grandparent, p)]
  514. //as p_grandparent is not the header, another rotation is coming and p_parent
  515. //will be the right child of p_grandparent
  516. p_parent = p;
  517. }
  518. bstree_algo::rotate_left(p_grandparent, p_parent, NodeTraits::get_parent(p_grandparent), header);
  519. }
  520. NodeTraits::set_color(p_parent, NodeTraits::black());
  521. break;
  522. }
  523. }
  524. NodeTraits::set_color(NodeTraits::get_parent(header), NodeTraits::black());
  525. }
  526. /// @endcond
  527. };
  528. /// @cond
  529. template<class NodeTraits>
  530. struct get_algo<RbTreeAlgorithms, NodeTraits>
  531. {
  532. typedef rbtree_algorithms<NodeTraits> type;
  533. };
  534. template <class ValueTraits, class NodePtrCompare, class ExtraChecker>
  535. struct get_node_checker<RbTreeAlgorithms, ValueTraits, NodePtrCompare, ExtraChecker>
  536. {
  537. typedef detail::rbtree_node_checker<ValueTraits, NodePtrCompare, ExtraChecker> type;
  538. };
  539. /// @endcond
  540. } //namespace intrusive
  541. } //namespace boost
  542. #include <boost/intrusive/detail/config_end.hpp>
  543. #endif //BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP