8155648983ba4a04a9ede4fff7aaa21b6b172145
[platform/upstream/boost.git] / boost / intrusive / splaytree_algorithms.hpp
1 /////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga  2007-2012
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 code has been modified and (supposely) improved by Ion Gaztanaga.
16 // Here is the header of the file used as base code:
17 //
18 //  splay_tree.h -- implementation of a STL compatible splay tree.
19 //
20 //  Copyright (c) 2004 Ralf Mattethat
21 //
22 //  Permission to copy, use, modify, sell and distribute this software
23 //  is granted provided this copyright notice appears in all copies.
24 //  This software is provided "as is" without express or implied
25 //  warranty, and with no claim as to its suitability for any purpose.
26 //
27 //  Please send questions, comments, complaints, performance data, etc to
28 //  ralf.mattethat@teknologisk.dk
29 //
30 //  Requirements for element type
31 //  * must be copy-constructible
32 //  * destructor must not throw exception
33 //
34 //    Methods marked with note A only throws an exception if the evaluation of the
35 //    predicate throws an exception. If an exception is thrown the call has no
36 //    effect on the containers state
37 //
38 //    Methods marked with note B only throws an exception if the coppy constructor
39 //    or assignment operator of the predicate throws an exception. If an exception
40 //    is thrown the call has no effect on the containers state
41 //
42 //    iterators are only invalidated, if the element pointed to by the iterator
43 //    is deleted. The same goes for element references
44 //
45
46 #ifndef BOOST_INTRUSIVE_SPLAYTREE_ALGORITHMS_HPP
47 #define BOOST_INTRUSIVE_SPLAYTREE_ALGORITHMS_HPP
48
49 #include <boost/intrusive/detail/config_begin.hpp>
50 #include <boost/intrusive/detail/assert.hpp>
51 #include <boost/intrusive/intrusive_fwd.hpp>
52 #include <boost/intrusive/pointer_traits.hpp>
53 #include <cstddef>
54 #include <boost/intrusive/detail/utilities.hpp>
55 #include <boost/intrusive/detail/tree_algorithms.hpp>
56
57 namespace boost {
58 namespace intrusive {
59
60 /// @cond
61 namespace detail {
62
63 template<class NodeTraits>
64 struct splaydown_rollback
65 {
66    typedef typename NodeTraits::node_ptr node_ptr;
67    splaydown_rollback( const node_ptr *pcur_subtree, const node_ptr & header
68                      , const node_ptr & leftmost           , const node_ptr & rightmost)
69       : pcur_subtree_(pcur_subtree)  , header_(header)
70       , leftmost_(leftmost)   , rightmost_(rightmost)
71    {}
72
73    void release()
74    {  pcur_subtree_ = 0;  }
75
76    ~splaydown_rollback()
77    {
78       if(pcur_subtree_){
79          //Exception can only be thrown by comp, but
80          //tree invariants still hold. *pcur_subtree is the current root
81          //so link it to the header.
82          NodeTraits::set_parent(*pcur_subtree_, header_);
83          NodeTraits::set_parent(header_, *pcur_subtree_);
84          //Recover leftmost/rightmost pointers
85          NodeTraits::set_left (header_, leftmost_);
86          NodeTraits::set_right(header_, rightmost_);
87       }
88    }
89    const node_ptr *pcur_subtree_;
90    node_ptr header_, leftmost_, rightmost_;
91 };
92
93 }  //namespace detail {
94 /// @endcond
95
96 //!   A splay tree is an implementation of a binary search tree. The tree is
97 //!   self balancing using the splay algorithm as described in
98 //!
99 //!      "Self-Adjusting Binary Search Trees
100 //!      by Daniel Dominic Sleator and Robert Endre Tarjan
101 //!      AT&T Bell Laboratories, Murray Hill, NJ
102 //!      Journal of the ACM, Vol 32, no 3, July 1985, pp 652-686
103
104 //! splaytree_algorithms is configured with a NodeTraits class, which encapsulates the
105 //! information about the node to be manipulated. NodeTraits must support the
106 //! following interface:
107 //!
108 //! <b>Typedefs</b>:
109 //!
110 //! <tt>node</tt>: The type of the node that forms the circular list
111 //!
112 //! <tt>node_ptr</tt>: A pointer to a node
113 //!
114 //! <tt>const_node_ptr</tt>: A pointer to a const node
115 //!
116 //! <b>Static functions</b>:
117 //!
118 //! <tt>static node_ptr get_parent(const_node_ptr n);</tt>
119 //!
120 //! <tt>static void set_parent(node_ptr n, node_ptr parent);</tt>
121 //!
122 //! <tt>static node_ptr get_left(const_node_ptr n);</tt>
123 //!
124 //! <tt>static void set_left(node_ptr n, node_ptr left);</tt>
125 //!
126 //! <tt>static node_ptr get_right(const_node_ptr n);</tt>
127 //!
128 //! <tt>static void set_right(node_ptr n, node_ptr right);</tt>
129 template<class NodeTraits>
130 class splaytree_algorithms
131 {
132    /// @cond
133    private:
134    typedef detail::tree_algorithms<NodeTraits>  tree_algorithms;
135    /// @endcond
136
137    public:
138    typedef typename NodeTraits::node            node;
139    typedef NodeTraits                           node_traits;
140    typedef typename NodeTraits::node_ptr        node_ptr;
141    typedef typename NodeTraits::const_node_ptr  const_node_ptr;
142
143    //! This type is the information that will be
144    //! filled by insert_unique_check
145    typedef typename tree_algorithms::insert_commit_data insert_commit_data;
146
147    /// @cond
148    private:
149    static node_ptr uncast(const const_node_ptr & ptr)
150    {  return pointer_traits<node_ptr>::const_cast_from(ptr);  }
151    /// @endcond
152
153    public:
154    static node_ptr begin_node(const const_node_ptr & header)
155    {  return tree_algorithms::begin_node(header);   }
156
157    static node_ptr end_node(const const_node_ptr & header)
158    {  return tree_algorithms::end_node(header);   }
159
160    //! <b>Requires</b>: node is a node of the tree or an node initialized
161    //!   by init(...).
162    //!
163    //! <b>Effects</b>: Returns true if the node is initialized by init().
164    //!
165    //! <b>Complexity</b>: Constant time.
166    //!
167    //! <b>Throws</b>: Nothing.
168    static bool unique(const const_node_ptr & node)
169    {  return tree_algorithms::unique(node);  }
170
171    static void unlink(const node_ptr & node)
172    {  tree_algorithms::unlink(node);   }
173
174    //! <b>Requires</b>: node1 and node2 can't be header nodes
175    //!  of two trees.
176    //!
177    //! <b>Effects</b>: Swaps two nodes. After the function node1 will be inserted
178    //!   in the position node2 before the function. node2 will be inserted in the
179    //!   position node1 had before the function.
180    //!
181    //! <b>Complexity</b>: Logarithmic.
182    //!
183    //! <b>Throws</b>: Nothing.
184    //!
185    //! <b>Note</b>: This function will break container ordering invariants if
186    //!   node1 and node2 are not equivalent according to the ordering rules.
187    //!
188    //!Experimental function
189    static void swap_nodes(const node_ptr & node1, const node_ptr & node2)
190    {
191       if(node1 == node2)
192          return;
193
194       node_ptr header1(tree_algorithms::get_header(node1)), header2(tree_algorithms::get_header(node2));
195       swap_nodes(node1, header1, node2, header2);
196    }
197
198    //! <b>Requires</b>: node1 and node2 can't be header nodes
199    //!  of two trees with header header1 and header2.
200    //!
201    //! <b>Effects</b>: Swaps two nodes. After the function node1 will be inserted
202    //!   in the position node2 before the function. node2 will be inserted in the
203    //!   position node1 had before the function.
204    //!
205    //! <b>Complexity</b>: Constant.
206    //!
207    //! <b>Throws</b>: Nothing.
208    //!
209    //! <b>Note</b>: This function will break container ordering invariants if
210    //!   node1 and node2 are not equivalent according to the ordering rules.
211    //!
212    //!Experimental function
213    static void swap_nodes(const node_ptr & node1, const node_ptr & header1, const node_ptr & node2, const node_ptr & header2)
214    {  tree_algorithms::swap_nodes(node1, header1, node2, header2);   }
215
216    //! <b>Requires</b>: node_to_be_replaced must be inserted in a tree
217    //!   and new_node must not be inserted in a tree.
218    //!
219    //! <b>Effects</b>: Replaces node_to_be_replaced in its position in the
220    //!   tree with new_node. The tree does not need to be rebalanced
221    //!
222    //! <b>Complexity</b>: Logarithmic.
223    //!
224    //! <b>Throws</b>: Nothing.
225    //!
226    //! <b>Note</b>: This function will break container ordering invariants if
227    //!   new_node is not equivalent to node_to_be_replaced according to the
228    //!   ordering rules. This function is faster than erasing and inserting
229    //!   the node, since no rebalancing and comparison is needed.
230    //!
231    //!Experimental function
232    static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & new_node)
233    {
234       if(node_to_be_replaced == new_node)
235          return;
236       replace_node(node_to_be_replaced, tree_algorithms::get_header(node_to_be_replaced), new_node);
237    }
238
239    //! <b>Requires</b>: node_to_be_replaced must be inserted in a tree
240    //!   with header "header" and new_node must not be inserted in a tree.
241    //!
242    //! <b>Effects</b>: Replaces node_to_be_replaced in its position in the
243    //!   tree with new_node. The tree does not need to be rebalanced
244    //!
245    //! <b>Complexity</b>: Constant.
246    //!
247    //! <b>Throws</b>: Nothing.
248    //!
249    //! <b>Note</b>: This function will break container ordering invariants if
250    //!   new_node is not equivalent to node_to_be_replaced according to the
251    //!   ordering rules. This function is faster than erasing and inserting
252    //!   the node, since no rebalancing or comparison is needed.
253    //!
254    //!Experimental function
255    static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & header, const node_ptr & new_node)
256    {  tree_algorithms::replace_node(node_to_be_replaced, header, new_node);   }
257
258    //! <b>Requires</b>: p is a node from the tree except the header.
259    //!
260    //! <b>Effects</b>: Returns the next node of the tree.
261    //!
262    //! <b>Complexity</b>: Average constant time.
263    //!
264    //! <b>Throws</b>: Nothing.
265    static node_ptr next_node(const node_ptr & p)
266    {  return tree_algorithms::next_node(p); }
267
268    //! <b>Requires</b>: p is a node from the tree except the leftmost node.
269    //!
270    //! <b>Effects</b>: Returns the previous node of the tree.
271    //!
272    //! <b>Complexity</b>: Average constant time.
273    //!
274    //! <b>Throws</b>: Nothing.
275    static node_ptr prev_node(const node_ptr & p)
276    {  return tree_algorithms::prev_node(p); }
277
278    //! <b>Requires</b>: node must not be part of any tree.
279    //!
280    //! <b>Effects</b>: After the function unique(node) == true.
281    //!
282    //! <b>Complexity</b>: Constant.
283    //!
284    //! <b>Throws</b>: Nothing.
285    //!
286    //! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
287    static void init(const node_ptr & node)
288    {  tree_algorithms::init(node);  }
289
290    //! <b>Requires</b>: node must not be part of any tree.
291    //!
292    //! <b>Effects</b>: Initializes the header to represent an empty tree.
293    //!   unique(header) == true.
294    //!
295    //! <b>Complexity</b>: Constant.
296    //!
297    //! <b>Throws</b>: Nothing.
298    //!
299    //! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
300    static void init_header(const node_ptr & header)
301    {  tree_algorithms::init_header(header);  }
302
303    //! <b>Requires</b>: "disposer" must be an object function
304    //!   taking a node_ptr parameter and shouldn't throw.
305    //!
306    //! <b>Effects</b>: Empties the target tree calling
307    //!   <tt>void disposer::operator()(const node_ptr &)</tt> for every node of the tree
308    //!    except the header.
309    //!
310    //! <b>Complexity</b>: Linear to the number of element of the source tree plus the.
311    //!   number of elements of tree target tree when calling this function.
312    //!
313    //! <b>Throws</b>: If cloner functor throws. If this happens target nodes are disposed.
314    template<class Disposer>
315    static void clear_and_dispose(const node_ptr & header, Disposer disposer)
316    {  tree_algorithms::clear_and_dispose(header, disposer); }
317
318    //! <b>Requires</b>: node is a node of the tree but it's not the header.
319    //!
320    //! <b>Effects</b>: Returns the number of nodes of the subtree.
321    //!
322    //! <b>Complexity</b>: Linear time.
323    //!
324    //! <b>Throws</b>: Nothing.
325    static std::size_t count(const const_node_ptr & node)
326    {  return tree_algorithms::count(node);   }
327
328    //! <b>Requires</b>: header is the header node of the tree.
329    //!
330    //! <b>Effects</b>: Returns the number of nodes above the header.
331    //!
332    //! <b>Complexity</b>: Linear time.
333    //!
334    //! <b>Throws</b>: Nothing.
335    static std::size_t size(const const_node_ptr & header)
336    {  return tree_algorithms::size(header);   }
337
338    //! <b>Requires</b>: header1 and header2 must be the header nodes
339    //!  of two trees.
340    //!
341    //! <b>Effects</b>: Swaps two trees. After the function header1 will contain
342    //!   links to the second tree and header2 will have links to the first tree.
343    //!
344    //! <b>Complexity</b>: Constant.
345    //!
346    //! <b>Throws</b>: Nothing.
347    static void swap_tree(const node_ptr & header1, const node_ptr & header2)
348    {  return tree_algorithms::swap_tree(header1, header2);  }
349
350    //! <b>Requires</b>: "header" must be the header node of a tree.
351    //!   "commit_data" must have been obtained from a previous call to
352    //!   "insert_unique_check". No objects should have been inserted or erased
353    //!   from the set between the "insert_unique_check" that filled "commit_data"
354    //!   and the call to "insert_commit".
355    //!
356    //!
357    //! <b>Effects</b>: Inserts new_node in the set using the information obtained
358    //!   from the "commit_data" that a previous "insert_check" filled.
359    //!
360    //! <b>Complexity</b>: Constant time.
361    //!
362    //! <b>Throws</b>: Nothing.
363    //!
364    //! <b>Notes</b>: This function has only sense if a "insert_unique_check" has been
365    //!   previously executed to fill "commit_data". No value should be inserted or
366    //!   erased between the "insert_check" and "insert_commit" calls.
367    static void insert_unique_commit
368       (const node_ptr & header, const node_ptr & new_value, const insert_commit_data &commit_data)
369    {  tree_algorithms::insert_unique_commit(header, new_value, commit_data);  }
370
371    //! <b>Requires</b>: "header" must be the header node of a tree.
372    //!   KeyNodePtrCompare is a function object that induces a strict weak
373    //!   ordering compatible with the strict weak ordering used to create the
374    //!   the tree. NodePtrCompare compares KeyType with a node_ptr.
375    //!
376    //! <b>Effects</b>: Checks if there is an equivalent node to "key" in the
377    //!   tree according to "comp" and obtains the needed information to realize
378    //!   a constant-time node insertion if there is no equivalent node.
379    //!
380    //! <b>Returns</b>: If there is an equivalent value
381    //!   returns a pair containing a node_ptr to the already present node
382    //!   and false. If there is not equivalent key can be inserted returns true
383    //!   in the returned pair's boolean and fills "commit_data" that is meant to
384    //!   be used with the "insert_commit" function to achieve a constant-time
385    //!   insertion function.
386    //!
387    //! <b>Complexity</b>: Average complexity is at most logarithmic.
388    //!
389    //! <b>Throws</b>: If "comp" throws.
390    //!
391    //! <b>Notes</b>: This function is used to improve performance when constructing
392    //!   a node is expensive and the user does not want to have two equivalent nodes
393    //!   in the tree: if there is an equivalent value
394    //!   the constructed object must be discarded. Many times, the part of the
395    //!   node that is used to impose the order is much cheaper to construct
396    //!   than the node and this function offers the possibility to use that part
397    //!   to check if the insertion will be successful.
398    //!
399    //!   If the check is successful, the user can construct the node and use
400    //!   "insert_commit" to insert the node in constant-time. This gives a total
401    //!   logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)).
402    //!
403    //!   "commit_data" remains valid for a subsequent "insert_unique_commit" only
404    //!   if no more objects are inserted or erased from the set.
405    template<class KeyType, class KeyNodePtrCompare>
406    static std::pair<node_ptr, bool> insert_unique_check
407       (const node_ptr & header, const KeyType &key
408       ,KeyNodePtrCompare comp, insert_commit_data &commit_data)
409    {
410       splay_down(header, key, comp);
411       return tree_algorithms::insert_unique_check(header, key, comp, commit_data);
412    }
413
414    template<class KeyType, class KeyNodePtrCompare>
415    static std::pair<node_ptr, bool> insert_unique_check
416       (const node_ptr & header, const node_ptr &hint, const KeyType &key
417       ,KeyNodePtrCompare comp, insert_commit_data &commit_data)
418    {
419       splay_down(header, key, comp);
420       return tree_algorithms::insert_unique_check(header, hint, key, comp, commit_data);
421    }
422
423    static bool is_header(const const_node_ptr & p)
424    {  return tree_algorithms::is_header(p);  }
425
426    //! <b>Requires</b>: "header" must be the header node of a tree.
427    //!   KeyNodePtrCompare is a function object that induces a strict weak
428    //!   ordering compatible with the strict weak ordering used to create the
429    //!   the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
430    //!
431    //! <b>Effects</b>: Returns an node_ptr to the element that is equivalent to
432    //!   "key" according to "comp" or "header" if that element does not exist.
433    //!
434    //! <b>Complexity</b>: Logarithmic.
435    //!
436    //! <b>Throws</b>: If "comp" throws.
437    template<class KeyType, class KeyNodePtrCompare>
438    static node_ptr find
439       (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true)
440    {
441       if(splay)
442          splay_down(uncast(header), key, comp);
443       node_ptr end = uncast(header);
444       node_ptr y = lower_bound(header, key, comp, false);
445       node_ptr r = (y == end || comp(key, y)) ? end : y;
446       return r;
447    }
448
449    //! <b>Requires</b>: "header" must be the header node of a tree.
450    //!   KeyNodePtrCompare is a function object that induces a strict weak
451    //!   ordering compatible with the strict weak ordering used to create the
452    //!   the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
453    //!
454    //! <b>Effects</b>: Returns an a pair of node_ptr delimiting a range containing
455    //!   all elements that are equivalent to "key" according to "comp" or an
456    //!   empty range that indicates the position where those elements would be
457    //!   if they there are no equivalent elements.
458    //!
459    //! <b>Complexity</b>: Logarithmic.
460    //!
461    //! <b>Throws</b>: If "comp" throws.
462    template<class KeyType, class KeyNodePtrCompare>
463    static std::pair<node_ptr, node_ptr> equal_range
464       (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true)
465    {
466       //if(splay)
467          //splay_down(uncast(header), key, comp);
468       std::pair<node_ptr, node_ptr> ret =
469          tree_algorithms::equal_range(header, key, comp);
470
471       if(splay)
472          splay_up(ret.first, uncast(header));
473       return ret;
474    }
475
476    //! <b>Requires</b>: "header" must be the header node of a tree.
477    //!   KeyNodePtrCompare is a function object that induces a strict weak
478    //!   ordering compatible with the strict weak ordering used to create the
479    //!   the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
480    //!   'lower_key' must not be greater than 'upper_key' according to 'comp'. If
481    //!   'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false.
482    //!
483    //! <b>Effects</b>: Returns an a pair with the following criteria:
484    //!
485    //!   first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise
486    //!
487    //!   second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise
488    //!
489    //! <b>Complexity</b>: Logarithmic.
490    //!
491    //! <b>Throws</b>: If "comp" throws.
492    //!
493    //! <b>Note</b>: This function can be more efficient than calling upper_bound
494    //!   and lower_bound for lower_key and upper_key.
495    template<class KeyType, class KeyNodePtrCompare>
496    static std::pair<node_ptr, node_ptr> bounded_range
497       (const const_node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp
498       , bool left_closed, bool right_closed, bool splay = true)
499    {
500       std::pair<node_ptr, node_ptr> ret =
501          tree_algorithms::bounded_range(header, lower_key, upper_key, comp, left_closed, right_closed);
502
503       if(splay)
504          splay_up(ret.first, uncast(header));
505       return ret;
506    }
507
508    //! <b>Requires</b>: "header" must be the header node of a tree.
509    //!   KeyNodePtrCompare is a function object that induces a strict weak
510    //!   ordering compatible with the strict weak ordering used to create the
511    //!   the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
512    //!
513    //! <b>Effects</b>: Returns an node_ptr to the first element that is
514    //!   not less than "key" according to "comp" or "header" if that element does
515    //!   not exist.
516    //!
517    //! <b>Complexity</b>: Logarithmic.
518    //!
519    //! <b>Throws</b>: If "comp" throws.
520    template<class KeyType, class KeyNodePtrCompare>
521    static node_ptr lower_bound
522       (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true)
523    {
524       //if(splay)
525          //splay_down(uncast(header), key, comp);
526       node_ptr y = tree_algorithms::lower_bound(header, key, comp);
527       if(splay)
528          splay_up(y, uncast(header));
529       return y;
530    }
531
532    //! <b>Requires</b>: "header" must be the header node of a tree.
533    //!   KeyNodePtrCompare is a function object that induces a strict weak
534    //!   ordering compatible with the strict weak ordering used to create the
535    //!   the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
536    //!
537    //! <b>Effects</b>: Returns an node_ptr to the first element that is greater
538    //!   than "key" according to "comp" or "header" if that element does not exist.
539    //!
540    //! <b>Complexity</b>: Logarithmic.
541    //!
542    //! <b>Throws</b>: If "comp" throws.
543    template<class KeyType, class KeyNodePtrCompare>
544    static node_ptr upper_bound
545       (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true)
546    {
547       //if(splay)
548          //splay_down(uncast(header), key, comp);
549       node_ptr y = tree_algorithms::upper_bound(header, key, comp);
550       if(splay)
551          splay_up(y, uncast(header));
552       return y;
553    }
554
555    //! <b>Requires</b>: "header" must be the header node of a tree.
556    //!   NodePtrCompare is a function object that induces a strict weak
557    //!   ordering compatible with the strict weak ordering used to create the
558    //!   the tree. NodePtrCompare compares two node_ptrs. "hint" is node from
559    //!   the "header"'s tree.
560    //!
561    //! <b>Effects</b>: Inserts new_node into the tree, using "hint" as a hint to
562    //!   where it will be inserted. If "hint" is the upper_bound
563    //!   the insertion takes constant time (two comparisons in the worst case).
564    //!
565    //! <b>Complexity</b>: Logarithmic in general, but it is amortized
566    //!   constant time if new_node is inserted immediately before "hint".
567    //!
568    //! <b>Throws</b>: If "comp" throws.
569    template<class NodePtrCompare>
570    static node_ptr insert_equal
571       (const node_ptr & header, const node_ptr & hint, const node_ptr & new_node, NodePtrCompare comp)
572    {
573       splay_down(header, new_node, comp);
574       return tree_algorithms::insert_equal(header, hint, new_node, comp);
575    }
576
577
578    //! <b>Requires</b>: "header" must be the header node of a tree.
579    //!   "pos" must be a valid iterator or header (end) node.
580    //!   "pos" must be an iterator pointing to the successor to "new_node"
581    //!   once inserted according to the order of already inserted nodes. This function does not
582    //!   check "pos" and this precondition must be guaranteed by the caller.
583    //!
584    //! <b>Effects</b>: Inserts new_node into the tree before "pos".
585    //!
586    //! <b>Complexity</b>: Constant-time.
587    //!
588    //! <b>Throws</b>: Nothing.
589    //!
590    //! <b>Note</b>: If "pos" is not the successor of the newly inserted "new_node"
591    //! tree invariants might be broken.
592    static node_ptr insert_before
593       (const node_ptr & header, const node_ptr & pos, const node_ptr & new_node)
594    {
595       tree_algorithms::insert_before(header, pos, new_node);
596       splay_up(new_node, header);
597       return new_node;
598    }
599
600    //! <b>Requires</b>: "header" must be the header node of a tree.
601    //!   "new_node" must be, according to the used ordering no less than the
602    //!   greatest inserted key.
603    //!
604    //! <b>Effects</b>: Inserts new_node into the tree before "pos".
605    //!
606    //! <b>Complexity</b>: Constant-time.
607    //!
608    //! <b>Throws</b>: Nothing.
609    //!
610    //! <b>Note</b>: If "new_node" is less than the greatest inserted key
611    //! tree invariants are broken. This function is slightly faster than
612    //! using "insert_before".
613    static void push_back(const node_ptr & header, const node_ptr & new_node)
614    {
615       tree_algorithms::push_back(header, new_node);
616       splay_up(new_node, header);
617    }
618
619    //! <b>Requires</b>: "header" must be the header node of a tree.
620    //!   "new_node" must be, according to the used ordering, no greater than the
621    //!   lowest inserted key.
622    //!
623    //! <b>Effects</b>: Inserts new_node into the tree before "pos".
624    //!
625    //! <b>Complexity</b>: Constant-time.
626    //!
627    //! <b>Throws</b>: Nothing.
628    //!
629    //! <b>Note</b>: If "new_node" is greater than the lowest inserted key
630    //! tree invariants are broken. This function is slightly faster than
631    //! using "insert_before".
632    static void push_front(const node_ptr & header, const node_ptr & new_node)
633    {
634       tree_algorithms::push_front(header, new_node);
635       splay_up(new_node, header);
636    }
637
638    //! <b>Requires</b>: "header" must be the header node of a tree.
639    //!   NodePtrCompare is a function object that induces a strict weak
640    //!   ordering compatible with the strict weak ordering used to create the
641    //!   the tree. NodePtrCompare compares two node_ptrs.
642    //!
643    //! <b>Effects</b>: Inserts new_node into the tree before the upper bound
644    //!   according to "comp".
645    //!
646    //! <b>Complexity</b>: Average complexity for insert element is at
647    //!   most logarithmic.
648    //!
649    //! <b>Throws</b>: If "comp" throws.
650    template<class NodePtrCompare>
651    static node_ptr insert_equal_upper_bound
652       (const node_ptr & header, const node_ptr & new_node, NodePtrCompare comp)
653    {
654       splay_down(header, new_node, comp);
655       return tree_algorithms::insert_equal_upper_bound(header, new_node, comp);
656    }
657
658    //! <b>Requires</b>: "header" must be the header node of a tree.
659    //!   NodePtrCompare is a function object that induces a strict weak
660    //!   ordering compatible with the strict weak ordering used to create the
661    //!   the tree. NodePtrCompare compares two node_ptrs.
662    //!
663    //! <b>Effects</b>: Inserts new_node into the tree before the lower bound
664    //!   according to "comp".
665    //!
666    //! <b>Complexity</b>: Average complexity for insert element is at
667    //!   most logarithmic.
668    //!
669    //! <b>Throws</b>: If "comp" throws.
670    template<class NodePtrCompare>
671    static node_ptr insert_equal_lower_bound
672       (const node_ptr & header, const node_ptr & new_node, NodePtrCompare comp)
673    {
674       splay_down(header, new_node, comp);
675       return tree_algorithms::insert_equal_lower_bound(header, new_node, comp);
676    }
677
678    //! <b>Requires</b>: "cloner" must be a function
679    //!   object taking a node_ptr and returning a new cloned node of it. "disposer" must
680    //!   take a node_ptr and shouldn't throw.
681    //!
682    //! <b>Effects</b>: First empties target tree calling
683    //!   <tt>void disposer::operator()(const node_ptr &)</tt> for every node of the tree
684    //!    except the header.
685    //!
686    //!   Then, duplicates the entire tree pointed by "source_header" cloning each
687    //!   source node with <tt>node_ptr Cloner::operator()(const node_ptr &)</tt> to obtain
688    //!   the nodes of the target tree. If "cloner" throws, the cloned target nodes
689    //!   are disposed using <tt>void disposer(const node_ptr &)</tt>.
690    //!
691    //! <b>Complexity</b>: Linear to the number of element of the source tree plus the.
692    //!   number of elements of tree target tree when calling this function.
693    //!
694    //! <b>Throws</b>: If cloner functor throws. If this happens target nodes are disposed.
695    template <class Cloner, class Disposer>
696    static void clone
697       (const const_node_ptr & source_header, const node_ptr & target_header, Cloner cloner, Disposer disposer)
698    {  tree_algorithms::clone(source_header, target_header, cloner, disposer);   }
699
700    // delete node                        | complexity : constant        | exception : nothrow
701    static void erase(const node_ptr & header, const node_ptr & z, bool splay = true)
702    {
703 //      node_base* n = t->right;
704 //      if( t->left != node_ptr() ){
705 //         node_base* l = t->previous();
706 //         splay_up( l , t );
707 //         n = t->left;
708 //         n->right = t->right;
709 //         if( n->right != node_ptr() )
710 //            n->right->parent = n;
711 //      }
712 //
713 //      if( n != node_ptr() )
714 //         n->parent = t->parent;
715 //
716 //      if( t->parent->left == t )
717 //         t->parent->left = n;
718 //      else // must be ( t->parent->right == t )
719 //         t->parent->right = n;
720 //
721 //      if( data_->parent == t )
722 //         data_->parent = find_leftmost();
723          //posibility 1
724       if(splay && NodeTraits::get_left(z)){
725          splay_up(prev_node(z), header);
726       }
727       /*
728       //possibility 2
729       if(splay && NodeTraits::get_left(z) != node_ptr() ){
730          node_ptr l = NodeTraits::get_left(z);
731          splay_up(l, header);
732       }*//*
733       if(splay && NodeTraits::get_left(z) != node_ptr() ){
734          node_ptr l = prev_node(z);
735          splay_up_impl(l, z);
736       }*/
737       /*
738       //possibility 4
739       if(splay){
740          splay_up(z, header);
741       }*/
742
743       //if(splay)
744          //splay_up(z, header);
745       tree_algorithms::erase(header, z);
746    }
747
748    // bottom-up splay, use data_ as parent for n    | complexity : logarithmic    | exception : nothrow
749    static void splay_up(const node_ptr & node, const node_ptr & header)
750    {
751       // If (node == header) do a splay for the right most node instead
752       // this is to boost performance of equal_range/count on equivalent containers in the case
753       // where there are many equal elements at the end
754       node_ptr n((node == header) ? NodeTraits::get_right(header) : node);
755       node_ptr t(header);
756
757       if( n == t ) return;
758
759       for( ;; ){
760          node_ptr p(NodeTraits::get_parent(n));
761          node_ptr g(NodeTraits::get_parent(p));
762
763          if( p == t )   break;
764
765          if( g == t ){
766             // zig
767             rotate(n);
768          }
769          else if ((NodeTraits::get_left(p) == n && NodeTraits::get_left(g) == p)    ||
770                   (NodeTraits::get_right(p) == n && NodeTraits::get_right(g) == p)  ){
771             // zig-zig
772             rotate(p);
773             rotate(n);
774          }
775          else{
776             // zig-zag
777             rotate(n);
778             rotate(n);
779          }
780       }
781    }
782
783    // top-down splay | complexity : logarithmic    | exception : strong, note A
784    template<class KeyType, class KeyNodePtrCompare>
785    static node_ptr splay_down(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
786    {
787       if(!NodeTraits::get_parent(header))
788          return header;
789       //Most splay tree implementations use a dummy/null node to implement.
790       //this function. This has some problems for a generic library like Intrusive:
791       //
792       // * The node might not have a default constructor.
793       // * The default constructor could throw.
794       //
795       //We already have a header node. Leftmost and rightmost nodes of the tree
796       //are not changed when splaying (because the invariants of the tree don't
797       //change) We can back up them, use the header as the null node and
798       //reassign old values after the function has been completed.
799       node_ptr t = NodeTraits::get_parent(header);
800       //Check if tree has a single node
801       if(!NodeTraits::get_left(t) && !NodeTraits::get_right(t))
802          return t;
803       //Backup leftmost/rightmost
804       node_ptr leftmost (NodeTraits::get_left(header));
805       node_ptr rightmost(NodeTraits::get_right(header));
806       {
807          //Anti-exception rollback, recovers the original header node if an exception is thrown.
808          detail::splaydown_rollback<NodeTraits> rollback(&t, header, leftmost, rightmost);
809          node_ptr null_node = header;
810          node_ptr l = null_node;
811          node_ptr r = null_node;
812
813          for( ;; ){
814             if(comp(key, t)){
815                if(NodeTraits::get_left(t) == node_ptr() )
816                   break;
817                if(comp(key, NodeTraits::get_left(t))){
818                   t = tree_algorithms::rotate_right(t);
819
820                   if(NodeTraits::get_left(t) == node_ptr())
821                      break;
822                   link_right(t, r);
823                }
824                else if(comp(NodeTraits::get_left(t), key)){
825                   link_right(t, r);
826
827                   if(NodeTraits::get_right(t) == node_ptr() )
828                      break;
829                   link_left(t, l);
830                }
831                else{
832                   link_right(t, r);
833                }
834             }
835             else if(comp(t, key)){
836                if(NodeTraits::get_right(t) == node_ptr() )
837                   break;
838
839                if(comp(NodeTraits::get_right(t), key)){
840                      t = tree_algorithms::rotate_left( t );
841
842                      if(NodeTraits::get_right(t) == node_ptr() )
843                         break;
844                      link_left(t, l);
845                }
846                else if(comp(key, NodeTraits::get_right(t))){
847                   link_left(t, l);
848
849                   if(NodeTraits::get_left(t) == node_ptr())
850                      break;
851
852                   link_right(t, r);
853                }
854                else{
855                   link_left(t, l);
856                }
857             }
858             else{
859                break;
860             }
861          }
862
863          assemble(t, l, r, null_node);
864          rollback.release();
865       }
866
867       //Now recover the original header except for the
868       //splayed root node.
869       //t is the current root
870       NodeTraits::set_parent(header, t);
871       NodeTraits::set_parent(t, header);
872       //Recover leftmost/rightmost pointers
873       NodeTraits::set_left (header, leftmost);
874       NodeTraits::set_right(header, rightmost);
875       return t;
876    }
877
878    //! <b>Requires</b>: header must be the header of a tree.
879    //!
880    //! <b>Effects</b>: Rebalances the tree.
881    //!
882    //! <b>Throws</b>: Nothing.
883    //!
884    //! <b>Complexity</b>: Linear.
885    static void rebalance(const node_ptr & header)
886    {  tree_algorithms::rebalance(header); }
887
888    //! <b>Requires</b>: old_root is a node of a tree.
889    //!
890    //! <b>Effects</b>: Rebalances the subtree rooted at old_root.
891    //!
892    //! <b>Returns</b>: The new root of the subtree.
893    //!
894    //! <b>Throws</b>: Nothing.
895    //!
896    //! <b>Complexity</b>: Linear.
897    static node_ptr rebalance_subtree(const node_ptr & old_root)
898    {  return tree_algorithms::rebalance_subtree(old_root); }
899
900
901    //! <b>Requires</b>: "n" must be a node inserted in a tree.
902    //!
903    //! <b>Effects</b>: Returns a pointer to the header node of the tree.
904    //!
905    //! <b>Complexity</b>: Logarithmic.
906    //!
907    //! <b>Throws</b>: Nothing.
908    static node_ptr get_header(const node_ptr & n)
909    {  return tree_algorithms::get_header(n);   }
910
911    private:
912
913    /// @cond
914
915    // assemble the three sub-trees into new tree pointed to by t    | complexity : constant        | exception : nothrow
916    static void assemble(const node_ptr &t, const node_ptr & l, const node_ptr & r, const const_node_ptr & null_node )
917    {
918       NodeTraits::set_right(l, NodeTraits::get_left(t));
919       NodeTraits::set_left(r, NodeTraits::get_right(t));
920
921       if(NodeTraits::get_right(l) != node_ptr()){
922          NodeTraits::set_parent(NodeTraits::get_right(l), l);
923       }
924
925       if(NodeTraits::get_left(r) != node_ptr()){
926          NodeTraits::set_parent(NodeTraits::get_left(r), r);
927       }
928
929       NodeTraits::set_left (t, NodeTraits::get_right(null_node));
930       NodeTraits::set_right(t, NodeTraits::get_left(null_node));
931
932       if( NodeTraits::get_left(t) != node_ptr() ){
933          NodeTraits::set_parent(NodeTraits::get_left(t), t);
934       }
935
936       if( NodeTraits::get_right(t) ){
937          NodeTraits::set_parent(NodeTraits::get_right(t), t);
938       }
939    }
940
941    // break link to left child node and attach it to left tree pointed to by l   | complexity : constant | exception : nothrow
942    static void link_left(node_ptr & t, node_ptr & l)
943    {
944       NodeTraits::set_right(l, t);
945       NodeTraits::set_parent(t, l);
946       l = t;
947       t = NodeTraits::get_right(t);
948    }
949
950    // break link to right child node and attach it to right tree pointed to by r | complexity : constant | exception : nothrow
951    static void link_right(node_ptr & t, node_ptr & r)
952    {
953       NodeTraits::set_left(r, t);
954       NodeTraits::set_parent(t, r);
955       r = t;
956       t = NodeTraits::get_left(t);
957    }
958
959    // rotate n with its parent                     | complexity : constant    | exception : nothrow
960    static void rotate(const node_ptr & n)
961    {
962       node_ptr p = NodeTraits::get_parent(n);
963       node_ptr g = NodeTraits::get_parent(p);
964       //Test if g is header before breaking tree
965       //invariants that would make is_header invalid
966       bool g_is_header = is_header(g);
967
968       if(NodeTraits::get_left(p) == n){
969          NodeTraits::set_left(p, NodeTraits::get_right(n));
970          if(NodeTraits::get_left(p) != node_ptr())
971             NodeTraits::set_parent(NodeTraits::get_left(p), p);
972          NodeTraits::set_right(n, p);
973       }
974       else{ // must be ( p->right == n )
975          NodeTraits::set_right(p, NodeTraits::get_left(n));
976          if(NodeTraits::get_right(p) != node_ptr())
977             NodeTraits::set_parent(NodeTraits::get_right(p), p);
978          NodeTraits::set_left(n, p);
979       }
980
981       NodeTraits::set_parent(p, n);
982       NodeTraits::set_parent(n, g);
983
984       if(g_is_header){
985          if(NodeTraits::get_parent(g) == p)
986             NodeTraits::set_parent(g, n);
987          else{//must be ( g->right == p )
988             BOOST_INTRUSIVE_INVARIANT_ASSERT(false);
989             NodeTraits::set_right(g, n);
990          }
991       }
992       else{
993          if(NodeTraits::get_left(g) == p)
994             NodeTraits::set_left(g, n);
995          else  //must be ( g->right == p )
996             NodeTraits::set_right(g, n);
997       }
998    }
999
1000    /// @endcond
1001 };
1002
1003 } //namespace intrusive
1004 } //namespace boost
1005
1006 #include <boost/intrusive/detail/config_end.hpp>
1007
1008 #endif //BOOST_INTRUSIVE_SPLAYTREE_ALGORITHMS_HPP