Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/intrusive/splaytree_algorithms.hpp @ 101:c530137014c0
Update Boost headers (1.58.0)
author | Chris Cannam |
---|---|
date | Mon, 07 Sep 2015 11:12:49 +0100 |
parents | 2665513ce2d3 |
children |
comparison
equal
deleted
inserted
replaced
100:793467b5e61c | 101:c530137014c0 |
---|---|
1 ///////////////////////////////////////////////////////////////////////////// | 1 ///////////////////////////////////////////////////////////////////////////// |
2 // | 2 // |
3 // (C) Copyright Ion Gaztanaga 2007-2013 | 3 // (C) Copyright Ion Gaztanaga 2007-2014 |
4 // | 4 // |
5 // Distributed under the Boost Software License, Version 1.0. | 5 // Distributed under the Boost Software License, Version 1.0. |
6 // (See accompanying file LICENSE_1_0.txt or copy at | 6 // (See accompanying file LICENSE_1_0.txt or copy at |
7 // http://www.boost.org/LICENSE_1_0.txt) | 7 // http://www.boost.org/LICENSE_1_0.txt) |
8 // | 8 // |
29 | 29 |
30 #ifndef BOOST_INTRUSIVE_SPLAYTREE_ALGORITHMS_HPP | 30 #ifndef BOOST_INTRUSIVE_SPLAYTREE_ALGORITHMS_HPP |
31 #define BOOST_INTRUSIVE_SPLAYTREE_ALGORITHMS_HPP | 31 #define BOOST_INTRUSIVE_SPLAYTREE_ALGORITHMS_HPP |
32 | 32 |
33 #include <boost/intrusive/detail/config_begin.hpp> | 33 #include <boost/intrusive/detail/config_begin.hpp> |
34 #include <boost/intrusive/intrusive_fwd.hpp> | |
34 #include <boost/intrusive/detail/assert.hpp> | 35 #include <boost/intrusive/detail/assert.hpp> |
35 #include <boost/intrusive/intrusive_fwd.hpp> | 36 #include <boost/intrusive/detail/algo_type.hpp> |
36 #include <boost/intrusive/pointer_traits.hpp> | 37 #include <boost/intrusive/detail/uncast.hpp> |
38 #include <boost/intrusive/bstree_algorithms.hpp> | |
39 | |
37 #include <cstddef> | 40 #include <cstddef> |
38 #include <boost/intrusive/detail/utilities.hpp> | 41 |
39 #include <boost/intrusive/bstree_algorithms.hpp> | 42 #if defined(BOOST_HAS_PRAGMA_ONCE) |
43 # pragma once | |
44 #endif | |
40 | 45 |
41 namespace boost { | 46 namespace boost { |
42 namespace intrusive { | 47 namespace intrusive { |
43 | 48 |
44 /// @cond | 49 /// @cond |
45 namespace detail { | 50 namespace detail { |
46 | 51 |
47 template<class NodeTraits> | 52 template<class NodeTraits> |
48 struct splaydown_rollback | 53 struct splaydown_assemble_and_fix_header |
49 { | 54 { |
50 typedef typename NodeTraits::node_ptr node_ptr; | 55 typedef typename NodeTraits::node_ptr node_ptr; |
51 splaydown_rollback( const node_ptr *pcur_subtree, const node_ptr & header | 56 |
52 , const node_ptr & leftmost , const node_ptr & rightmost) | 57 splaydown_assemble_and_fix_header(const node_ptr & t, const node_ptr & header, const node_ptr &leftmost, const node_ptr &rightmost) |
53 : pcur_subtree_(pcur_subtree) , header_(header) | 58 : t_(t) |
54 , leftmost_(leftmost) , rightmost_(rightmost) | 59 , null_node_(header) |
60 , l_(null_node_) | |
61 , r_(null_node_) | |
62 , leftmost_(leftmost) | |
63 , rightmost_(rightmost) | |
55 {} | 64 {} |
56 | 65 |
57 void release() | 66 ~splaydown_assemble_and_fix_header() |
58 { pcur_subtree_ = 0; } | 67 { |
59 | 68 this->assemble(); |
60 ~splaydown_rollback() | 69 |
61 { | 70 //Now recover the original header except for the |
62 if(pcur_subtree_){ | 71 //splayed root node. |
63 //Exception can only be thrown by comp, but | 72 //"t_" is the current root and "null_node_" is the header node |
64 //tree invariants still hold. *pcur_subtree is the current root | 73 NodeTraits::set_parent(null_node_, t_); |
65 //so link it to the header. | 74 NodeTraits::set_parent(t_, null_node_); |
66 NodeTraits::set_parent(*pcur_subtree_, header_); | 75 //Recover leftmost/rightmost pointers |
67 NodeTraits::set_parent(header_, *pcur_subtree_); | 76 NodeTraits::set_left (null_node_, leftmost_); |
68 //Recover leftmost/rightmost pointers | 77 NodeTraits::set_right(null_node_, rightmost_); |
69 NodeTraits::set_left (header_, leftmost_); | 78 } |
70 NodeTraits::set_right(header_, rightmost_); | 79 |
71 } | 80 private: |
72 } | 81 |
73 const node_ptr *pcur_subtree_; | 82 void assemble() |
74 node_ptr header_, leftmost_, rightmost_; | 83 { |
84 //procedure assemble; | |
85 // left(r), right(l) := right(t), left(t); | |
86 // left(t), right(t) := right(null), left(null); | |
87 //end assemble; | |
88 { // left(r), right(l) := right(t), left(t); | |
89 | |
90 node_ptr const old_t_left = NodeTraits::get_left(t_); | |
91 node_ptr const old_t_right = NodeTraits::get_right(t_); | |
92 NodeTraits::set_right(l_, old_t_left); | |
93 NodeTraits::set_left (r_, old_t_right); | |
94 if(old_t_left){ | |
95 NodeTraits::set_parent(old_t_left, l_); | |
96 } | |
97 if(old_t_right){ | |
98 NodeTraits::set_parent(old_t_right, r_); | |
99 } | |
100 } | |
101 { // left(t), right(t) := right(null), left(null); | |
102 node_ptr const null_right = NodeTraits::get_right(null_node_); | |
103 node_ptr const null_left = NodeTraits::get_left(null_node_); | |
104 NodeTraits::set_left (t_, null_right); | |
105 NodeTraits::set_right(t_, null_left); | |
106 if(null_right){ | |
107 NodeTraits::set_parent(null_right, t_); | |
108 } | |
109 if(null_left){ | |
110 NodeTraits::set_parent(null_left, t_); | |
111 } | |
112 } | |
113 } | |
114 | |
115 public: | |
116 node_ptr t_, null_node_, l_, r_, leftmost_, rightmost_; | |
75 }; | 117 }; |
76 | 118 |
77 } //namespace detail { | 119 } //namespace detail { |
78 /// @endcond | 120 /// @endcond |
79 | 121 |
178 //! @copydoc ::boost::intrusive::bstree_algorithms::init(const node_ptr&) | 220 //! @copydoc ::boost::intrusive::bstree_algorithms::init(const node_ptr&) |
179 static void init(const node_ptr & node); | 221 static void init(const node_ptr & node); |
180 | 222 |
181 //! @copydoc ::boost::intrusive::bstree_algorithms::init_header(const node_ptr&) | 223 //! @copydoc ::boost::intrusive::bstree_algorithms::init_header(const node_ptr&) |
182 static void init_header(const node_ptr & header); | 224 static void init_header(const node_ptr & header); |
183 | 225 |
184 #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED | 226 #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED |
185 | 227 |
186 //! @copydoc ::boost::intrusive::bstree_algorithms::erase(const node_ptr&,const node_ptr&) | 228 //! @copydoc ::boost::intrusive::bstree_algorithms::erase(const node_ptr&,const node_ptr&) |
187 //! Additional notes: the previous node of z is splayed. The "splay" parameter which indicated if splaying | 229 //! Additional notes: the previous node of z is splayed to speed up range deletions. |
188 //! should be performed, it's deprecated and will disappear in future versions. | 230 static void erase(const node_ptr & header, const node_ptr & z) |
189 static void erase(const node_ptr & header, const node_ptr & z, bool splay = true) | |
190 { | 231 { |
191 //posibility 1 | 232 //posibility 1 |
192 if(splay && NodeTraits::get_left(z)){ | 233 if(NodeTraits::get_left(z)){ |
193 splay_up(bstree_algo::prev_node(z), header); | 234 splay_up(bstree_algo::prev_node(z), header); |
194 } | 235 } |
195 /* | 236 |
196 //possibility 2 | 237 //possibility 2 |
197 if(splay && NodeTraits::get_left(z)){ | 238 //if(NodeTraits::get_left(z)){ |
198 node_ptr l = NodeTraits::get_left(z); | 239 // node_ptr l = NodeTraits::get_left(z); |
199 splay_up(l, header); | 240 // splay_up(l, header); |
200 }*//* | 241 //} |
201 if(splay && NodeTraits::get_left(z)){ | 242 |
202 node_ptr l = bstree_algo::prev_node(z); | 243 //if(NodeTraits::get_left(z)){ |
203 splay_up_impl(l, z); | 244 // node_ptr l = bstree_algo::prev_node(z); |
204 }*/ | 245 // splay_up_impl(l, z); |
205 /* | 246 //} |
247 | |
206 //possibility 4 | 248 //possibility 4 |
207 if(splay){ | 249 //splay_up(z, header); |
208 splay_up(z, header); | 250 |
209 }*/ | |
210 | |
211 //if(splay) | |
212 //splay_up(z, header); | |
213 bstree_algo::erase(header, z); | 251 bstree_algo::erase(header, z); |
214 } | 252 } |
215 | 253 |
216 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED | 254 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED |
217 //! @copydoc ::boost::intrusive::bstree_algorithms::clone(const const_node_ptr&,const node_ptr&,Cloner,Disposer) | 255 //! @copydoc ::boost::intrusive::bstree_algorithms::clone(const const_node_ptr&,const node_ptr&,Cloner,Disposer) |
223 template<class Disposer> | 261 template<class Disposer> |
224 static void clear_and_dispose(const node_ptr & header, Disposer disposer); | 262 static void clear_and_dispose(const node_ptr & header, Disposer disposer); |
225 | 263 |
226 #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED | 264 #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED |
227 //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) | 265 //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) |
228 //! Additional notes: the first node of the range is splayed. | 266 //! Additional notes: an element with key `key` is splayed. |
229 template<class KeyType, class KeyNodePtrCompare> | 267 template<class KeyType, class KeyNodePtrCompare> |
230 static std::size_t count | 268 static std::size_t count |
231 (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) | 269 (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) |
232 { | 270 { |
233 std::pair<node_ptr, node_ptr> ret = equal_range(header, key, comp); | 271 std::pair<node_ptr, node_ptr> ret = equal_range(header, key, comp); |
245 static std::size_t count | 283 static std::size_t count |
246 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) | 284 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) |
247 { return bstree_algo::count(header, key, comp); } | 285 { return bstree_algo::count(header, key, comp); } |
248 | 286 |
249 //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) | 287 //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) |
250 //! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying | 288 //! Additional notes: the first node of the range is splayed. |
251 //! should be performed, it's deprecated and will disappear in future versions. | |
252 template<class KeyType, class KeyNodePtrCompare> | 289 template<class KeyType, class KeyNodePtrCompare> |
253 static node_ptr lower_bound | 290 static node_ptr lower_bound |
254 (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) | 291 (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) |
255 { | 292 { |
256 //splay_down(detail::uncast(header), key, comp); | 293 splay_down(detail::uncast(header), key, comp); |
257 node_ptr y = bstree_algo::lower_bound(header, key, comp); | 294 node_ptr y = bstree_algo::lower_bound(header, key, comp); |
258 if(splay) splay_up(y, detail::uncast(header)); | 295 //splay_up(y, detail::uncast(header)); |
259 return y; | 296 return y; |
260 } | 297 } |
261 | 298 |
262 //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) | 299 //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) |
263 //! Additional note: no splaying is performed | 300 //! Additional note: no splaying is performed |
265 static node_ptr lower_bound | 302 static node_ptr lower_bound |
266 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) | 303 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) |
267 { return bstree_algo::lower_bound(header, key, comp); } | 304 { return bstree_algo::lower_bound(header, key, comp); } |
268 | 305 |
269 //! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) | 306 //! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) |
270 //! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying | 307 //! Additional notes: the first node of the range is splayed. |
271 //! should be performed, it's deprecated and will disappear in future versions. | |
272 template<class KeyType, class KeyNodePtrCompare> | 308 template<class KeyType, class KeyNodePtrCompare> |
273 static node_ptr upper_bound | 309 static node_ptr upper_bound |
274 (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) | 310 (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) |
275 { | 311 { |
276 //splay_down(detail::uncast(header), key, comp); | 312 splay_down(detail::uncast(header), key, comp); |
277 node_ptr y = bstree_algo::upper_bound(header, key, comp); | 313 node_ptr y = bstree_algo::upper_bound(header, key, comp); |
278 if(splay) splay_up(y, detail::uncast(header)); | 314 //splay_up(y, detail::uncast(header)); |
279 return y; | 315 return y; |
280 } | 316 } |
281 | 317 |
282 //! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) | 318 //! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) |
283 //! Additional note: no splaying is performed | 319 //! Additional note: no splaying is performed |
285 static node_ptr upper_bound | 321 static node_ptr upper_bound |
286 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) | 322 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) |
287 { return bstree_algo::upper_bound(header, key, comp); } | 323 { return bstree_algo::upper_bound(header, key, comp); } |
288 | 324 |
289 //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare) | 325 //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare) |
290 //! Additional notes: the found node of the lower bound is splayed. The "splay" parameter which indicated if splaying | 326 //! Additional notes: the found node of the lower bound is splayed. |
291 //! should be performed, it's deprecated and will disappear in future versions. | |
292 template<class KeyType, class KeyNodePtrCompare> | 327 template<class KeyType, class KeyNodePtrCompare> |
293 static node_ptr find | 328 static node_ptr find |
294 (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) | 329 (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) |
295 { | 330 { |
296 if(splay) splay_down(detail::uncast(header), key, comp); | 331 splay_down(detail::uncast(header), key, comp); |
297 node_ptr end = detail::uncast(header); | 332 return bstree_algo::find(header, key, comp); |
298 node_ptr y = bstree_algo::lower_bound(header, key, comp); | |
299 node_ptr r = (y == end || comp(key, y)) ? end : y; | |
300 return r; | |
301 } | 333 } |
302 | 334 |
303 //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare) | 335 //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare) |
304 //! Additional note: no splaying is performed | 336 //! Additional note: no splaying is performed |
305 template<class KeyType, class KeyNodePtrCompare> | 337 template<class KeyType, class KeyNodePtrCompare> |
306 static node_ptr find | 338 static node_ptr find |
307 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) | 339 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) |
308 { return bstree_algo::find(header, key, comp); } | 340 { return bstree_algo::find(header, key, comp); } |
309 | 341 |
310 //! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) | 342 //! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) |
311 //! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying | 343 //! Additional notes: the first node of the range is splayed. |
312 //! should be performed, it's deprecated and will disappear in future versions. | |
313 template<class KeyType, class KeyNodePtrCompare> | 344 template<class KeyType, class KeyNodePtrCompare> |
314 static std::pair<node_ptr, node_ptr> equal_range | 345 static std::pair<node_ptr, node_ptr> equal_range |
315 (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) | 346 (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) |
316 { | 347 { |
317 //splay_down(detail::uncast(header), key, comp); | 348 splay_down(detail::uncast(header), key, comp); |
318 std::pair<node_ptr, node_ptr> ret = bstree_algo::equal_range(header, key, comp); | 349 std::pair<node_ptr, node_ptr> ret = bstree_algo::equal_range(header, key, comp); |
319 if(splay) splay_up(ret.first, detail::uncast(header)); | 350 //splay_up(ret.first, detail::uncast(header)); |
320 return ret; | 351 return ret; |
321 } | 352 } |
322 | 353 |
323 //! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) | 354 //! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) |
324 //! Additional note: no splaying is performed | 355 //! Additional note: no splaying is performed |
325 template<class KeyType, class KeyNodePtrCompare> | 356 template<class KeyType, class KeyNodePtrCompare> |
326 static std::pair<node_ptr, node_ptr> equal_range | 357 static std::pair<node_ptr, node_ptr> equal_range |
327 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) | 358 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) |
328 { return bstree_algo::equal_range(header, key, comp); } | 359 { return bstree_algo::equal_range(header, key, comp); } |
329 | 360 |
361 //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) | |
362 //! Additional notes: the first node of the range is splayed. | |
363 template<class KeyType, class KeyNodePtrCompare> | |
364 static std::pair<node_ptr, node_ptr> lower_bound_range | |
365 (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) | |
366 { | |
367 splay_down(detail::uncast(header), key, comp); | |
368 std::pair<node_ptr, node_ptr> ret = bstree_algo::lower_bound_range(header, key, comp); | |
369 //splay_up(ret.first, detail::uncast(header)); | |
370 return ret; | |
371 } | |
372 | |
373 //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) | |
374 //! Additional note: no splaying is performed | |
375 template<class KeyType, class KeyNodePtrCompare> | |
376 static std::pair<node_ptr, node_ptr> lower_bound_range | |
377 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) | |
378 { return bstree_algo::lower_bound_range(header, key, comp); } | |
379 | |
330 //! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool) | 380 //! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool) |
331 //! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying | 381 //! Additional notes: the first node of the range is splayed. |
332 //! should be performed, it's deprecated and will disappear in future versions. | |
333 template<class KeyType, class KeyNodePtrCompare> | 382 template<class KeyType, class KeyNodePtrCompare> |
334 static std::pair<node_ptr, node_ptr> bounded_range | 383 static std::pair<node_ptr, node_ptr> bounded_range |
335 (const node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp | 384 (const node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp |
336 , bool left_closed, bool right_closed, bool splay = true) | 385 , bool left_closed, bool right_closed) |
337 { | 386 { |
387 splay_down(detail::uncast(header), lower_key, comp); | |
338 std::pair<node_ptr, node_ptr> ret = | 388 std::pair<node_ptr, node_ptr> ret = |
339 bstree_algo::bounded_range(header, lower_key, upper_key, comp, left_closed, right_closed); | 389 bstree_algo::bounded_range(header, lower_key, upper_key, comp, left_closed, right_closed); |
340 if(splay) splay_up(ret.first, detail::uncast(header)); | 390 //splay_up(ret.first, detail::uncast(header)); |
341 return ret; | 391 return ret; |
342 } | 392 } |
343 | 393 |
344 //! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool) | 394 //! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool) |
345 //! Additional note: no splaying is performed | 395 //! Additional note: no splaying is performed |
443 | 493 |
444 #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED | 494 #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED |
445 | 495 |
446 // bottom-up splay, use data_ as parent for n | complexity : logarithmic | exception : nothrow | 496 // bottom-up splay, use data_ as parent for n | complexity : logarithmic | exception : nothrow |
447 static void splay_up(const node_ptr & node, const node_ptr & header) | 497 static void splay_up(const node_ptr & node, const node_ptr & header) |
498 { priv_splay_up<true>(node, header); } | |
499 | |
500 // top-down splay | complexity : logarithmic | exception : strong, note A | |
501 template<class KeyType, class KeyNodePtrCompare> | |
502 static node_ptr splay_down(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool *pfound = 0) | |
503 { return priv_splay_down<true>(header, key, comp, pfound); } | |
504 | |
505 private: | |
506 | |
507 /// @cond | |
508 | |
509 // bottom-up splay, use data_ as parent for n | complexity : logarithmic | exception : nothrow | |
510 template<bool SimpleSplay> | |
511 static void priv_splay_up(const node_ptr & node, const node_ptr & header) | |
448 { | 512 { |
449 // If (node == header) do a splay for the right most node instead | 513 // If (node == header) do a splay for the right most node instead |
450 // this is to boost performance of equal_range/count on equivalent containers in the case | 514 // this is to boost performance of equal_range/count on equivalent containers in the case |
451 // where there are many equal elements at the end | 515 // where there are many equal elements at the end |
452 node_ptr n((node == header) ? NodeTraits::get_right(header) : node); | 516 node_ptr n((node == header) ? NodeTraits::get_right(header) : node); |
468 (NodeTraits::get_right(p) == n && NodeTraits::get_right(g) == p) ){ | 532 (NodeTraits::get_right(p) == n && NodeTraits::get_right(g) == p) ){ |
469 // zig-zig | 533 // zig-zig |
470 rotate(p); | 534 rotate(p); |
471 rotate(n); | 535 rotate(n); |
472 } | 536 } |
473 else{ | 537 else { |
474 // zig-zag | 538 // zig-zag |
475 rotate(n); | 539 rotate(n); |
476 rotate(n); | 540 if(!SimpleSplay){ |
477 } | 541 rotate(n); |
478 } | 542 } |
479 } | 543 } |
480 | 544 } |
481 // top-down splay | complexity : logarithmic | exception : strong, note A | 545 } |
482 template<class KeyType, class KeyNodePtrCompare> | 546 |
483 static node_ptr splay_down(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) | 547 template<bool SimpleSplay, class KeyType, class KeyNodePtrCompare> |
484 { | 548 static node_ptr priv_splay_down(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool *pfound = 0) |
485 if(!NodeTraits::get_parent(header)) | 549 { |
486 return header; | |
487 //Most splay tree implementations use a dummy/null node to implement. | 550 //Most splay tree implementations use a dummy/null node to implement. |
488 //this function. This has some problems for a generic library like Intrusive: | 551 //this function. This has some problems for a generic library like Intrusive: |
489 // | 552 // |
490 // * The node might not have a default constructor. | 553 // * The node might not have a default constructor. |
491 // * The default constructor could throw. | 554 // * The default constructor could throw. |
492 // | 555 // |
493 //We already have a header node. Leftmost and rightmost nodes of the tree | 556 //We already have a header node. Leftmost and rightmost nodes of the tree |
494 //are not changed when splaying (because the invariants of the tree don't | 557 //are not changed when splaying (because the invariants of the tree don't |
495 //change) We can back up them, use the header as the null node and | 558 //change) We can back up them, use the header as the null node and |
496 //reassign old values after the function has been completed. | 559 //reassign old values after the function has been completed. |
497 node_ptr t = NodeTraits::get_parent(header); | 560 node_ptr const old_root = NodeTraits::get_parent(header); |
498 //Check if tree has a single node | 561 node_ptr const leftmost = NodeTraits::get_left(header); |
499 if(!NodeTraits::get_left(t) && !NodeTraits::get_right(t)) | 562 node_ptr const rightmost = NodeTraits::get_right(header); |
500 return t; | 563 if(leftmost == rightmost){ //Empty or unique node |
501 //Backup leftmost/rightmost | 564 if(pfound){ |
502 node_ptr leftmost (NodeTraits::get_left(header)); | 565 *pfound = old_root && !comp(key, old_root) && !comp(old_root, key); |
503 node_ptr rightmost(NodeTraits::get_right(header)); | 566 } |
504 { | 567 return old_root ? old_root : header; |
505 //Anti-exception rollback, recovers the original header node if an exception is thrown. | 568 } |
506 detail::splaydown_rollback<NodeTraits> rollback(&t, header, leftmost, rightmost); | 569 else{ |
507 node_ptr null_node = header; | 570 //Initialize "null node" (the header in our case) |
508 node_ptr l = null_node; | 571 NodeTraits::set_left (header, node_ptr()); |
509 node_ptr r = null_node; | 572 NodeTraits::set_right(header, node_ptr()); |
573 //Class that will backup leftmost/rightmost from header, commit the assemble(), | |
574 //and will restore leftmost/rightmost to header even if "comp" throws | |
575 detail::splaydown_assemble_and_fix_header<NodeTraits> commit(old_root, header, leftmost, rightmost); | |
576 bool found = false; | |
510 | 577 |
511 for( ;; ){ | 578 for( ;; ){ |
512 if(comp(key, t)){ | 579 if(comp(key, commit.t_)){ |
513 if(NodeTraits::get_left(t) == node_ptr() ) | 580 node_ptr const t_left = NodeTraits::get_left(commit.t_); |
581 if(!t_left) | |
514 break; | 582 break; |
515 if(comp(key, NodeTraits::get_left(t))){ | 583 if(comp(key, t_left)){ |
516 t = bstree_algo::rotate_right(t); | 584 bstree_algo::rotate_right_no_parent_fix(commit.t_, t_left); |
517 | 585 commit.t_ = t_left; |
518 if(NodeTraits::get_left(t) == node_ptr()) | 586 if( !NodeTraits::get_left(commit.t_) ) |
519 break; | 587 break; |
520 link_right(t, r); | 588 link_right(commit.t_, commit.r_); |
521 } | |
522 else if(comp(NodeTraits::get_left(t), key)){ | |
523 link_right(t, r); | |
524 | |
525 if(NodeTraits::get_right(t) == node_ptr() ) | |
526 break; | |
527 link_left(t, l); | |
528 } | 589 } |
529 else{ | 590 else{ |
530 link_right(t, r); | 591 link_right(commit.t_, commit.r_); |
592 if(!SimpleSplay && comp(t_left, key)){ | |
593 if( !NodeTraits::get_right(commit.t_) ) | |
594 break; | |
595 link_left(commit.t_, commit.l_); | |
596 } | |
531 } | 597 } |
532 } | 598 } |
533 else if(comp(t, key)){ | 599 else if(comp(commit.t_, key)){ |
534 if(NodeTraits::get_right(t) == node_ptr() ) | 600 node_ptr const t_right = NodeTraits::get_right(commit.t_); |
601 if(!t_right) | |
535 break; | 602 break; |
536 | 603 |
537 if(comp(NodeTraits::get_right(t), key)){ | 604 if(comp(t_right, key)){ |
538 t = bstree_algo::rotate_left( t ); | 605 bstree_algo::rotate_left_no_parent_fix(commit.t_, t_right); |
539 | 606 commit.t_ = t_right; |
540 if(NodeTraits::get_right(t) == node_ptr() ) | 607 if( !NodeTraits::get_right(commit.t_) ) |
541 break; | 608 break; |
542 link_left(t, l); | 609 link_left(commit.t_, commit.l_); |
543 } | |
544 else if(comp(key, NodeTraits::get_right(t))){ | |
545 link_left(t, l); | |
546 | |
547 if(NodeTraits::get_left(t) == node_ptr()) | |
548 break; | |
549 | |
550 link_right(t, r); | |
551 } | 610 } |
552 else{ | 611 else{ |
553 link_left(t, l); | 612 link_left(commit.t_, commit.l_); |
613 if(!SimpleSplay && comp(key, t_right)){ | |
614 if( !NodeTraits::get_left(commit.t_) ) | |
615 break; | |
616 link_right(commit.t_, commit.r_); | |
617 } | |
554 } | 618 } |
555 } | 619 } |
556 else{ | 620 else{ |
621 found = true; | |
557 break; | 622 break; |
558 } | 623 } |
559 } | 624 } |
560 | 625 |
561 assemble(t, l, r, null_node); | 626 //commit.~splaydown_assemble_and_fix_header<NodeTraits>() will first |
562 rollback.release(); | 627 //"assemble()" + link the new root & recover header's leftmost & rightmost |
563 } | 628 if(pfound){ |
564 | 629 *pfound = found; |
565 //Now recover the original header except for the | 630 } |
566 //splayed root node. | 631 return commit.t_; |
567 //t is the current root | |
568 NodeTraits::set_parent(header, t); | |
569 NodeTraits::set_parent(t, header); | |
570 //Recover leftmost/rightmost pointers | |
571 NodeTraits::set_left (header, leftmost); | |
572 NodeTraits::set_right(header, rightmost); | |
573 return t; | |
574 } | |
575 | |
576 private: | |
577 | |
578 /// @cond | |
579 | |
580 // assemble the three sub-trees into new tree pointed to by t | complexity : constant | exception : nothrow | |
581 static void assemble(const node_ptr &t, const node_ptr & l, const node_ptr & r, const const_node_ptr & null_node ) | |
582 { | |
583 NodeTraits::set_right(l, NodeTraits::get_left(t)); | |
584 NodeTraits::set_left(r, NodeTraits::get_right(t)); | |
585 | |
586 if(NodeTraits::get_right(l) != node_ptr()){ | |
587 NodeTraits::set_parent(NodeTraits::get_right(l), l); | |
588 } | |
589 | |
590 if(NodeTraits::get_left(r) != node_ptr()){ | |
591 NodeTraits::set_parent(NodeTraits::get_left(r), r); | |
592 } | |
593 | |
594 NodeTraits::set_left (t, NodeTraits::get_right(null_node)); | |
595 NodeTraits::set_right(t, NodeTraits::get_left(null_node)); | |
596 | |
597 if( NodeTraits::get_left(t) != node_ptr() ){ | |
598 NodeTraits::set_parent(NodeTraits::get_left(t), t); | |
599 } | |
600 | |
601 if( NodeTraits::get_right(t) ){ | |
602 NodeTraits::set_parent(NodeTraits::get_right(t), t); | |
603 } | 632 } |
604 } | 633 } |
605 | 634 |
606 // break link to left child node and attach it to left tree pointed to by l | complexity : constant | exception : nothrow | 635 // break link to left child node and attach it to left tree pointed to by l | complexity : constant | exception : nothrow |
607 static void link_left(node_ptr & t, node_ptr & l) | 636 static void link_left(node_ptr & t, node_ptr & l) |
608 { | 637 { |
638 //procedure link_left; | |
639 // t, l, right(l) := right(t), t, t | |
640 //end link_left | |
609 NodeTraits::set_right(l, t); | 641 NodeTraits::set_right(l, t); |
610 NodeTraits::set_parent(t, l); | 642 NodeTraits::set_parent(t, l); |
611 l = t; | 643 l = t; |
612 t = NodeTraits::get_right(t); | 644 t = NodeTraits::get_right(t); |
613 } | 645 } |
614 | 646 |
615 // break link to right child node and attach it to right tree pointed to by r | complexity : constant | exception : nothrow | 647 // break link to right child node and attach it to right tree pointed to by r | complexity : constant | exception : nothrow |
616 static void link_right(node_ptr & t, node_ptr & r) | 648 static void link_right(node_ptr & t, node_ptr & r) |
617 { | 649 { |
650 //procedure link_right; | |
651 // t, r, left(r) := left(t), t, t | |
652 //end link_right; | |
618 NodeTraits::set_left(r, t); | 653 NodeTraits::set_left(r, t); |
619 NodeTraits::set_parent(t, r); | 654 NodeTraits::set_parent(t, r); |
620 r = t; | 655 r = t; |
621 t = NodeTraits::get_left(t); | 656 t = NodeTraits::get_left(t); |
622 } | 657 } |
623 | 658 |
624 // rotate n with its parent | complexity : constant | exception : nothrow | 659 // rotate n with its parent | complexity : constant | exception : nothrow |
625 static void rotate(const node_ptr & n) | 660 static void rotate(const node_ptr & n) |
626 { | 661 { |
662 //procedure rotate_left; | |
663 // t, right(t), left(right(t)) := right(t), left(right(t)), t | |
664 //end rotate_left; | |
627 node_ptr p = NodeTraits::get_parent(n); | 665 node_ptr p = NodeTraits::get_parent(n); |
628 node_ptr g = NodeTraits::get_parent(p); | 666 node_ptr g = NodeTraits::get_parent(p); |
629 //Test if g is header before breaking tree | 667 //Test if g is header before breaking tree |
630 //invariants that would make is_header invalid | 668 //invariants that would make is_header invalid |
631 bool g_is_header = bstree_algo::is_header(g); | 669 bool g_is_header = bstree_algo::is_header(g); |
632 | 670 |
633 if(NodeTraits::get_left(p) == n){ | 671 if(NodeTraits::get_left(p) == n){ |
634 NodeTraits::set_left(p, NodeTraits::get_right(n)); | 672 NodeTraits::set_left(p, NodeTraits::get_right(n)); |
635 if(NodeTraits::get_left(p) != node_ptr()) | 673 if(NodeTraits::get_left(p)) |
636 NodeTraits::set_parent(NodeTraits::get_left(p), p); | 674 NodeTraits::set_parent(NodeTraits::get_left(p), p); |
637 NodeTraits::set_right(n, p); | 675 NodeTraits::set_right(n, p); |
638 } | 676 } |
639 else{ // must be ( p->right == n ) | 677 else{ // must be ( p->right == n ) |
640 NodeTraits::set_right(p, NodeTraits::get_left(n)); | 678 NodeTraits::set_right(p, NodeTraits::get_left(n)); |
641 if(NodeTraits::get_right(p) != node_ptr()) | 679 if(NodeTraits::get_right(p)) |
642 NodeTraits::set_parent(NodeTraits::get_right(p), p); | 680 NodeTraits::set_parent(NodeTraits::get_right(p), p); |
643 NodeTraits::set_left(n, p); | 681 NodeTraits::set_left(n, p); |
644 } | 682 } |
645 | 683 |
646 NodeTraits::set_parent(p, n); | 684 NodeTraits::set_parent(p, n); |
671 struct get_algo<SplayTreeAlgorithms, NodeTraits> | 709 struct get_algo<SplayTreeAlgorithms, NodeTraits> |
672 { | 710 { |
673 typedef splaytree_algorithms<NodeTraits> type; | 711 typedef splaytree_algorithms<NodeTraits> type; |
674 }; | 712 }; |
675 | 713 |
714 template <class ValueTraits, class NodePtrCompare, class ExtraChecker> | |
715 struct get_node_checker<SplayTreeAlgorithms, ValueTraits, NodePtrCompare, ExtraChecker> | |
716 { | |
717 typedef detail::bstree_node_checker<ValueTraits, NodePtrCompare, ExtraChecker> type; | |
718 }; | |
719 | |
676 /// @endcond | 720 /// @endcond |
677 | 721 |
678 } //namespace intrusive | 722 } //namespace intrusive |
679 } //namespace boost | 723 } //namespace boost |
680 | 724 |