Chris@16
|
1 /////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
2 //
|
Chris@16
|
3 // (C) Copyright Olaf Krzikalla 2004-2006.
|
Chris@101
|
4 // (C) Copyright Ion Gaztanaga 2006-2014.
|
Chris@16
|
5 //
|
Chris@16
|
6 // Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
7 // (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
8 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
9 //
|
Chris@16
|
10 // See http://www.boost.org/libs/intrusive for documentation.
|
Chris@16
|
11 //
|
Chris@16
|
12 /////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
13 //
|
Chris@16
|
14 // The tree destruction algorithm is based on Julienne Walker and The EC Team code:
|
Chris@16
|
15 //
|
Chris@16
|
16 // This code is in the public domain. Anyone may use it or change it in any way that
|
Chris@16
|
17 // they see fit. The author assumes no responsibility for damages incurred through
|
Chris@16
|
18 // use of the original code or any variations thereof.
|
Chris@16
|
19 //
|
Chris@16
|
20 // It is requested, but not required, that due credit is given to the original author
|
Chris@16
|
21 // and anyone who has modified the code through a header comment, such as this one.
|
Chris@16
|
22
|
Chris@16
|
23 #ifndef BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP
|
Chris@16
|
24 #define BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP
|
Chris@16
|
25
|
Chris@16
|
26 #include <boost/intrusive/detail/config_begin.hpp>
|
Chris@101
|
27 #include <boost/intrusive/intrusive_fwd.hpp>
|
Chris@16
|
28
|
Chris@16
|
29 #include <cstddef>
|
Chris@16
|
30
|
Chris@16
|
31 #include <boost/intrusive/detail/assert.hpp>
|
Chris@101
|
32 #include <boost/intrusive/detail/algo_type.hpp>
|
Chris@16
|
33 #include <boost/intrusive/bstree_algorithms.hpp>
|
Chris@101
|
34 #include <boost/intrusive/detail/ebo_functor_holder.hpp>
|
Chris@101
|
35
|
Chris@101
|
36 #if defined(BOOST_HAS_PRAGMA_ONCE)
|
Chris@101
|
37 # pragma once
|
Chris@101
|
38 #endif
|
Chris@16
|
39
|
Chris@16
|
40 namespace boost {
|
Chris@16
|
41 namespace intrusive {
|
Chris@16
|
42
|
Chris@16
|
43 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
Chris@16
|
44
|
Chris@16
|
45 template<class NodeTraits, class F>
|
Chris@16
|
46 struct rbtree_node_cloner
|
Chris@101
|
47 //Use public inheritance to avoid MSVC bugs with closures
|
Chris@101
|
48 : public detail::ebo_functor_holder<F>
|
Chris@16
|
49 {
|
Chris@16
|
50 typedef typename NodeTraits::node_ptr node_ptr;
|
Chris@16
|
51 typedef detail::ebo_functor_holder<F> base_t;
|
Chris@16
|
52
|
Chris@101
|
53 explicit rbtree_node_cloner(F f)
|
Chris@16
|
54 : base_t(f)
|
Chris@16
|
55 {}
|
Chris@16
|
56
|
Chris@16
|
57 node_ptr operator()(const node_ptr & p)
|
Chris@16
|
58 {
|
Chris@16
|
59 node_ptr n = base_t::get()(p);
|
Chris@16
|
60 NodeTraits::set_color(n, NodeTraits::get_color(p));
|
Chris@16
|
61 return n;
|
Chris@16
|
62 }
|
Chris@16
|
63 };
|
Chris@16
|
64
|
Chris@101
|
65 namespace detail {
|
Chris@101
|
66
|
Chris@101
|
67 template<class ValueTraits, class NodePtrCompare, class ExtraChecker>
|
Chris@101
|
68 struct rbtree_node_checker
|
Chris@101
|
69 : public bstree_node_checker<ValueTraits, NodePtrCompare, ExtraChecker>
|
Chris@16
|
70 {
|
Chris@101
|
71 typedef bstree_node_checker<ValueTraits, NodePtrCompare, ExtraChecker> base_checker_t;
|
Chris@101
|
72 typedef ValueTraits value_traits;
|
Chris@101
|
73 typedef typename value_traits::node_traits node_traits;
|
Chris@101
|
74 typedef typename node_traits::const_node_ptr const_node_ptr;
|
Chris@101
|
75 typedef typename node_traits::node_ptr node_ptr;
|
Chris@16
|
76
|
Chris@101
|
77 struct return_type
|
Chris@101
|
78 : public base_checker_t::return_type
|
Chris@16
|
79 {
|
Chris@101
|
80 return_type() : black_count_(0) {}
|
Chris@101
|
81 std::size_t black_count_;
|
Chris@101
|
82 };
|
Chris@101
|
83
|
Chris@101
|
84 rbtree_node_checker(const NodePtrCompare& comp, ExtraChecker extra_checker)
|
Chris@101
|
85 : base_checker_t(comp, extra_checker)
|
Chris@101
|
86 {}
|
Chris@101
|
87
|
Chris@101
|
88 void operator () (const const_node_ptr& p,
|
Chris@101
|
89 const return_type& check_return_left, const return_type& check_return_right,
|
Chris@101
|
90 return_type& check_return)
|
Chris@101
|
91 {
|
Chris@101
|
92
|
Chris@101
|
93 if (node_traits::get_color(p) == node_traits::red()){
|
Chris@101
|
94 //Red nodes have black children
|
Chris@101
|
95 const node_ptr p_left(node_traits::get_left(p));
|
Chris@101
|
96 const node_ptr p_right(node_traits::get_right(p));
|
Chris@101
|
97 BOOST_INTRUSIVE_INVARIANT_ASSERT(!p_left || node_traits::get_color(p_left) == node_traits::black());
|
Chris@101
|
98 BOOST_INTRUSIVE_INVARIANT_ASSERT(!p_right || node_traits::get_color(p_right) == node_traits::black());
|
Chris@101
|
99 //Red node can't be root
|
Chris@101
|
100 BOOST_INTRUSIVE_INVARIANT_ASSERT(node_traits::get_parent(node_traits::get_parent(p)) != p);
|
Chris@101
|
101 }
|
Chris@101
|
102 //Every path to p contains the same number of black nodes
|
Chris@101
|
103 const std::size_t l_black_count = check_return_left.black_count_;
|
Chris@101
|
104 BOOST_INTRUSIVE_INVARIANT_ASSERT(l_black_count == check_return_right.black_count_);
|
Chris@101
|
105 check_return.black_count_ = l_black_count +
|
Chris@101
|
106 static_cast<std::size_t>(node_traits::get_color(p) == node_traits::black());
|
Chris@101
|
107 base_checker_t::operator()(p, check_return_left, check_return_right, check_return);
|
Chris@16
|
108 }
|
Chris@16
|
109 };
|
Chris@16
|
110
|
Chris@101
|
111 } // namespace detail
|
Chris@101
|
112
|
Chris@16
|
113 #endif //#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
Chris@16
|
114
|
Chris@16
|
115 //! rbtree_algorithms provides basic algorithms to manipulate
|
Chris@16
|
116 //! nodes forming a red-black tree. The insertion and deletion algorithms are
|
Chris@16
|
117 //! based on those in Cormen, Leiserson, and Rivest, Introduction to Algorithms
|
Chris@16
|
118 //! (MIT Press, 1990), except that
|
Chris@16
|
119 //!
|
Chris@16
|
120 //! (1) the header node is maintained with links not only to the root
|
Chris@16
|
121 //! but also to the leftmost node of the tree, to enable constant time
|
Chris@16
|
122 //! begin(), and to the rightmost node of the tree, to enable linear time
|
Chris@16
|
123 //! performance when used with the generic set algorithms (set_union,
|
Chris@16
|
124 //! etc.);
|
Chris@16
|
125 //!
|
Chris@16
|
126 //! (2) when a node being deleted has two children its successor node is
|
Chris@16
|
127 //! relinked into its place, rather than copied, so that the only
|
Chris@16
|
128 //! pointers invalidated are those referring to the deleted node.
|
Chris@16
|
129 //!
|
Chris@16
|
130 //! rbtree_algorithms is configured with a NodeTraits class, which encapsulates the
|
Chris@16
|
131 //! information about the node to be manipulated. NodeTraits must support the
|
Chris@16
|
132 //! following interface:
|
Chris@16
|
133 //!
|
Chris@16
|
134 //! <b>Typedefs</b>:
|
Chris@16
|
135 //!
|
Chris@16
|
136 //! <tt>node</tt>: The type of the node that forms the binary search tree
|
Chris@16
|
137 //!
|
Chris@16
|
138 //! <tt>node_ptr</tt>: A pointer to a node
|
Chris@16
|
139 //!
|
Chris@16
|
140 //! <tt>const_node_ptr</tt>: A pointer to a const node
|
Chris@16
|
141 //!
|
Chris@16
|
142 //! <tt>color</tt>: The type that can store the color of a node
|
Chris@16
|
143 //!
|
Chris@16
|
144 //! <b>Static functions</b>:
|
Chris@16
|
145 //!
|
Chris@16
|
146 //! <tt>static node_ptr get_parent(const_node_ptr n);</tt>
|
Chris@16
|
147 //!
|
Chris@16
|
148 //! <tt>static void set_parent(node_ptr n, node_ptr parent);</tt>
|
Chris@16
|
149 //!
|
Chris@16
|
150 //! <tt>static node_ptr get_left(const_node_ptr n);</tt>
|
Chris@16
|
151 //!
|
Chris@16
|
152 //! <tt>static void set_left(node_ptr n, node_ptr left);</tt>
|
Chris@16
|
153 //!
|
Chris@16
|
154 //! <tt>static node_ptr get_right(const_node_ptr n);</tt>
|
Chris@16
|
155 //!
|
Chris@16
|
156 //! <tt>static void set_right(node_ptr n, node_ptr right);</tt>
|
Chris@16
|
157 //!
|
Chris@16
|
158 //! <tt>static color get_color(const_node_ptr n);</tt>
|
Chris@16
|
159 //!
|
Chris@16
|
160 //! <tt>static void set_color(node_ptr n, color c);</tt>
|
Chris@16
|
161 //!
|
Chris@16
|
162 //! <tt>static color black();</tt>
|
Chris@16
|
163 //!
|
Chris@16
|
164 //! <tt>static color red();</tt>
|
Chris@16
|
165 template<class NodeTraits>
|
Chris@16
|
166 class rbtree_algorithms
|
Chris@16
|
167 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
Chris@16
|
168 : public bstree_algorithms<NodeTraits>
|
Chris@16
|
169 #endif
|
Chris@16
|
170 {
|
Chris@16
|
171 public:
|
Chris@16
|
172 typedef NodeTraits node_traits;
|
Chris@16
|
173 typedef typename NodeTraits::node node;
|
Chris@16
|
174 typedef typename NodeTraits::node_ptr node_ptr;
|
Chris@16
|
175 typedef typename NodeTraits::const_node_ptr const_node_ptr;
|
Chris@16
|
176 typedef typename NodeTraits::color color;
|
Chris@16
|
177
|
Chris@16
|
178 /// @cond
|
Chris@16
|
179 private:
|
Chris@16
|
180
|
Chris@16
|
181 typedef bstree_algorithms<NodeTraits> bstree_algo;
|
Chris@16
|
182
|
Chris@16
|
183 /// @endcond
|
Chris@16
|
184
|
Chris@16
|
185 public:
|
Chris@16
|
186
|
Chris@16
|
187 //! This type is the information that will be
|
Chris@16
|
188 //! filled by insert_unique_check
|
Chris@16
|
189 typedef typename bstree_algo::insert_commit_data insert_commit_data;
|
Chris@16
|
190
|
Chris@16
|
191 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
Chris@16
|
192
|
Chris@16
|
193 //! @copydoc ::boost::intrusive::bstree_algorithms::get_header(const const_node_ptr&)
|
Chris@16
|
194 static node_ptr get_header(const const_node_ptr & n);
|
Chris@16
|
195
|
Chris@16
|
196 //! @copydoc ::boost::intrusive::bstree_algorithms::begin_node
|
Chris@16
|
197 static node_ptr begin_node(const const_node_ptr & header);
|
Chris@16
|
198
|
Chris@16
|
199 //! @copydoc ::boost::intrusive::bstree_algorithms::end_node
|
Chris@16
|
200 static node_ptr end_node(const const_node_ptr & header);
|
Chris@16
|
201
|
Chris@16
|
202 //! @copydoc ::boost::intrusive::bstree_algorithms::swap_tree
|
Chris@16
|
203 static void swap_tree(const node_ptr & header1, const node_ptr & header2);
|
Chris@101
|
204
|
Chris@16
|
205 #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
Chris@16
|
206
|
Chris@16
|
207 //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(const node_ptr&,const node_ptr&)
|
Chris@16
|
208 static void swap_nodes(const node_ptr & node1, const node_ptr & node2)
|
Chris@16
|
209 {
|
Chris@16
|
210 if(node1 == node2)
|
Chris@16
|
211 return;
|
Chris@16
|
212
|
Chris@16
|
213 node_ptr header1(bstree_algo::get_header(node1)), header2(bstree_algo::get_header(node2));
|
Chris@16
|
214 swap_nodes(node1, header1, node2, header2);
|
Chris@16
|
215 }
|
Chris@16
|
216
|
Chris@16
|
217 //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(const node_ptr&,const node_ptr&,const node_ptr&,const node_ptr&)
|
Chris@16
|
218 static void swap_nodes(const node_ptr & node1, const node_ptr & header1, const node_ptr & node2, const node_ptr & header2)
|
Chris@16
|
219 {
|
Chris@16
|
220 if(node1 == node2) return;
|
Chris@16
|
221
|
Chris@16
|
222 bstree_algo::swap_nodes(node1, header1, node2, header2);
|
Chris@16
|
223 //Swap color
|
Chris@16
|
224 color c = NodeTraits::get_color(node1);
|
Chris@16
|
225 NodeTraits::set_color(node1, NodeTraits::get_color(node2));
|
Chris@16
|
226 NodeTraits::set_color(node2, c);
|
Chris@16
|
227 }
|
Chris@16
|
228
|
Chris@16
|
229 //! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(const node_ptr&,const node_ptr&)
|
Chris@16
|
230 static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & new_node)
|
Chris@16
|
231 {
|
Chris@16
|
232 if(node_to_be_replaced == new_node)
|
Chris@16
|
233 return;
|
Chris@16
|
234 replace_node(node_to_be_replaced, bstree_algo::get_header(node_to_be_replaced), new_node);
|
Chris@16
|
235 }
|
Chris@16
|
236
|
Chris@16
|
237 //! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(const node_ptr&,const node_ptr&,const node_ptr&)
|
Chris@16
|
238 static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & header, const node_ptr & new_node)
|
Chris@16
|
239 {
|
Chris@16
|
240 bstree_algo::replace_node(node_to_be_replaced, header, new_node);
|
Chris@16
|
241 NodeTraits::set_color(new_node, NodeTraits::get_color(node_to_be_replaced));
|
Chris@16
|
242 }
|
Chris@16
|
243
|
Chris@16
|
244 //! @copydoc ::boost::intrusive::bstree_algorithms::unlink(const node_ptr&)
|
Chris@16
|
245 static void unlink(const node_ptr& node)
|
Chris@16
|
246 {
|
Chris@16
|
247 node_ptr x = NodeTraits::get_parent(node);
|
Chris@16
|
248 if(x){
|
Chris@16
|
249 while(!is_header(x))
|
Chris@16
|
250 x = NodeTraits::get_parent(x);
|
Chris@16
|
251 erase(x, node);
|
Chris@16
|
252 }
|
Chris@16
|
253 }
|
Chris@16
|
254
|
Chris@16
|
255 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
Chris@16
|
256 //! @copydoc ::boost::intrusive::bstree_algorithms::unlink_leftmost_without_rebalance
|
Chris@16
|
257 static node_ptr unlink_leftmost_without_rebalance(const node_ptr & header);
|
Chris@16
|
258
|
Chris@16
|
259 //! @copydoc ::boost::intrusive::bstree_algorithms::unique(const const_node_ptr&)
|
Chris@16
|
260 static bool unique(const const_node_ptr & node);
|
Chris@16
|
261
|
Chris@16
|
262 //! @copydoc ::boost::intrusive::bstree_algorithms::size(const const_node_ptr&)
|
Chris@16
|
263 static std::size_t size(const const_node_ptr & header);
|
Chris@16
|
264
|
Chris@16
|
265 //! @copydoc ::boost::intrusive::bstree_algorithms::next_node(const node_ptr&)
|
Chris@16
|
266 static node_ptr next_node(const node_ptr & node);
|
Chris@16
|
267
|
Chris@16
|
268 //! @copydoc ::boost::intrusive::bstree_algorithms::prev_node(const node_ptr&)
|
Chris@16
|
269 static node_ptr prev_node(const node_ptr & node);
|
Chris@16
|
270
|
Chris@16
|
271 //! @copydoc ::boost::intrusive::bstree_algorithms::init(const node_ptr&)
|
Chris@16
|
272 static void init(const node_ptr & node);
|
Chris@16
|
273 #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
Chris@16
|
274
|
Chris@16
|
275 //! @copydoc ::boost::intrusive::bstree_algorithms::init_header(const node_ptr&)
|
Chris@16
|
276 static void init_header(const node_ptr & header)
|
Chris@16
|
277 {
|
Chris@16
|
278 bstree_algo::init_header(header);
|
Chris@16
|
279 NodeTraits::set_color(header, NodeTraits::red());
|
Chris@16
|
280 }
|
Chris@16
|
281
|
Chris@16
|
282 //! @copydoc ::boost::intrusive::bstree_algorithms::erase(const node_ptr&,const node_ptr&)
|
Chris@16
|
283 static node_ptr erase(const node_ptr & header, const node_ptr & z)
|
Chris@16
|
284 {
|
Chris@16
|
285 typename bstree_algo::data_for_rebalance info;
|
Chris@101
|
286 bstree_algo::erase(header, z, info);
|
Chris@16
|
287
|
Chris@101
|
288 color new_z_color;
|
Chris@101
|
289 if(info.y != z){
|
Chris@101
|
290 new_z_color = NodeTraits::get_color(info.y);
|
Chris@101
|
291 NodeTraits::set_color(info.y, NodeTraits::get_color(z));
|
Chris@101
|
292 }
|
Chris@101
|
293 else{
|
Chris@101
|
294 new_z_color = NodeTraits::get_color(z);
|
Chris@101
|
295 }
|
Chris@101
|
296 //Rebalance rbtree if needed
|
Chris@101
|
297 if(new_z_color != NodeTraits::red()){
|
Chris@16
|
298 rebalance_after_erasure(header, info.x, info.x_parent);
|
Chris@16
|
299 }
|
Chris@16
|
300 return z;
|
Chris@16
|
301 }
|
Chris@16
|
302
|
Chris@16
|
303 //! @copydoc ::boost::intrusive::bstree_algorithms::clone(const const_node_ptr&,const node_ptr&,Cloner,Disposer)
|
Chris@16
|
304 template <class Cloner, class Disposer>
|
Chris@16
|
305 static void clone
|
Chris@16
|
306 (const const_node_ptr & source_header, const node_ptr & target_header, Cloner cloner, Disposer disposer)
|
Chris@16
|
307 {
|
Chris@16
|
308 rbtree_node_cloner<NodeTraits, Cloner> new_cloner(cloner);
|
Chris@16
|
309 bstree_algo::clone(source_header, target_header, new_cloner, disposer);
|
Chris@16
|
310 }
|
Chris@16
|
311
|
Chris@16
|
312 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
Chris@16
|
313 //! @copydoc ::boost::intrusive::bstree_algorithms::clear_and_dispose(const node_ptr&,Disposer)
|
Chris@16
|
314 template<class Disposer>
|
Chris@16
|
315 static void clear_and_dispose(const node_ptr & header, Disposer disposer);
|
Chris@16
|
316
|
Chris@16
|
317 //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
|
Chris@16
|
318 template<class KeyType, class KeyNodePtrCompare>
|
Chris@16
|
319 static node_ptr lower_bound
|
Chris@16
|
320 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
|
Chris@16
|
321
|
Chris@16
|
322 //! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
|
Chris@16
|
323 template<class KeyType, class KeyNodePtrCompare>
|
Chris@16
|
324 static node_ptr upper_bound
|
Chris@16
|
325 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
|
Chris@16
|
326
|
Chris@16
|
327 //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare)
|
Chris@16
|
328 template<class KeyType, class KeyNodePtrCompare>
|
Chris@16
|
329 static node_ptr find
|
Chris@16
|
330 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
|
Chris@16
|
331
|
Chris@16
|
332 //! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
|
Chris@16
|
333 template<class KeyType, class KeyNodePtrCompare>
|
Chris@16
|
334 static std::pair<node_ptr, node_ptr> equal_range
|
Chris@16
|
335 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
|
Chris@16
|
336
|
Chris@16
|
337 //! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool)
|
Chris@16
|
338 template<class KeyType, class KeyNodePtrCompare>
|
Chris@16
|
339 static std::pair<node_ptr, node_ptr> bounded_range
|
Chris@16
|
340 (const const_node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp
|
Chris@16
|
341 , bool left_closed, bool right_closed);
|
Chris@16
|
342
|
Chris@16
|
343 //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
|
Chris@16
|
344 template<class KeyType, class KeyNodePtrCompare>
|
Chris@16
|
345 static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
|
Chris@101
|
346
|
Chris@16
|
347 #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
Chris@16
|
348
|
Chris@16
|
349 //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_upper_bound(const node_ptr&,const node_ptr&,NodePtrCompare)
|
Chris@16
|
350 template<class NodePtrCompare>
|
Chris@16
|
351 static node_ptr insert_equal_upper_bound
|
Chris@16
|
352 (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp)
|
Chris@16
|
353 {
|
Chris@16
|
354 bstree_algo::insert_equal_upper_bound(h, new_node, comp);
|
Chris@16
|
355 rebalance_after_insertion(h, new_node);
|
Chris@16
|
356 return new_node;
|
Chris@16
|
357 }
|
Chris@16
|
358
|
Chris@16
|
359 //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_lower_bound(const node_ptr&,const node_ptr&,NodePtrCompare)
|
Chris@16
|
360 template<class NodePtrCompare>
|
Chris@16
|
361 static node_ptr insert_equal_lower_bound
|
Chris@16
|
362 (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp)
|
Chris@16
|
363 {
|
Chris@16
|
364 bstree_algo::insert_equal_lower_bound(h, new_node, comp);
|
Chris@16
|
365 rebalance_after_insertion(h, new_node);
|
Chris@16
|
366 return new_node;
|
Chris@16
|
367 }
|
Chris@16
|
368
|
Chris@16
|
369 //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal(const node_ptr&,const node_ptr&,const node_ptr&,NodePtrCompare)
|
Chris@16
|
370 template<class NodePtrCompare>
|
Chris@16
|
371 static node_ptr insert_equal
|
Chris@16
|
372 (const node_ptr & header, const node_ptr & hint, const node_ptr & new_node, NodePtrCompare comp)
|
Chris@16
|
373 {
|
Chris@16
|
374 bstree_algo::insert_equal(header, hint, new_node, comp);
|
Chris@16
|
375 rebalance_after_insertion(header, new_node);
|
Chris@16
|
376 return new_node;
|
Chris@16
|
377 }
|
Chris@16
|
378
|
Chris@16
|
379 //! @copydoc ::boost::intrusive::bstree_algorithms::insert_before(const node_ptr&,const node_ptr&,const node_ptr&)
|
Chris@16
|
380 static node_ptr insert_before
|
Chris@16
|
381 (const node_ptr & header, const node_ptr & pos, const node_ptr & new_node)
|
Chris@16
|
382 {
|
Chris@16
|
383 bstree_algo::insert_before(header, pos, new_node);
|
Chris@16
|
384 rebalance_after_insertion(header, new_node);
|
Chris@16
|
385 return new_node;
|
Chris@16
|
386 }
|
Chris@16
|
387
|
Chris@16
|
388 //! @copydoc ::boost::intrusive::bstree_algorithms::push_back(const node_ptr&,const node_ptr&)
|
Chris@16
|
389 static void push_back(const node_ptr & header, const node_ptr & new_node)
|
Chris@16
|
390 {
|
Chris@16
|
391 bstree_algo::push_back(header, new_node);
|
Chris@16
|
392 rebalance_after_insertion(header, new_node);
|
Chris@16
|
393 }
|
Chris@16
|
394
|
Chris@16
|
395 //! @copydoc ::boost::intrusive::bstree_algorithms::push_front(const node_ptr&,const node_ptr&)
|
Chris@16
|
396 static void push_front(const node_ptr & header, const node_ptr & new_node)
|
Chris@16
|
397 {
|
Chris@16
|
398 bstree_algo::push_front(header, new_node);
|
Chris@16
|
399 rebalance_after_insertion(header, new_node);
|
Chris@16
|
400 }
|
Chris@16
|
401
|
Chris@16
|
402 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
Chris@16
|
403 //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const const_node_ptr&,const KeyType&,KeyNodePtrCompare,insert_commit_data&)
|
Chris@16
|
404 template<class KeyType, class KeyNodePtrCompare>
|
Chris@16
|
405 static std::pair<node_ptr, bool> insert_unique_check
|
Chris@16
|
406 (const const_node_ptr & header, const KeyType &key
|
Chris@16
|
407 ,KeyNodePtrCompare comp, insert_commit_data &commit_data);
|
Chris@16
|
408
|
Chris@16
|
409 //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const const_node_ptr&,const node_ptr&,const KeyType&,KeyNodePtrCompare,insert_commit_data&)
|
Chris@16
|
410 template<class KeyType, class KeyNodePtrCompare>
|
Chris@16
|
411 static std::pair<node_ptr, bool> insert_unique_check
|
Chris@16
|
412 (const const_node_ptr & header, const node_ptr &hint, const KeyType &key
|
Chris@16
|
413 ,KeyNodePtrCompare comp, insert_commit_data &commit_data);
|
Chris@16
|
414 #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
Chris@16
|
415
|
Chris@16
|
416 //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_commit(const node_ptr&,const node_ptr&,const insert_commit_data&)
|
Chris@16
|
417 static void insert_unique_commit
|
Chris@16
|
418 (const node_ptr & header, const node_ptr & new_value, const insert_commit_data &commit_data)
|
Chris@16
|
419 {
|
Chris@16
|
420 bstree_algo::insert_unique_commit(header, new_value, commit_data);
|
Chris@16
|
421 rebalance_after_insertion(header, new_value);
|
Chris@16
|
422 }
|
Chris@16
|
423
|
Chris@16
|
424 //! @copydoc ::boost::intrusive::bstree_algorithms::is_header
|
Chris@16
|
425 static bool is_header(const const_node_ptr & p)
|
Chris@16
|
426 {
|
Chris@16
|
427 return NodeTraits::get_color(p) == NodeTraits::red() &&
|
Chris@16
|
428 bstree_algo::is_header(p);
|
Chris@16
|
429 }
|
Chris@16
|
430
|
Chris@16
|
431 /// @cond
|
Chris@16
|
432 private:
|
Chris@16
|
433
|
Chris@16
|
434 static void rebalance_after_erasure(const node_ptr & header, node_ptr x, node_ptr x_parent)
|
Chris@16
|
435 {
|
Chris@101
|
436 while(1){
|
Chris@101
|
437 if(x_parent == header || (x && NodeTraits::get_color(x) != NodeTraits::black())){
|
Chris@101
|
438 break;
|
Chris@101
|
439 }
|
Chris@101
|
440 //Don't cache x_is_leftchild or similar because x can be null and
|
Chris@101
|
441 //equal to both x_parent_left and x_parent_right
|
Chris@101
|
442 const node_ptr x_parent_left(NodeTraits::get_left(x_parent));
|
Chris@101
|
443 if(x == x_parent_left){ //x is left child
|
Chris@16
|
444 node_ptr w = NodeTraits::get_right(x_parent);
|
Chris@101
|
445 BOOST_INTRUSIVE_INVARIANT_ASSERT(w);
|
Chris@16
|
446 if(NodeTraits::get_color(w) == NodeTraits::red()){
|
Chris@16
|
447 NodeTraits::set_color(w, NodeTraits::black());
|
Chris@16
|
448 NodeTraits::set_color(x_parent, NodeTraits::red());
|
Chris@101
|
449 bstree_algo::rotate_left(x_parent, w, NodeTraits::get_parent(x_parent), header);
|
Chris@16
|
450 w = NodeTraits::get_right(x_parent);
|
Chris@16
|
451 }
|
Chris@101
|
452 node_ptr const w_left (NodeTraits::get_left(w));
|
Chris@101
|
453 node_ptr const w_right(NodeTraits::get_right(w));
|
Chris@101
|
454 if((!w_left || NodeTraits::get_color(w_left) == NodeTraits::black()) &&
|
Chris@101
|
455 (!w_right || NodeTraits::get_color(w_right) == NodeTraits::black())){
|
Chris@16
|
456 NodeTraits::set_color(w, NodeTraits::red());
|
Chris@16
|
457 x = x_parent;
|
Chris@16
|
458 x_parent = NodeTraits::get_parent(x_parent);
|
Chris@16
|
459 }
|
Chris@16
|
460 else {
|
Chris@101
|
461 if(!w_right || NodeTraits::get_color(w_right) == NodeTraits::black()){
|
Chris@101
|
462 NodeTraits::set_color(w_left, NodeTraits::black());
|
Chris@16
|
463 NodeTraits::set_color(w, NodeTraits::red());
|
Chris@101
|
464 bstree_algo::rotate_right(w, w_left, NodeTraits::get_parent(w), header);
|
Chris@16
|
465 w = NodeTraits::get_right(x_parent);
|
Chris@16
|
466 }
|
Chris@16
|
467 NodeTraits::set_color(w, NodeTraits::get_color(x_parent));
|
Chris@16
|
468 NodeTraits::set_color(x_parent, NodeTraits::black());
|
Chris@101
|
469 const node_ptr new_wright(NodeTraits::get_right(w));
|
Chris@101
|
470 if(new_wright)
|
Chris@101
|
471 NodeTraits::set_color(new_wright, NodeTraits::black());
|
Chris@101
|
472 bstree_algo::rotate_left(x_parent, NodeTraits::get_right(x_parent), NodeTraits::get_parent(x_parent), header);
|
Chris@16
|
473 break;
|
Chris@16
|
474 }
|
Chris@16
|
475 }
|
Chris@16
|
476 else {
|
Chris@16
|
477 // same as above, with right_ <-> left_.
|
Chris@101
|
478 node_ptr w = x_parent_left;
|
Chris@16
|
479 if(NodeTraits::get_color(w) == NodeTraits::red()){
|
Chris@16
|
480 NodeTraits::set_color(w, NodeTraits::black());
|
Chris@16
|
481 NodeTraits::set_color(x_parent, NodeTraits::red());
|
Chris@101
|
482 bstree_algo::rotate_right(x_parent, w, NodeTraits::get_parent(x_parent), header);
|
Chris@16
|
483 w = NodeTraits::get_left(x_parent);
|
Chris@16
|
484 }
|
Chris@101
|
485 node_ptr const w_left (NodeTraits::get_left(w));
|
Chris@101
|
486 node_ptr const w_right(NodeTraits::get_right(w));
|
Chris@101
|
487 if((!w_right || NodeTraits::get_color(w_right) == NodeTraits::black()) &&
|
Chris@101
|
488 (!w_left || NodeTraits::get_color(w_left) == NodeTraits::black())){
|
Chris@16
|
489 NodeTraits::set_color(w, NodeTraits::red());
|
Chris@16
|
490 x = x_parent;
|
Chris@16
|
491 x_parent = NodeTraits::get_parent(x_parent);
|
Chris@16
|
492 }
|
Chris@16
|
493 else {
|
Chris@101
|
494 if(!w_left || NodeTraits::get_color(w_left) == NodeTraits::black()){
|
Chris@101
|
495 NodeTraits::set_color(w_right, NodeTraits::black());
|
Chris@16
|
496 NodeTraits::set_color(w, NodeTraits::red());
|
Chris@101
|
497 bstree_algo::rotate_left(w, w_right, NodeTraits::get_parent(w), header);
|
Chris@16
|
498 w = NodeTraits::get_left(x_parent);
|
Chris@16
|
499 }
|
Chris@16
|
500 NodeTraits::set_color(w, NodeTraits::get_color(x_parent));
|
Chris@16
|
501 NodeTraits::set_color(x_parent, NodeTraits::black());
|
Chris@101
|
502 const node_ptr new_wleft(NodeTraits::get_left(w));
|
Chris@101
|
503 if(new_wleft)
|
Chris@101
|
504 NodeTraits::set_color(new_wleft, NodeTraits::black());
|
Chris@101
|
505 bstree_algo::rotate_right(x_parent, NodeTraits::get_left(x_parent), NodeTraits::get_parent(x_parent), header);
|
Chris@16
|
506 break;
|
Chris@16
|
507 }
|
Chris@16
|
508 }
|
Chris@16
|
509 }
|
Chris@16
|
510 if(x)
|
Chris@16
|
511 NodeTraits::set_color(x, NodeTraits::black());
|
Chris@16
|
512 }
|
Chris@16
|
513
|
Chris@16
|
514 static void rebalance_after_insertion(const node_ptr & header, node_ptr p)
|
Chris@16
|
515 {
|
Chris@16
|
516 NodeTraits::set_color(p, NodeTraits::red());
|
Chris@101
|
517 while(1){
|
Chris@16
|
518 node_ptr p_parent(NodeTraits::get_parent(p));
|
Chris@101
|
519 const node_ptr p_grandparent(NodeTraits::get_parent(p_parent));
|
Chris@101
|
520 if(p_parent == header || NodeTraits::get_color(p_parent) == NodeTraits::black() || p_grandparent == header){
|
Chris@101
|
521 break;
|
Chris@101
|
522 }
|
Chris@101
|
523
|
Chris@101
|
524 NodeTraits::set_color(p_grandparent, NodeTraits::red());
|
Chris@101
|
525 node_ptr const p_grandparent_left (NodeTraits::get_left (p_grandparent));
|
Chris@101
|
526 bool const p_parent_is_left_child = p_parent == p_grandparent_left;
|
Chris@101
|
527 node_ptr const x(p_parent_is_left_child ? NodeTraits::get_right(p_grandparent) : p_grandparent_left);
|
Chris@101
|
528
|
Chris@101
|
529 if(x && NodeTraits::get_color(x) == NodeTraits::red()){
|
Chris@101
|
530 NodeTraits::set_color(x, NodeTraits::black());
|
Chris@101
|
531 NodeTraits::set_color(p_parent, NodeTraits::black());
|
Chris@101
|
532 p = p_grandparent;
|
Chris@101
|
533 }
|
Chris@101
|
534 else{ //Final step
|
Chris@101
|
535 const bool p_is_left_child(NodeTraits::get_left(p_parent) == p);
|
Chris@101
|
536 if(p_parent_is_left_child){ //p_parent is left child
|
Chris@101
|
537 if(!p_is_left_child){ //p is right child
|
Chris@101
|
538 bstree_algo::rotate_left_no_parent_fix(p_parent, p);
|
Chris@101
|
539 //No need to link p and p_grandparent:
|
Chris@101
|
540 // [NodeTraits::set_parent(p, p_grandparent) + NodeTraits::set_left(p_grandparent, p)]
|
Chris@101
|
541 //as p_grandparent is not the header, another rotation is coming and p_parent
|
Chris@101
|
542 //will be the left child of p_grandparent
|
Chris@101
|
543 p_parent = p;
|
Chris@101
|
544 }
|
Chris@101
|
545 bstree_algo::rotate_right(p_grandparent, p_parent, NodeTraits::get_parent(p_grandparent), header);
|
Chris@16
|
546 }
|
Chris@101
|
547 else{ //p_parent is right child
|
Chris@101
|
548 if(p_is_left_child){ //p is left child
|
Chris@101
|
549 bstree_algo::rotate_right_no_parent_fix(p_parent, p);
|
Chris@101
|
550 //No need to link p and p_grandparent:
|
Chris@101
|
551 // [NodeTraits::set_parent(p, p_grandparent) + NodeTraits::set_right(p_grandparent, p)]
|
Chris@101
|
552 //as p_grandparent is not the header, another rotation is coming and p_parent
|
Chris@101
|
553 //will be the right child of p_grandparent
|
Chris@101
|
554 p_parent = p;
|
Chris@16
|
555 }
|
Chris@101
|
556 bstree_algo::rotate_left(p_grandparent, p_parent, NodeTraits::get_parent(p_grandparent), header);
|
Chris@16
|
557 }
|
Chris@101
|
558 NodeTraits::set_color(p_parent, NodeTraits::black());
|
Chris@101
|
559 break;
|
Chris@16
|
560 }
|
Chris@16
|
561 }
|
Chris@16
|
562 NodeTraits::set_color(NodeTraits::get_parent(header), NodeTraits::black());
|
Chris@16
|
563 }
|
Chris@16
|
564 /// @endcond
|
Chris@16
|
565 };
|
Chris@16
|
566
|
Chris@16
|
567 /// @cond
|
Chris@16
|
568
|
Chris@16
|
569 template<class NodeTraits>
|
Chris@16
|
570 struct get_algo<RbTreeAlgorithms, NodeTraits>
|
Chris@16
|
571 {
|
Chris@16
|
572 typedef rbtree_algorithms<NodeTraits> type;
|
Chris@16
|
573 };
|
Chris@16
|
574
|
Chris@101
|
575 template <class ValueTraits, class NodePtrCompare, class ExtraChecker>
|
Chris@101
|
576 struct get_node_checker<RbTreeAlgorithms, ValueTraits, NodePtrCompare, ExtraChecker>
|
Chris@101
|
577 {
|
Chris@101
|
578 typedef detail::rbtree_node_checker<ValueTraits, NodePtrCompare, ExtraChecker> type;
|
Chris@101
|
579 };
|
Chris@101
|
580
|
Chris@16
|
581 /// @endcond
|
Chris@16
|
582
|
Chris@16
|
583 } //namespace intrusive
|
Chris@16
|
584 } //namespace boost
|
Chris@16
|
585
|
Chris@16
|
586 #include <boost/intrusive/detail/config_end.hpp>
|
Chris@16
|
587
|
Chris@16
|
588 #endif //BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP
|