annotate DEPENDENCIES/generic/include/boost/intrusive/splaytree_algorithms.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
rev   line source
Chris@16 1 /////////////////////////////////////////////////////////////////////////////
Chris@16 2 //
Chris@16 3 // (C) Copyright Ion Gaztanaga 2007-2013
Chris@16 4 //
Chris@16 5 // Distributed under the Boost Software License, Version 1.0.
Chris@16 6 // (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 7 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 8 //
Chris@16 9 // See http://www.boost.org/libs/intrusive for documentation.
Chris@16 10 //
Chris@16 11 /////////////////////////////////////////////////////////////////////////////
Chris@16 12 // The implementation of splay trees is based on the article and code published
Chris@16 13 // in C++ Users Journal "Implementing Splay Trees in C++" (September 1, 2005).
Chris@16 14 //
Chris@16 15 // The splay code has been modified and (supposedly) improved by Ion Gaztanaga.
Chris@16 16 //
Chris@16 17 // Here is the copyright notice of the original file containing the splay code:
Chris@16 18 //
Chris@16 19 // splay_tree.h -- implementation of a STL compatible splay tree.
Chris@16 20 //
Chris@16 21 // Copyright (c) 2004 Ralf Mattethat
Chris@16 22 //
Chris@16 23 // Permission to copy, use, modify, sell and distribute this software
Chris@16 24 // is granted provided this copyright notice appears in all copies.
Chris@16 25 // This software is provided "as is" without express or implied
Chris@16 26 // warranty, and with no claim as to its suitability for any purpose.
Chris@16 27 //
Chris@16 28 /////////////////////////////////////////////////////////////////////////////
Chris@16 29
Chris@16 30 #ifndef BOOST_INTRUSIVE_SPLAYTREE_ALGORITHMS_HPP
Chris@16 31 #define BOOST_INTRUSIVE_SPLAYTREE_ALGORITHMS_HPP
Chris@16 32
Chris@16 33 #include <boost/intrusive/detail/config_begin.hpp>
Chris@16 34 #include <boost/intrusive/detail/assert.hpp>
Chris@16 35 #include <boost/intrusive/intrusive_fwd.hpp>
Chris@16 36 #include <boost/intrusive/pointer_traits.hpp>
Chris@16 37 #include <cstddef>
Chris@16 38 #include <boost/intrusive/detail/utilities.hpp>
Chris@16 39 #include <boost/intrusive/bstree_algorithms.hpp>
Chris@16 40
Chris@16 41 namespace boost {
Chris@16 42 namespace intrusive {
Chris@16 43
Chris@16 44 /// @cond
Chris@16 45 namespace detail {
Chris@16 46
Chris@16 47 template<class NodeTraits>
Chris@16 48 struct splaydown_rollback
Chris@16 49 {
Chris@16 50 typedef typename NodeTraits::node_ptr node_ptr;
Chris@16 51 splaydown_rollback( const node_ptr *pcur_subtree, const node_ptr & header
Chris@16 52 , const node_ptr & leftmost , const node_ptr & rightmost)
Chris@16 53 : pcur_subtree_(pcur_subtree) , header_(header)
Chris@16 54 , leftmost_(leftmost) , rightmost_(rightmost)
Chris@16 55 {}
Chris@16 56
Chris@16 57 void release()
Chris@16 58 { pcur_subtree_ = 0; }
Chris@16 59
Chris@16 60 ~splaydown_rollback()
Chris@16 61 {
Chris@16 62 if(pcur_subtree_){
Chris@16 63 //Exception can only be thrown by comp, but
Chris@16 64 //tree invariants still hold. *pcur_subtree is the current root
Chris@16 65 //so link it to the header.
Chris@16 66 NodeTraits::set_parent(*pcur_subtree_, header_);
Chris@16 67 NodeTraits::set_parent(header_, *pcur_subtree_);
Chris@16 68 //Recover leftmost/rightmost pointers
Chris@16 69 NodeTraits::set_left (header_, leftmost_);
Chris@16 70 NodeTraits::set_right(header_, rightmost_);
Chris@16 71 }
Chris@16 72 }
Chris@16 73 const node_ptr *pcur_subtree_;
Chris@16 74 node_ptr header_, leftmost_, rightmost_;
Chris@16 75 };
Chris@16 76
Chris@16 77 } //namespace detail {
Chris@16 78 /// @endcond
Chris@16 79
Chris@16 80 //! A splay tree is an implementation of a binary search tree. The tree is
Chris@16 81 //! self balancing using the splay algorithm as described in
Chris@16 82 //!
Chris@16 83 //! "Self-Adjusting Binary Search Trees
Chris@16 84 //! by Daniel Dominic Sleator and Robert Endre Tarjan
Chris@16 85 //! AT&T Bell Laboratories, Murray Hill, NJ
Chris@16 86 //! Journal of the ACM, Vol 32, no 3, July 1985, pp 652-686
Chris@16 87 //!
Chris@16 88 //! splaytree_algorithms is configured with a NodeTraits class, which encapsulates the
Chris@16 89 //! information about the node to be manipulated. NodeTraits must support the
Chris@16 90 //! following interface:
Chris@16 91 //!
Chris@16 92 //! <b>Typedefs</b>:
Chris@16 93 //!
Chris@16 94 //! <tt>node</tt>: The type of the node that forms the binary search tree
Chris@16 95 //!
Chris@16 96 //! <tt>node_ptr</tt>: A pointer to a node
Chris@16 97 //!
Chris@16 98 //! <tt>const_node_ptr</tt>: A pointer to a const node
Chris@16 99 //!
Chris@16 100 //! <b>Static functions</b>:
Chris@16 101 //!
Chris@16 102 //! <tt>static node_ptr get_parent(const_node_ptr n);</tt>
Chris@16 103 //!
Chris@16 104 //! <tt>static void set_parent(node_ptr n, node_ptr parent);</tt>
Chris@16 105 //!
Chris@16 106 //! <tt>static node_ptr get_left(const_node_ptr n);</tt>
Chris@16 107 //!
Chris@16 108 //! <tt>static void set_left(node_ptr n, node_ptr left);</tt>
Chris@16 109 //!
Chris@16 110 //! <tt>static node_ptr get_right(const_node_ptr n);</tt>
Chris@16 111 //!
Chris@16 112 //! <tt>static void set_right(node_ptr n, node_ptr right);</tt>
Chris@16 113 template<class NodeTraits>
Chris@16 114 class splaytree_algorithms
Chris@16 115 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
Chris@16 116 : public bstree_algorithms<NodeTraits>
Chris@16 117 #endif
Chris@16 118 {
Chris@16 119 /// @cond
Chris@16 120 private:
Chris@16 121 typedef bstree_algorithms<NodeTraits> bstree_algo;
Chris@16 122 /// @endcond
Chris@16 123
Chris@16 124 public:
Chris@16 125 typedef typename NodeTraits::node node;
Chris@16 126 typedef NodeTraits node_traits;
Chris@16 127 typedef typename NodeTraits::node_ptr node_ptr;
Chris@16 128 typedef typename NodeTraits::const_node_ptr const_node_ptr;
Chris@16 129
Chris@16 130 //! This type is the information that will be
Chris@16 131 //! filled by insert_unique_check
Chris@16 132 typedef typename bstree_algo::insert_commit_data insert_commit_data;
Chris@16 133
Chris@16 134 public:
Chris@16 135 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
Chris@16 136 //! @copydoc ::boost::intrusive::bstree_algorithms::get_header(const const_node_ptr&)
Chris@16 137 static node_ptr get_header(const const_node_ptr & n);
Chris@16 138
Chris@16 139 //! @copydoc ::boost::intrusive::bstree_algorithms::begin_node
Chris@16 140 static node_ptr begin_node(const const_node_ptr & header);
Chris@16 141
Chris@16 142 //! @copydoc ::boost::intrusive::bstree_algorithms::end_node
Chris@16 143 static node_ptr end_node(const const_node_ptr & header);
Chris@16 144
Chris@16 145 //! @copydoc ::boost::intrusive::bstree_algorithms::swap_tree
Chris@16 146 static void swap_tree(const node_ptr & header1, const node_ptr & header2);
Chris@16 147
Chris@16 148 //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(const node_ptr&,const node_ptr&)
Chris@16 149 static void swap_nodes(const node_ptr & node1, const node_ptr & node2);
Chris@16 150
Chris@16 151 //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(const node_ptr&,const node_ptr&,const node_ptr&,const node_ptr&)
Chris@16 152 static void swap_nodes(const node_ptr & node1, const node_ptr & header1, const node_ptr & node2, const node_ptr & header2);
Chris@16 153
Chris@16 154 //! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(const node_ptr&,const node_ptr&)
Chris@16 155 static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & new_node);
Chris@16 156
Chris@16 157 //! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(const node_ptr&,const node_ptr&,const node_ptr&)
Chris@16 158 static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & header, const node_ptr & new_node);
Chris@16 159
Chris@16 160 //! @copydoc ::boost::intrusive::bstree_algorithms::unlink(const node_ptr&)
Chris@16 161 static void unlink(const node_ptr & node);
Chris@16 162
Chris@16 163 //! @copydoc ::boost::intrusive::bstree_algorithms::unlink_leftmost_without_rebalance
Chris@16 164 static node_ptr unlink_leftmost_without_rebalance(const node_ptr & header);
Chris@16 165
Chris@16 166 //! @copydoc ::boost::intrusive::bstree_algorithms::unique(const const_node_ptr&)
Chris@16 167 static bool unique(const const_node_ptr & node);
Chris@16 168
Chris@16 169 //! @copydoc ::boost::intrusive::bstree_algorithms::size(const const_node_ptr&)
Chris@16 170 static std::size_t size(const const_node_ptr & header);
Chris@16 171
Chris@16 172 //! @copydoc ::boost::intrusive::bstree_algorithms::next_node(const node_ptr&)
Chris@16 173 static node_ptr next_node(const node_ptr & node);
Chris@16 174
Chris@16 175 //! @copydoc ::boost::intrusive::bstree_algorithms::prev_node(const node_ptr&)
Chris@16 176 static node_ptr prev_node(const node_ptr & node);
Chris@16 177
Chris@16 178 //! @copydoc ::boost::intrusive::bstree_algorithms::init(const node_ptr&)
Chris@16 179 static void init(const node_ptr & node);
Chris@16 180
Chris@16 181 //! @copydoc ::boost::intrusive::bstree_algorithms::init_header(const node_ptr&)
Chris@16 182 static void init_header(const node_ptr & header);
Chris@16 183
Chris@16 184 #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
Chris@16 185
Chris@16 186 //! @copydoc ::boost::intrusive::bstree_algorithms::erase(const node_ptr&,const node_ptr&)
Chris@16 187 //! Additional notes: the previous node of z is splayed. The "splay" parameter which indicated if splaying
Chris@16 188 //! should be performed, it's deprecated and will disappear in future versions.
Chris@16 189 static void erase(const node_ptr & header, const node_ptr & z, bool splay = true)
Chris@16 190 {
Chris@16 191 //posibility 1
Chris@16 192 if(splay && NodeTraits::get_left(z)){
Chris@16 193 splay_up(bstree_algo::prev_node(z), header);
Chris@16 194 }
Chris@16 195 /*
Chris@16 196 //possibility 2
Chris@16 197 if(splay && NodeTraits::get_left(z)){
Chris@16 198 node_ptr l = NodeTraits::get_left(z);
Chris@16 199 splay_up(l, header);
Chris@16 200 }*//*
Chris@16 201 if(splay && NodeTraits::get_left(z)){
Chris@16 202 node_ptr l = bstree_algo::prev_node(z);
Chris@16 203 splay_up_impl(l, z);
Chris@16 204 }*/
Chris@16 205 /*
Chris@16 206 //possibility 4
Chris@16 207 if(splay){
Chris@16 208 splay_up(z, header);
Chris@16 209 }*/
Chris@16 210
Chris@16 211 //if(splay)
Chris@16 212 //splay_up(z, header);
Chris@16 213 bstree_algo::erase(header, z);
Chris@16 214 }
Chris@16 215
Chris@16 216 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
Chris@16 217 //! @copydoc ::boost::intrusive::bstree_algorithms::clone(const const_node_ptr&,const node_ptr&,Cloner,Disposer)
Chris@16 218 template <class Cloner, class Disposer>
Chris@16 219 static void clone
Chris@16 220 (const const_node_ptr & source_header, const node_ptr & target_header, Cloner cloner, Disposer disposer);
Chris@16 221
Chris@16 222 //! @copydoc ::boost::intrusive::bstree_algorithms::clear_and_dispose(const node_ptr&,Disposer)
Chris@16 223 template<class Disposer>
Chris@16 224 static void clear_and_dispose(const node_ptr & header, Disposer disposer);
Chris@16 225
Chris@16 226 #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
Chris@16 227 //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
Chris@16 228 //! Additional notes: the first node of the range is splayed.
Chris@16 229 template<class KeyType, class KeyNodePtrCompare>
Chris@16 230 static std::size_t count
Chris@16 231 (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
Chris@16 232 {
Chris@16 233 std::pair<node_ptr, node_ptr> ret = equal_range(header, key, comp);
Chris@16 234 std::size_t n = 0;
Chris@16 235 while(ret.first != ret.second){
Chris@16 236 ++n;
Chris@16 237 ret.first = next_node(ret.first);
Chris@16 238 }
Chris@16 239 return n;
Chris@16 240 }
Chris@16 241
Chris@16 242 //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
Chris@16 243 //! Additional note: no splaying is performed
Chris@16 244 template<class KeyType, class KeyNodePtrCompare>
Chris@16 245 static std::size_t count
Chris@16 246 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
Chris@16 247 { return bstree_algo::count(header, key, comp); }
Chris@16 248
Chris@16 249 //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
Chris@16 250 //! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying
Chris@16 251 //! should be performed, it's deprecated and will disappear in future versions.
Chris@16 252 template<class KeyType, class KeyNodePtrCompare>
Chris@16 253 static node_ptr lower_bound
Chris@16 254 (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true)
Chris@16 255 {
Chris@16 256 //splay_down(detail::uncast(header), key, comp);
Chris@16 257 node_ptr y = bstree_algo::lower_bound(header, key, comp);
Chris@16 258 if(splay) splay_up(y, detail::uncast(header));
Chris@16 259 return y;
Chris@16 260 }
Chris@16 261
Chris@16 262 //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
Chris@16 263 //! Additional note: no splaying is performed
Chris@16 264 template<class KeyType, class KeyNodePtrCompare>
Chris@16 265 static node_ptr lower_bound
Chris@16 266 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
Chris@16 267 { return bstree_algo::lower_bound(header, key, comp); }
Chris@16 268
Chris@16 269 //! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
Chris@16 270 //! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying
Chris@16 271 //! should be performed, it's deprecated and will disappear in future versions.
Chris@16 272 template<class KeyType, class KeyNodePtrCompare>
Chris@16 273 static node_ptr upper_bound
Chris@16 274 (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true)
Chris@16 275 {
Chris@16 276 //splay_down(detail::uncast(header), key, comp);
Chris@16 277 node_ptr y = bstree_algo::upper_bound(header, key, comp);
Chris@16 278 if(splay) splay_up(y, detail::uncast(header));
Chris@16 279 return y;
Chris@16 280 }
Chris@16 281
Chris@16 282 //! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
Chris@16 283 //! Additional note: no splaying is performed
Chris@16 284 template<class KeyType, class KeyNodePtrCompare>
Chris@16 285 static node_ptr upper_bound
Chris@16 286 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
Chris@16 287 { return bstree_algo::upper_bound(header, key, comp); }
Chris@16 288
Chris@16 289 //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare)
Chris@16 290 //! Additional notes: the found node of the lower bound is splayed. The "splay" parameter which indicated if splaying
Chris@16 291 //! should be performed, it's deprecated and will disappear in future versions.
Chris@16 292 template<class KeyType, class KeyNodePtrCompare>
Chris@16 293 static node_ptr find
Chris@16 294 (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true)
Chris@16 295 {
Chris@16 296 if(splay) splay_down(detail::uncast(header), key, comp);
Chris@16 297 node_ptr end = detail::uncast(header);
Chris@16 298 node_ptr y = bstree_algo::lower_bound(header, key, comp);
Chris@16 299 node_ptr r = (y == end || comp(key, y)) ? end : y;
Chris@16 300 return r;
Chris@16 301 }
Chris@16 302
Chris@16 303 //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare)
Chris@16 304 //! Additional note: no splaying is performed
Chris@16 305 template<class KeyType, class KeyNodePtrCompare>
Chris@16 306 static node_ptr find
Chris@16 307 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
Chris@16 308 { return bstree_algo::find(header, key, comp); }
Chris@16 309
Chris@16 310 //! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
Chris@16 311 //! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying
Chris@16 312 //! should be performed, it's deprecated and will disappear in future versions.
Chris@16 313 template<class KeyType, class KeyNodePtrCompare>
Chris@16 314 static std::pair<node_ptr, node_ptr> equal_range
Chris@16 315 (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true)
Chris@16 316 {
Chris@16 317 //splay_down(detail::uncast(header), key, comp);
Chris@16 318 std::pair<node_ptr, node_ptr> ret = bstree_algo::equal_range(header, key, comp);
Chris@16 319 if(splay) splay_up(ret.first, detail::uncast(header));
Chris@16 320 return ret;
Chris@16 321 }
Chris@16 322
Chris@16 323 //! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
Chris@16 324 //! Additional note: no splaying is performed
Chris@16 325 template<class KeyType, class KeyNodePtrCompare>
Chris@16 326 static std::pair<node_ptr, node_ptr> equal_range
Chris@16 327 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
Chris@16 328 { return bstree_algo::equal_range(header, key, comp); }
Chris@16 329
Chris@16 330 //! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool)
Chris@16 331 //! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying
Chris@16 332 //! should be performed, it's deprecated and will disappear in future versions.
Chris@16 333 template<class KeyType, class KeyNodePtrCompare>
Chris@16 334 static std::pair<node_ptr, node_ptr> bounded_range
Chris@16 335 (const node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp
Chris@16 336 , bool left_closed, bool right_closed, bool splay = true)
Chris@16 337 {
Chris@16 338 std::pair<node_ptr, node_ptr> ret =
Chris@16 339 bstree_algo::bounded_range(header, lower_key, upper_key, comp, left_closed, right_closed);
Chris@16 340 if(splay) splay_up(ret.first, detail::uncast(header));
Chris@16 341 return ret;
Chris@16 342 }
Chris@16 343
Chris@16 344 //! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool)
Chris@16 345 //! Additional note: no splaying is performed
Chris@16 346 template<class KeyType, class KeyNodePtrCompare>
Chris@16 347 static std::pair<node_ptr, node_ptr> bounded_range
Chris@16 348 (const const_node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp
Chris@16 349 , bool left_closed, bool right_closed)
Chris@16 350 { return bstree_algo::bounded_range(header, lower_key, upper_key, comp, left_closed, right_closed); }
Chris@16 351
Chris@16 352 //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_upper_bound(const node_ptr&,const node_ptr&,NodePtrCompare)
Chris@16 353 //! Additional note: the inserted node is splayed
Chris@16 354 template<class NodePtrCompare>
Chris@16 355 static node_ptr insert_equal_upper_bound
Chris@16 356 (const node_ptr & header, const node_ptr & new_node, NodePtrCompare comp)
Chris@16 357 {
Chris@16 358 splay_down(header, new_node, comp);
Chris@16 359 return bstree_algo::insert_equal_upper_bound(header, new_node, comp);
Chris@16 360 }
Chris@16 361
Chris@16 362 //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_lower_bound(const node_ptr&,const node_ptr&,NodePtrCompare)
Chris@16 363 //! Additional note: the inserted node is splayed
Chris@16 364 template<class NodePtrCompare>
Chris@16 365 static node_ptr insert_equal_lower_bound
Chris@16 366 (const node_ptr & header, const node_ptr & new_node, NodePtrCompare comp)
Chris@16 367 {
Chris@16 368 splay_down(header, new_node, comp);
Chris@16 369 return bstree_algo::insert_equal_lower_bound(header, new_node, comp);
Chris@16 370 }
Chris@16 371
Chris@16 372 //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal(const node_ptr&,const node_ptr&,const node_ptr&,NodePtrCompare)
Chris@16 373 //! Additional note: the inserted node is splayed
Chris@16 374 template<class NodePtrCompare>
Chris@16 375 static node_ptr insert_equal
Chris@16 376 (const node_ptr & header, const node_ptr & hint, const node_ptr & new_node, NodePtrCompare comp)
Chris@16 377 {
Chris@16 378 splay_down(header, new_node, comp);
Chris@16 379 return bstree_algo::insert_equal(header, hint, new_node, comp);
Chris@16 380 }
Chris@16 381
Chris@16 382 //! @copydoc ::boost::intrusive::bstree_algorithms::insert_before(const node_ptr&,const node_ptr&,const node_ptr&)
Chris@16 383 //! Additional note: the inserted node is splayed
Chris@16 384 static node_ptr insert_before
Chris@16 385 (const node_ptr & header, const node_ptr & pos, const node_ptr & new_node)
Chris@16 386 {
Chris@16 387 bstree_algo::insert_before(header, pos, new_node);
Chris@16 388 splay_up(new_node, header);
Chris@16 389 return new_node;
Chris@16 390 }
Chris@16 391
Chris@16 392 //! @copydoc ::boost::intrusive::bstree_algorithms::push_back(const node_ptr&,const node_ptr&)
Chris@16 393 //! Additional note: the inserted node is splayed
Chris@16 394 static void push_back(const node_ptr & header, const node_ptr & new_node)
Chris@16 395 {
Chris@16 396 bstree_algo::push_back(header, new_node);
Chris@16 397 splay_up(new_node, header);
Chris@16 398 }
Chris@16 399
Chris@16 400 //! @copydoc ::boost::intrusive::bstree_algorithms::push_front(const node_ptr&,const node_ptr&)
Chris@16 401 //! Additional note: the inserted node is splayed
Chris@16 402 static void push_front(const node_ptr & header, const node_ptr & new_node)
Chris@16 403 {
Chris@16 404 bstree_algo::push_front(header, new_node);
Chris@16 405 splay_up(new_node, header);
Chris@16 406 }
Chris@16 407
Chris@16 408 //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const const_node_ptr&,const KeyType&,KeyNodePtrCompare,insert_commit_data&)
Chris@16 409 //! Additional note: nodes with the given key are splayed
Chris@16 410 template<class KeyType, class KeyNodePtrCompare>
Chris@16 411 static std::pair<node_ptr, bool> insert_unique_check
Chris@16 412 (const node_ptr & header, const KeyType &key
Chris@16 413 ,KeyNodePtrCompare comp, insert_commit_data &commit_data)
Chris@16 414 {
Chris@16 415 splay_down(header, key, comp);
Chris@16 416 return bstree_algo::insert_unique_check(header, key, comp, commit_data);
Chris@16 417 }
Chris@16 418
Chris@16 419 //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const const_node_ptr&,const node_ptr&,const KeyType&,KeyNodePtrCompare,insert_commit_data&)
Chris@16 420 //! Additional note: nodes with the given key are splayed
Chris@16 421 template<class KeyType, class KeyNodePtrCompare>
Chris@16 422 static std::pair<node_ptr, bool> insert_unique_check
Chris@16 423 (const node_ptr & header, const node_ptr &hint, const KeyType &key
Chris@16 424 ,KeyNodePtrCompare comp, insert_commit_data &commit_data)
Chris@16 425 {
Chris@16 426 splay_down(header, key, comp);
Chris@16 427 return bstree_algo::insert_unique_check(header, hint, key, comp, commit_data);
Chris@16 428 }
Chris@16 429
Chris@16 430 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
Chris@16 431 //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_commit(const node_ptr&,const node_ptr&,const insert_commit_data&)
Chris@16 432 static void insert_unique_commit
Chris@16 433 (const node_ptr & header, const node_ptr & new_value, const insert_commit_data &commit_data);
Chris@16 434
Chris@16 435 //! @copydoc ::boost::intrusive::bstree_algorithms::is_header
Chris@16 436 static bool is_header(const const_node_ptr & p);
Chris@16 437
Chris@16 438 //! @copydoc ::boost::intrusive::bstree_algorithms::rebalance
Chris@16 439 static void rebalance(const node_ptr & header);
Chris@16 440
Chris@16 441 //! @copydoc ::boost::intrusive::bstree_algorithms::rebalance_subtree
Chris@16 442 static node_ptr rebalance_subtree(const node_ptr & old_root);
Chris@16 443
Chris@16 444 #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
Chris@16 445
Chris@16 446 // bottom-up splay, use data_ as parent for n | complexity : logarithmic | exception : nothrow
Chris@16 447 static void splay_up(const node_ptr & node, const node_ptr & header)
Chris@16 448 {
Chris@16 449 // If (node == header) do a splay for the right most node instead
Chris@16 450 // this is to boost performance of equal_range/count on equivalent containers in the case
Chris@16 451 // where there are many equal elements at the end
Chris@16 452 node_ptr n((node == header) ? NodeTraits::get_right(header) : node);
Chris@16 453 node_ptr t(header);
Chris@16 454
Chris@16 455 if( n == t ) return;
Chris@16 456
Chris@16 457 for( ;; ){
Chris@16 458 node_ptr p(NodeTraits::get_parent(n));
Chris@16 459 node_ptr g(NodeTraits::get_parent(p));
Chris@16 460
Chris@16 461 if( p == t ) break;
Chris@16 462
Chris@16 463 if( g == t ){
Chris@16 464 // zig
Chris@16 465 rotate(n);
Chris@16 466 }
Chris@16 467 else if ((NodeTraits::get_left(p) == n && NodeTraits::get_left(g) == p) ||
Chris@16 468 (NodeTraits::get_right(p) == n && NodeTraits::get_right(g) == p) ){
Chris@16 469 // zig-zig
Chris@16 470 rotate(p);
Chris@16 471 rotate(n);
Chris@16 472 }
Chris@16 473 else{
Chris@16 474 // zig-zag
Chris@16 475 rotate(n);
Chris@16 476 rotate(n);
Chris@16 477 }
Chris@16 478 }
Chris@16 479 }
Chris@16 480
Chris@16 481 // top-down splay | complexity : logarithmic | exception : strong, note A
Chris@16 482 template<class KeyType, class KeyNodePtrCompare>
Chris@16 483 static node_ptr splay_down(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
Chris@16 484 {
Chris@16 485 if(!NodeTraits::get_parent(header))
Chris@16 486 return header;
Chris@16 487 //Most splay tree implementations use a dummy/null node to implement.
Chris@16 488 //this function. This has some problems for a generic library like Intrusive:
Chris@16 489 //
Chris@16 490 // * The node might not have a default constructor.
Chris@16 491 // * The default constructor could throw.
Chris@16 492 //
Chris@16 493 //We already have a header node. Leftmost and rightmost nodes of the tree
Chris@16 494 //are not changed when splaying (because the invariants of the tree don't
Chris@16 495 //change) We can back up them, use the header as the null node and
Chris@16 496 //reassign old values after the function has been completed.
Chris@16 497 node_ptr t = NodeTraits::get_parent(header);
Chris@16 498 //Check if tree has a single node
Chris@16 499 if(!NodeTraits::get_left(t) && !NodeTraits::get_right(t))
Chris@16 500 return t;
Chris@16 501 //Backup leftmost/rightmost
Chris@16 502 node_ptr leftmost (NodeTraits::get_left(header));
Chris@16 503 node_ptr rightmost(NodeTraits::get_right(header));
Chris@16 504 {
Chris@16 505 //Anti-exception rollback, recovers the original header node if an exception is thrown.
Chris@16 506 detail::splaydown_rollback<NodeTraits> rollback(&t, header, leftmost, rightmost);
Chris@16 507 node_ptr null_node = header;
Chris@16 508 node_ptr l = null_node;
Chris@16 509 node_ptr r = null_node;
Chris@16 510
Chris@16 511 for( ;; ){
Chris@16 512 if(comp(key, t)){
Chris@16 513 if(NodeTraits::get_left(t) == node_ptr() )
Chris@16 514 break;
Chris@16 515 if(comp(key, NodeTraits::get_left(t))){
Chris@16 516 t = bstree_algo::rotate_right(t);
Chris@16 517
Chris@16 518 if(NodeTraits::get_left(t) == node_ptr())
Chris@16 519 break;
Chris@16 520 link_right(t, r);
Chris@16 521 }
Chris@16 522 else if(comp(NodeTraits::get_left(t), key)){
Chris@16 523 link_right(t, r);
Chris@16 524
Chris@16 525 if(NodeTraits::get_right(t) == node_ptr() )
Chris@16 526 break;
Chris@16 527 link_left(t, l);
Chris@16 528 }
Chris@16 529 else{
Chris@16 530 link_right(t, r);
Chris@16 531 }
Chris@16 532 }
Chris@16 533 else if(comp(t, key)){
Chris@16 534 if(NodeTraits::get_right(t) == node_ptr() )
Chris@16 535 break;
Chris@16 536
Chris@16 537 if(comp(NodeTraits::get_right(t), key)){
Chris@16 538 t = bstree_algo::rotate_left( t );
Chris@16 539
Chris@16 540 if(NodeTraits::get_right(t) == node_ptr() )
Chris@16 541 break;
Chris@16 542 link_left(t, l);
Chris@16 543 }
Chris@16 544 else if(comp(key, NodeTraits::get_right(t))){
Chris@16 545 link_left(t, l);
Chris@16 546
Chris@16 547 if(NodeTraits::get_left(t) == node_ptr())
Chris@16 548 break;
Chris@16 549
Chris@16 550 link_right(t, r);
Chris@16 551 }
Chris@16 552 else{
Chris@16 553 link_left(t, l);
Chris@16 554 }
Chris@16 555 }
Chris@16 556 else{
Chris@16 557 break;
Chris@16 558 }
Chris@16 559 }
Chris@16 560
Chris@16 561 assemble(t, l, r, null_node);
Chris@16 562 rollback.release();
Chris@16 563 }
Chris@16 564
Chris@16 565 //Now recover the original header except for the
Chris@16 566 //splayed root node.
Chris@16 567 //t is the current root
Chris@16 568 NodeTraits::set_parent(header, t);
Chris@16 569 NodeTraits::set_parent(t, header);
Chris@16 570 //Recover leftmost/rightmost pointers
Chris@16 571 NodeTraits::set_left (header, leftmost);
Chris@16 572 NodeTraits::set_right(header, rightmost);
Chris@16 573 return t;
Chris@16 574 }
Chris@16 575
Chris@16 576 private:
Chris@16 577
Chris@16 578 /// @cond
Chris@16 579
Chris@16 580 // assemble the three sub-trees into new tree pointed to by t | complexity : constant | exception : nothrow
Chris@16 581 static void assemble(const node_ptr &t, const node_ptr & l, const node_ptr & r, const const_node_ptr & null_node )
Chris@16 582 {
Chris@16 583 NodeTraits::set_right(l, NodeTraits::get_left(t));
Chris@16 584 NodeTraits::set_left(r, NodeTraits::get_right(t));
Chris@16 585
Chris@16 586 if(NodeTraits::get_right(l) != node_ptr()){
Chris@16 587 NodeTraits::set_parent(NodeTraits::get_right(l), l);
Chris@16 588 }
Chris@16 589
Chris@16 590 if(NodeTraits::get_left(r) != node_ptr()){
Chris@16 591 NodeTraits::set_parent(NodeTraits::get_left(r), r);
Chris@16 592 }
Chris@16 593
Chris@16 594 NodeTraits::set_left (t, NodeTraits::get_right(null_node));
Chris@16 595 NodeTraits::set_right(t, NodeTraits::get_left(null_node));
Chris@16 596
Chris@16 597 if( NodeTraits::get_left(t) != node_ptr() ){
Chris@16 598 NodeTraits::set_parent(NodeTraits::get_left(t), t);
Chris@16 599 }
Chris@16 600
Chris@16 601 if( NodeTraits::get_right(t) ){
Chris@16 602 NodeTraits::set_parent(NodeTraits::get_right(t), t);
Chris@16 603 }
Chris@16 604 }
Chris@16 605
Chris@16 606 // break link to left child node and attach it to left tree pointed to by l | complexity : constant | exception : nothrow
Chris@16 607 static void link_left(node_ptr & t, node_ptr & l)
Chris@16 608 {
Chris@16 609 NodeTraits::set_right(l, t);
Chris@16 610 NodeTraits::set_parent(t, l);
Chris@16 611 l = t;
Chris@16 612 t = NodeTraits::get_right(t);
Chris@16 613 }
Chris@16 614
Chris@16 615 // break link to right child node and attach it to right tree pointed to by r | complexity : constant | exception : nothrow
Chris@16 616 static void link_right(node_ptr & t, node_ptr & r)
Chris@16 617 {
Chris@16 618 NodeTraits::set_left(r, t);
Chris@16 619 NodeTraits::set_parent(t, r);
Chris@16 620 r = t;
Chris@16 621 t = NodeTraits::get_left(t);
Chris@16 622 }
Chris@16 623
Chris@16 624 // rotate n with its parent | complexity : constant | exception : nothrow
Chris@16 625 static void rotate(const node_ptr & n)
Chris@16 626 {
Chris@16 627 node_ptr p = NodeTraits::get_parent(n);
Chris@16 628 node_ptr g = NodeTraits::get_parent(p);
Chris@16 629 //Test if g is header before breaking tree
Chris@16 630 //invariants that would make is_header invalid
Chris@16 631 bool g_is_header = bstree_algo::is_header(g);
Chris@16 632
Chris@16 633 if(NodeTraits::get_left(p) == n){
Chris@16 634 NodeTraits::set_left(p, NodeTraits::get_right(n));
Chris@16 635 if(NodeTraits::get_left(p) != node_ptr())
Chris@16 636 NodeTraits::set_parent(NodeTraits::get_left(p), p);
Chris@16 637 NodeTraits::set_right(n, p);
Chris@16 638 }
Chris@16 639 else{ // must be ( p->right == n )
Chris@16 640 NodeTraits::set_right(p, NodeTraits::get_left(n));
Chris@16 641 if(NodeTraits::get_right(p) != node_ptr())
Chris@16 642 NodeTraits::set_parent(NodeTraits::get_right(p), p);
Chris@16 643 NodeTraits::set_left(n, p);
Chris@16 644 }
Chris@16 645
Chris@16 646 NodeTraits::set_parent(p, n);
Chris@16 647 NodeTraits::set_parent(n, g);
Chris@16 648
Chris@16 649 if(g_is_header){
Chris@16 650 if(NodeTraits::get_parent(g) == p)
Chris@16 651 NodeTraits::set_parent(g, n);
Chris@16 652 else{//must be ( g->right == p )
Chris@16 653 BOOST_INTRUSIVE_INVARIANT_ASSERT(false);
Chris@16 654 NodeTraits::set_right(g, n);
Chris@16 655 }
Chris@16 656 }
Chris@16 657 else{
Chris@16 658 if(NodeTraits::get_left(g) == p)
Chris@16 659 NodeTraits::set_left(g, n);
Chris@16 660 else //must be ( g->right == p )
Chris@16 661 NodeTraits::set_right(g, n);
Chris@16 662 }
Chris@16 663 }
Chris@16 664
Chris@16 665 /// @endcond
Chris@16 666 };
Chris@16 667
Chris@16 668 /// @cond
Chris@16 669
Chris@16 670 template<class NodeTraits>
Chris@16 671 struct get_algo<SplayTreeAlgorithms, NodeTraits>
Chris@16 672 {
Chris@16 673 typedef splaytree_algorithms<NodeTraits> type;
Chris@16 674 };
Chris@16 675
Chris@16 676 /// @endcond
Chris@16 677
Chris@16 678 } //namespace intrusive
Chris@16 679 } //namespace boost
Chris@16 680
Chris@16 681 #include <boost/intrusive/detail/config_end.hpp>
Chris@16 682
Chris@16 683 #endif //BOOST_INTRUSIVE_SPLAYTREE_ALGORITHMS_HPP