bstree_algorithms_base.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2014-2014
  4. //
  5. // Distributed under the Boost Software License, Version 1.0.
  6. // (See accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //
  9. // See http://www.boost.org/libs/intrusive for documentation.
  10. //
  11. /////////////////////////////////////////////////////////////////////////////
  12. #ifndef BOOST_INTRUSIVE_BSTREE_ALGORITHMS_BASE_HPP
  13. #define BOOST_INTRUSIVE_BSTREE_ALGORITHMS_BASE_HPP
  14. #ifndef BOOST_CONFIG_HPP
  15. # include <boost/config.hpp>
  16. #endif
  17. #if defined(BOOST_HAS_PRAGMA_ONCE)
  18. # pragma once
  19. #endif
  20. #include <boost/intrusive/detail/uncast.hpp>
  21. namespace boost {
  22. namespace intrusive {
  23. template<class NodeTraits>
  24. class bstree_algorithms_base
  25. {
  26. public:
  27. typedef typename NodeTraits::node node;
  28. typedef NodeTraits node_traits;
  29. typedef typename NodeTraits::node_ptr node_ptr;
  30. typedef typename NodeTraits::const_node_ptr const_node_ptr;
  31. //! <b>Requires</b>: 'node' is a node from the tree except the header.
  32. //!
  33. //! <b>Effects</b>: Returns the next node of the tree.
  34. //!
  35. //! <b>Complexity</b>: Average constant time.
  36. //!
  37. //! <b>Throws</b>: Nothing.
  38. static node_ptr next_node(const node_ptr & node)
  39. {
  40. node_ptr const n_right(NodeTraits::get_right(node));
  41. if(n_right){
  42. return minimum(n_right);
  43. }
  44. else {
  45. node_ptr n(node);
  46. node_ptr p(NodeTraits::get_parent(n));
  47. while(n == NodeTraits::get_right(p)){
  48. n = p;
  49. p = NodeTraits::get_parent(p);
  50. }
  51. return NodeTraits::get_right(n) != p ? p : n;
  52. }
  53. }
  54. //! <b>Requires</b>: 'node' is a node from the tree except the leftmost node.
  55. //!
  56. //! <b>Effects</b>: Returns the previous node of the tree.
  57. //!
  58. //! <b>Complexity</b>: Average constant time.
  59. //!
  60. //! <b>Throws</b>: Nothing.
  61. static node_ptr prev_node(const node_ptr & node)
  62. {
  63. if(is_header(node)){
  64. //return NodeTraits::get_right(node);
  65. return maximum(NodeTraits::get_parent(node));
  66. }
  67. else if(NodeTraits::get_left(node)){
  68. return maximum(NodeTraits::get_left(node));
  69. }
  70. else {
  71. node_ptr p(node);
  72. node_ptr x = NodeTraits::get_parent(p);
  73. while(p == NodeTraits::get_left(x)){
  74. p = x;
  75. x = NodeTraits::get_parent(x);
  76. }
  77. return x;
  78. }
  79. }
  80. //! <b>Requires</b>: 'node' is a node of a tree but not the header.
  81. //!
  82. //! <b>Effects</b>: Returns the minimum node of the subtree starting at p.
  83. //!
  84. //! <b>Complexity</b>: Logarithmic to the size of the subtree.
  85. //!
  86. //! <b>Throws</b>: Nothing.
  87. static node_ptr minimum(node_ptr node)
  88. {
  89. for(node_ptr p_left = NodeTraits::get_left(node)
  90. ;p_left
  91. ;p_left = NodeTraits::get_left(node)){
  92. node = p_left;
  93. }
  94. return node;
  95. }
  96. //! <b>Requires</b>: 'node' is a node of a tree but not the header.
  97. //!
  98. //! <b>Effects</b>: Returns the maximum node of the subtree starting at p.
  99. //!
  100. //! <b>Complexity</b>: Logarithmic to the size of the subtree.
  101. //!
  102. //! <b>Throws</b>: Nothing.
  103. static node_ptr maximum(node_ptr node)
  104. {
  105. for(node_ptr p_right = NodeTraits::get_right(node)
  106. ;p_right
  107. ;p_right = NodeTraits::get_right(node)){
  108. node = p_right;
  109. }
  110. return node;
  111. }
  112. //! <b>Requires</b>: p is a node of a tree.
  113. //!
  114. //! <b>Effects</b>: Returns true if p is the header of the tree.
  115. //!
  116. //! <b>Complexity</b>: Constant.
  117. //!
  118. //! <b>Throws</b>: Nothing.
  119. static bool is_header(const const_node_ptr & p)
  120. {
  121. node_ptr p_left (NodeTraits::get_left(p));
  122. node_ptr p_right(NodeTraits::get_right(p));
  123. if(!NodeTraits::get_parent(p) || //Header condition when empty tree
  124. (p_left && p_right && //Header always has leftmost and rightmost
  125. (p_left == p_right || //Header condition when only node
  126. (NodeTraits::get_parent(p_left) != p ||
  127. NodeTraits::get_parent(p_right) != p ))
  128. //When tree size > 1 headers can't be leftmost's
  129. //and rightmost's parent
  130. )){
  131. return true;
  132. }
  133. return false;
  134. }
  135. //! <b>Requires</b>: 'node' is a node of the tree or a header node.
  136. //!
  137. //! <b>Effects</b>: Returns the header of the tree.
  138. //!
  139. //! <b>Complexity</b>: Logarithmic.
  140. //!
  141. //! <b>Throws</b>: Nothing.
  142. static node_ptr get_header(const const_node_ptr & node)
  143. {
  144. node_ptr n(detail::uncast(node));
  145. node_ptr p(NodeTraits::get_parent(node));
  146. //If p is null, then n is the header of an empty tree
  147. if(p){
  148. //Non-empty tree, check if n is neither root nor header
  149. node_ptr pp(NodeTraits::get_parent(p));
  150. //If granparent is not equal to n, then n is neither root nor header,
  151. //the try the fast path
  152. if(n != pp){
  153. do{
  154. n = p;
  155. p = pp;
  156. pp = NodeTraits::get_parent(pp);
  157. }while(n != pp);
  158. n = p;
  159. }
  160. //Check if n is root or header when size() > 0
  161. else if(!bstree_algorithms_base::is_header(n)){
  162. n = p;
  163. }
  164. }
  165. return n;
  166. }
  167. };
  168. } //namespace intrusive
  169. } //namespace boost
  170. #endif //BOOST_INTRUSIVE_BSTREE_ALGORITHMS_BASE_HPP