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