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