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