avltree_algorithms.hpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Daniel K. O. 2005.
  4. // (C) Copyright Ion Gaztanaga 2007-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. #ifndef BOOST_INTRUSIVE_AVLTREE_ALGORITHMS_HPP
  14. #define BOOST_INTRUSIVE_AVLTREE_ALGORITHMS_HPP
  15. #include <boost/intrusive/detail/config_begin.hpp>
  16. #include <cstddef>
  17. #include <boost/intrusive/intrusive_fwd.hpp>
  18. #include <boost/intrusive/detail/assert.hpp>
  19. #include <boost/intrusive/detail/utilities.hpp>
  20. #include <boost/intrusive/bstree_algorithms.hpp>
  21. #include <boost/intrusive/pointer_traits.hpp>
  22. namespace boost {
  23. namespace intrusive {
  24. /// @cond
  25. template<class NodeTraits, class F>
  26. struct avltree_node_cloner
  27. : private detail::ebo_functor_holder<F>
  28. {
  29. typedef typename NodeTraits::node_ptr node_ptr;
  30. typedef detail::ebo_functor_holder<F> base_t;
  31. avltree_node_cloner(F f)
  32. : base_t(f)
  33. {}
  34. node_ptr operator()(const node_ptr & p)
  35. {
  36. node_ptr n = base_t::get()(p);
  37. NodeTraits::set_balance(n, NodeTraits::get_balance(p));
  38. return n;
  39. }
  40. };
  41. template<class NodeTraits>
  42. struct avltree_erase_fixup
  43. {
  44. typedef typename NodeTraits::node_ptr node_ptr;
  45. void operator()(const node_ptr & to_erase, const node_ptr & successor)
  46. { NodeTraits::set_balance(successor, NodeTraits::get_balance(to_erase)); }
  47. };
  48. /// @endcond
  49. //! avltree_algorithms is configured with a NodeTraits class, which encapsulates the
  50. //! information about the node to be manipulated. NodeTraits must support the
  51. //! following interface:
  52. //!
  53. //! <b>Typedefs</b>:
  54. //!
  55. //! <tt>node</tt>: The type of the node that forms the binary search tree
  56. //!
  57. //! <tt>node_ptr</tt>: A pointer to a node
  58. //!
  59. //! <tt>const_node_ptr</tt>: A pointer to a const node
  60. //!
  61. //! <tt>balance</tt>: The type of the balance factor
  62. //!
  63. //! <b>Static functions</b>:
  64. //!
  65. //! <tt>static node_ptr get_parent(const_node_ptr n);</tt>
  66. //!
  67. //! <tt>static void set_parent(node_ptr n, node_ptr parent);</tt>
  68. //!
  69. //! <tt>static node_ptr get_left(const_node_ptr n);</tt>
  70. //!
  71. //! <tt>static void set_left(node_ptr n, node_ptr left);</tt>
  72. //!
  73. //! <tt>static node_ptr get_right(const_node_ptr n);</tt>
  74. //!
  75. //! <tt>static void set_right(node_ptr n, node_ptr right);</tt>
  76. //!
  77. //! <tt>static balance get_balance(const_node_ptr n);</tt>
  78. //!
  79. //! <tt>static void set_balance(node_ptr n, balance b);</tt>
  80. //!
  81. //! <tt>static balance negative();</tt>
  82. //!
  83. //! <tt>static balance zero();</tt>
  84. //!
  85. //! <tt>static balance positive();</tt>
  86. template<class NodeTraits>
  87. class avltree_algorithms
  88. #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  89. : public bstree_algorithms<NodeTraits>
  90. #endif
  91. {
  92. public:
  93. typedef typename NodeTraits::node node;
  94. typedef NodeTraits node_traits;
  95. typedef typename NodeTraits::node_ptr node_ptr;
  96. typedef typename NodeTraits::const_node_ptr const_node_ptr;
  97. typedef typename NodeTraits::balance balance;
  98. /// @cond
  99. private:
  100. typedef bstree_algorithms<NodeTraits> bstree_algo;
  101. /// @endcond
  102. public:
  103. //! This type is the information that will be
  104. //! filled by insert_unique_check
  105. typedef typename bstree_algo::insert_commit_data insert_commit_data;
  106. #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  107. //! @copydoc ::boost::intrusive::bstree_algorithms::get_header(const const_node_ptr&)
  108. static node_ptr get_header(const const_node_ptr & n);
  109. //! @copydoc ::boost::intrusive::bstree_algorithms::begin_node
  110. static node_ptr begin_node(const const_node_ptr & header);
  111. //! @copydoc ::boost::intrusive::bstree_algorithms::end_node
  112. static node_ptr end_node(const const_node_ptr & header);
  113. //! @copydoc ::boost::intrusive::bstree_algorithms::swap_tree
  114. static void swap_tree(const node_ptr & header1, const node_ptr & header2);
  115. #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  116. //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(const node_ptr&,const node_ptr&)
  117. static void swap_nodes(const node_ptr & node1, const node_ptr & node2)
  118. {
  119. if(node1 == node2)
  120. return;
  121. node_ptr header1(bstree_algo::get_header(node1)), header2(bstree_algo::get_header(node2));
  122. swap_nodes(node1, header1, node2, header2);
  123. }
  124. //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(const node_ptr&,const node_ptr&,const node_ptr&,const node_ptr&)
  125. static void swap_nodes(const node_ptr & node1, const node_ptr & header1, const node_ptr & node2, const node_ptr & header2)
  126. {
  127. if(node1 == node2) return;
  128. bstree_algo::swap_nodes(node1, header1, node2, header2);
  129. //Swap balance
  130. balance c = NodeTraits::get_balance(node1);
  131. NodeTraits::set_balance(node1, NodeTraits::get_balance(node2));
  132. NodeTraits::set_balance(node2, c);
  133. }
  134. //! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(const node_ptr&,const node_ptr&)
  135. static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & new_node)
  136. {
  137. if(node_to_be_replaced == new_node)
  138. return;
  139. replace_node(node_to_be_replaced, bstree_algo::get_header(node_to_be_replaced), new_node);
  140. }
  141. //! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(const node_ptr&,const node_ptr&,const node_ptr&)
  142. static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & header, const node_ptr & new_node)
  143. {
  144. bstree_algo::replace_node(node_to_be_replaced, header, new_node);
  145. NodeTraits::set_balance(new_node, NodeTraits::get_balance(node_to_be_replaced));
  146. }
  147. //! @copydoc ::boost::intrusive::bstree_algorithms::unlink(const node_ptr&)
  148. static void unlink(const node_ptr & node)
  149. {
  150. node_ptr x = NodeTraits::get_parent(node);
  151. if(x){
  152. while(!is_header(x))
  153. x = NodeTraits::get_parent(x);
  154. erase(x, node);
  155. }
  156. }
  157. #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  158. //! @copydoc ::boost::intrusive::bstree_algorithms::unlink_leftmost_without_rebalance
  159. static node_ptr unlink_leftmost_without_rebalance(const node_ptr & header);
  160. //! @copydoc ::boost::intrusive::bstree_algorithms::unique(const const_node_ptr&)
  161. static bool unique(const const_node_ptr & node);
  162. //! @copydoc ::boost::intrusive::bstree_algorithms::size(const const_node_ptr&)
  163. static std::size_t size(const const_node_ptr & header);
  164. //! @copydoc ::boost::intrusive::bstree_algorithms::next_node(const node_ptr&)
  165. static node_ptr next_node(const node_ptr & node);
  166. //! @copydoc ::boost::intrusive::bstree_algorithms::prev_node(const node_ptr&)
  167. static node_ptr prev_node(const node_ptr & node);
  168. //! @copydoc ::boost::intrusive::bstree_algorithms::init(const node_ptr&)
  169. static void init(const node_ptr & node);
  170. #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  171. //! <b>Requires</b>: node must not be part of any tree.
  172. //!
  173. //! <b>Effects</b>: Initializes the header to represent an empty tree.
  174. //! unique(header) == true.
  175. //!
  176. //! <b>Complexity</b>: Constant.
  177. //!
  178. //! <b>Throws</b>: Nothing.
  179. //!
  180. //! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
  181. static void init_header(const node_ptr & header)
  182. {
  183. bstree_algo::init_header(header);
  184. NodeTraits::set_balance(header, NodeTraits::zero());
  185. }
  186. //! @copydoc ::boost::intrusive::bstree_algorithms::erase(const node_ptr&,const node_ptr&)
  187. static node_ptr erase(const node_ptr & header, const node_ptr & z)
  188. {
  189. typename bstree_algo::data_for_rebalance info;
  190. bstree_algo::erase(header, z, avltree_erase_fixup<NodeTraits>(), info);
  191. //Rebalance avltree
  192. rebalance_after_erasure(header, info.x, info.x_parent);
  193. return z;
  194. }
  195. //! @copydoc ::boost::intrusive::bstree_algorithms::clone(const const_node_ptr&,const node_ptr&,Cloner,Disposer)
  196. template <class Cloner, class Disposer>
  197. static void clone
  198. (const const_node_ptr & source_header, const node_ptr & target_header, Cloner cloner, Disposer disposer)
  199. {
  200. avltree_node_cloner<NodeTraits, Cloner> new_cloner(cloner);
  201. bstree_algo::clone(source_header, target_header, new_cloner, disposer);
  202. }
  203. #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  204. //! @copydoc ::boost::intrusive::bstree_algorithms::clear_and_dispose(const node_ptr&,Disposer)
  205. template<class Disposer>
  206. static void clear_and_dispose(const node_ptr & header, Disposer disposer);
  207. //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
  208. template<class KeyType, class KeyNodePtrCompare>
  209. static node_ptr lower_bound
  210. (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
  211. //! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
  212. template<class KeyType, class KeyNodePtrCompare>
  213. static node_ptr upper_bound
  214. (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
  215. //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
  216. template<class KeyType, class KeyNodePtrCompare>
  217. static node_ptr find
  218. (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
  219. //! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
  220. template<class KeyType, class KeyNodePtrCompare>
  221. static std::pair<node_ptr, node_ptr> equal_range
  222. (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
  223. //! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool)
  224. template<class KeyType, class KeyNodePtrCompare>
  225. static std::pair<node_ptr, node_ptr> bounded_range
  226. (const const_node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp
  227. , bool left_closed, bool right_closed);
  228. //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
  229. template<class KeyType, class KeyNodePtrCompare>
  230. static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
  231. #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  232. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_upper_bound(const node_ptr&,const node_ptr&,NodePtrCompare)
  233. template<class NodePtrCompare>
  234. static node_ptr insert_equal_upper_bound
  235. (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp)
  236. {
  237. bstree_algo::insert_equal_upper_bound(h, new_node, comp);
  238. rebalance_after_insertion(h, new_node);
  239. return new_node;
  240. }
  241. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_lower_bound(const node_ptr&,const node_ptr&,NodePtrCompare)
  242. template<class NodePtrCompare>
  243. static node_ptr insert_equal_lower_bound
  244. (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp)
  245. {
  246. bstree_algo::insert_equal_lower_bound(h, new_node, comp);
  247. rebalance_after_insertion(h, new_node);
  248. return new_node;
  249. }
  250. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal(const node_ptr&,const node_ptr&,const node_ptr&,NodePtrCompare)
  251. template<class NodePtrCompare>
  252. static node_ptr insert_equal
  253. (const node_ptr & header, const node_ptr & hint, const node_ptr & new_node, NodePtrCompare comp)
  254. {
  255. bstree_algo::insert_equal(header, hint, new_node, comp);
  256. rebalance_after_insertion(header, new_node);
  257. return new_node;
  258. }
  259. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_before(const node_ptr&,const node_ptr&,const node_ptr&)
  260. static node_ptr insert_before
  261. (const node_ptr & header, const node_ptr & pos, const node_ptr & new_node)
  262. {
  263. bstree_algo::insert_before(header, pos, new_node);
  264. rebalance_after_insertion(header, new_node);
  265. return new_node;
  266. }
  267. //! @copydoc ::boost::intrusive::bstree_algorithms::push_back(const node_ptr&,const node_ptr&)
  268. static void push_back(const node_ptr & header, const node_ptr & new_node)
  269. {
  270. bstree_algo::push_back(header, new_node);
  271. rebalance_after_insertion(header, new_node);
  272. }
  273. //! @copydoc ::boost::intrusive::bstree_algorithms::push_front(const node_ptr&,const node_ptr&)
  274. static void push_front(const node_ptr & header, const node_ptr & new_node)
  275. {
  276. bstree_algo::push_front(header, new_node);
  277. rebalance_after_insertion(header, new_node);
  278. }
  279. #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  280. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const const_node_ptr&,const KeyType&,KeyNodePtrCompare,insert_commit_data&)
  281. template<class KeyType, class KeyNodePtrCompare>
  282. static std::pair<node_ptr, bool> insert_unique_check
  283. (const const_node_ptr & header, const KeyType &key
  284. ,KeyNodePtrCompare comp, insert_commit_data &commit_data);
  285. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const const_node_ptr&,const node_ptr&,const KeyType&,KeyNodePtrCompare,insert_commit_data&)
  286. template<class KeyType, class KeyNodePtrCompare>
  287. static std::pair<node_ptr, bool> insert_unique_check
  288. (const const_node_ptr & header, const node_ptr &hint, const KeyType &key
  289. ,KeyNodePtrCompare comp, insert_commit_data &commit_data);
  290. #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  291. //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_commit(const node_ptr&,const node_ptr&,const insert_commit_data &)
  292. static void insert_unique_commit
  293. (const node_ptr & header, const node_ptr & new_value, const insert_commit_data &commit_data)
  294. {
  295. bstree_algo::insert_unique_commit(header, new_value, commit_data);
  296. rebalance_after_insertion(header, new_value);
  297. }
  298. //! @copydoc ::boost::intrusive::bstree_algorithms::is_header
  299. static bool is_header(const const_node_ptr & p)
  300. { return NodeTraits::get_balance(p) == NodeTraits::zero() && bstree_algo::is_header(p); }
  301. /// @cond
  302. private:
  303. static void rebalance_after_erasure(const node_ptr & header, const node_ptr & xnode, const node_ptr & xnode_parent)
  304. {
  305. node_ptr x(xnode), x_parent(xnode_parent);
  306. for (node_ptr root = NodeTraits::get_parent(header); x != root; root = NodeTraits::get_parent(header)) {
  307. const balance x_parent_balance = NodeTraits::get_balance(x_parent);
  308. if(x_parent_balance == NodeTraits::zero()){
  309. NodeTraits::set_balance(x_parent,
  310. (x == NodeTraits::get_right(x_parent) ? NodeTraits::negative() : NodeTraits::positive()));
  311. break; // the height didn't change, let's stop here
  312. }
  313. else if(x_parent_balance == NodeTraits::negative()){
  314. if (x == NodeTraits::get_left(x_parent)) {
  315. NodeTraits::set_balance(x_parent, NodeTraits::zero()); // balanced
  316. x = x_parent;
  317. x_parent = NodeTraits::get_parent(x_parent);
  318. }
  319. else {
  320. // x is right child
  321. // a is left child
  322. node_ptr a = NodeTraits::get_left(x_parent);
  323. BOOST_INTRUSIVE_INVARIANT_ASSERT(a);
  324. if (NodeTraits::get_balance(a) == NodeTraits::positive()) {
  325. // a MUST have a right child
  326. BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_right(a));
  327. rotate_left_right(x_parent, header);
  328. x = NodeTraits::get_parent(x_parent);
  329. x_parent = NodeTraits::get_parent(x);
  330. }
  331. else {
  332. rotate_right(x_parent, header);
  333. x = NodeTraits::get_parent(x_parent);
  334. x_parent = NodeTraits::get_parent(x);
  335. }
  336. // if changed from negative to NodeTraits::positive(), no need to check above
  337. if (NodeTraits::get_balance(x) == NodeTraits::positive()){
  338. break;
  339. }
  340. }
  341. }
  342. else if(x_parent_balance == NodeTraits::positive()){
  343. if (x == NodeTraits::get_right(x_parent)) {
  344. NodeTraits::set_balance(x_parent, NodeTraits::zero()); // balanced
  345. x = x_parent;
  346. x_parent = NodeTraits::get_parent(x_parent);
  347. }
  348. else {
  349. // x is left child
  350. // a is right child
  351. node_ptr a = NodeTraits::get_right(x_parent);
  352. BOOST_INTRUSIVE_INVARIANT_ASSERT(a);
  353. if (NodeTraits::get_balance(a) == NodeTraits::negative()) {
  354. // a MUST have then a left child
  355. BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_left(a));
  356. rotate_right_left(x_parent, header);
  357. x = NodeTraits::get_parent(x_parent);
  358. x_parent = NodeTraits::get_parent(x);
  359. }
  360. else {
  361. rotate_left(x_parent, header);
  362. x = NodeTraits::get_parent(x_parent);
  363. x_parent = NodeTraits::get_parent(x);
  364. }
  365. // if changed from NodeTraits::positive() to negative, no need to check above
  366. if (NodeTraits::get_balance(x) == NodeTraits::negative()){
  367. break;
  368. }
  369. }
  370. }
  371. else{
  372. BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached
  373. }
  374. }
  375. }
  376. static void rebalance_after_insertion(const node_ptr & header, const node_ptr & xnode)
  377. {
  378. node_ptr x(xnode);
  379. NodeTraits::set_balance(x, NodeTraits::zero());
  380. // Rebalance.
  381. for(node_ptr root = NodeTraits::get_parent(header); x != root; root = NodeTraits::get_parent(header)){
  382. const balance x_parent_balance = NodeTraits::get_balance(NodeTraits::get_parent(x));
  383. if(x_parent_balance == NodeTraits::zero()){
  384. // if x is left, parent will have parent->bal_factor = negative
  385. // else, parent->bal_factor = NodeTraits::positive()
  386. NodeTraits::set_balance( NodeTraits::get_parent(x)
  387. , x == NodeTraits::get_left(NodeTraits::get_parent(x))
  388. ? NodeTraits::negative() : NodeTraits::positive() );
  389. x = NodeTraits::get_parent(x);
  390. }
  391. else if(x_parent_balance == NodeTraits::positive()){
  392. // if x is a left child, parent->bal_factor = zero
  393. if (x == NodeTraits::get_left(NodeTraits::get_parent(x)))
  394. NodeTraits::set_balance(NodeTraits::get_parent(x), NodeTraits::zero());
  395. else{ // x is a right child, needs rebalancing
  396. if (NodeTraits::get_balance(x) == NodeTraits::negative())
  397. rotate_right_left(NodeTraits::get_parent(x), header);
  398. else
  399. rotate_left(NodeTraits::get_parent(x), header);
  400. }
  401. break;
  402. }
  403. else if(x_parent_balance == NodeTraits::negative()){
  404. // if x is a left child, needs rebalancing
  405. if (x == NodeTraits::get_left(NodeTraits::get_parent(x))) {
  406. if (NodeTraits::get_balance(x) == NodeTraits::positive())
  407. rotate_left_right(NodeTraits::get_parent(x), header);
  408. else
  409. rotate_right(NodeTraits::get_parent(x), header);
  410. }
  411. else
  412. NodeTraits::set_balance(NodeTraits::get_parent(x), NodeTraits::zero());
  413. break;
  414. }
  415. else{
  416. BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached
  417. }
  418. }
  419. }
  420. static void left_right_balancing(const node_ptr & a, const node_ptr & b, const node_ptr & c)
  421. {
  422. // balancing...
  423. const balance c_balance = NodeTraits::get_balance(c);
  424. const balance zero_balance = NodeTraits::zero();
  425. NodeTraits::set_balance(c, zero_balance);
  426. if(c_balance == NodeTraits::negative()){
  427. NodeTraits::set_balance(a, NodeTraits::positive());
  428. NodeTraits::set_balance(b, zero_balance);
  429. }
  430. else if(c_balance == zero_balance){
  431. NodeTraits::set_balance(a, zero_balance);
  432. NodeTraits::set_balance(b, zero_balance);
  433. }
  434. else if(c_balance == NodeTraits::positive()){
  435. NodeTraits::set_balance(a, zero_balance);
  436. NodeTraits::set_balance(b, NodeTraits::negative());
  437. }
  438. else{
  439. BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached
  440. }
  441. }
  442. static void rotate_left_right(const node_ptr a, const node_ptr & hdr)
  443. {
  444. // | | //
  445. // a(-2) c //
  446. // / \ / \ //
  447. // / \ ==> / \ //
  448. // (pos)b [g] b a //
  449. // / \ / \ / \ //
  450. // [d] c [d] e f [g] //
  451. // / \ //
  452. // e f //
  453. node_ptr b = NodeTraits::get_left(a), c = NodeTraits::get_right(b);
  454. bstree_algo::rotate_left(b, hdr);
  455. bstree_algo::rotate_right(a, hdr);
  456. left_right_balancing(a, b, c);
  457. }
  458. static void rotate_right_left(const node_ptr a, const node_ptr & hdr)
  459. {
  460. // | | //
  461. // a(pos) c //
  462. // / \ / \ //
  463. // / \ / \ //
  464. // [d] b(neg) ==> a b //
  465. // / \ / \ / \ //
  466. // c [g] [d] e f [g] //
  467. // / \ //
  468. // e f //
  469. node_ptr b = NodeTraits::get_right(a), c = NodeTraits::get_left(b);
  470. bstree_algo::rotate_right(b, hdr);
  471. bstree_algo::rotate_left(a, hdr);
  472. left_right_balancing(b, a, c);
  473. }
  474. static void rotate_left(const node_ptr x, const node_ptr & hdr)
  475. {
  476. const node_ptr y = NodeTraits::get_right(x);
  477. bstree_algo::rotate_left(x, hdr);
  478. // reset the balancing factor
  479. if (NodeTraits::get_balance(y) == NodeTraits::positive()) {
  480. NodeTraits::set_balance(x, NodeTraits::zero());
  481. NodeTraits::set_balance(y, NodeTraits::zero());
  482. }
  483. else { // this doesn't happen during insertions
  484. NodeTraits::set_balance(x, NodeTraits::positive());
  485. NodeTraits::set_balance(y, NodeTraits::negative());
  486. }
  487. }
  488. static void rotate_right(const node_ptr x, const node_ptr & hdr)
  489. {
  490. const node_ptr y = NodeTraits::get_left(x);
  491. bstree_algo::rotate_right(x, hdr);
  492. // reset the balancing factor
  493. if (NodeTraits::get_balance(y) == NodeTraits::negative()) {
  494. NodeTraits::set_balance(x, NodeTraits::zero());
  495. NodeTraits::set_balance(y, NodeTraits::zero());
  496. }
  497. else { // this doesn't happen during insertions
  498. NodeTraits::set_balance(x, NodeTraits::negative());
  499. NodeTraits::set_balance(y, NodeTraits::positive());
  500. }
  501. }
  502. /// @endcond
  503. };
  504. /// @cond
  505. template<class NodeTraits>
  506. struct get_algo<AvlTreeAlgorithms, NodeTraits>
  507. {
  508. typedef avltree_algorithms<NodeTraits> type;
  509. };
  510. /// @endcond
  511. } //namespace intrusive
  512. } //namespace boost
  513. #include <boost/intrusive/detail/config_end.hpp>
  514. #endif //BOOST_INTRUSIVE_AVLTREE_ALGORITHMS_HPP