fix doc example typo
[boost.git] / boost / intrusive / rbtree_algorithms.hpp
blob37140a3b2b26d15d9651b57e932e6cd5f1b3b1a7
1 /////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Olaf Krzikalla 2004-2006.
4 // (C) Copyright Ion Gaztanaga 2006-2008.
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 // (See accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
9 //
10 // See http://www.boost.org/libs/intrusive for documentation.
12 /////////////////////////////////////////////////////////////////////////////
13 // The internal implementation of red-black trees is based on that of SGI STL
14 // stl_tree.h file:
16 // Copyright (c) 1996,1997
17 // Silicon Graphics Computer Systems, Inc.
19 // Permission to use, copy, modify, distribute and sell this software
20 // and its documentation for any purpose is hereby granted without fee,
21 // provided that the above copyright notice appear in all copies and
22 // that both that copyright notice and this permission notice appear
23 // in supporting documentation. Silicon Graphics makes no
24 // representations about the suitability of this software for any
25 // purpose. It is provided "as is" without express or implied warranty.
28 // Copyright (c) 1994
29 // Hewlett-Packard Company
31 // Permission to use, copy, modify, distribute and sell this software
32 // and its documentation for any purpose is hereby granted without fee,
33 // provided that the above copyright notice appear in all copies and
34 // that both that copyright notice and this permission notice appear
35 // in supporting documentation. Hewlett-Packard Company makes no
36 // representations about the suitability of this software for any
37 // purpose. It is provided "as is" without express or implied warranty.
39 // The tree destruction algorithm is based on Julienne Walker and The EC Team code:
40 //
41 // This code is in the public domain. Anyone may use it or change it in any way that
42 // they see fit. The author assumes no responsibility for damages incurred through
43 // use of the original code or any variations thereof.
44 //
45 // It is requested, but not required, that due credit is given to the original author
46 // and anyone who has modified the code through a header comment, such as this one.
48 #ifndef BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP
49 #define BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP
51 #include <boost/intrusive/detail/config_begin.hpp>
53 #include <cstddef>
54 #include <boost/intrusive/intrusive_fwd.hpp>
56 #include <boost/intrusive/detail/assert.hpp>
57 #include <boost/intrusive/detail/utilities.hpp>
58 #include <boost/intrusive/detail/tree_algorithms.hpp>
61 namespace boost {
62 namespace intrusive {
64 //! rbtree_algorithms provides basic algorithms to manipulate
65 //! nodes forming a red-black tree. The insertion and deletion algorithms are
66 //! based on those in Cormen, Leiserson, and Rivest, Introduction to Algorithms
67 //! (MIT Press, 1990), except that
68 //!
69 //! (1) the header node is maintained with links not only to the root
70 //! but also to the leftmost node of the tree, to enable constant time
71 //! begin(), and to the rightmost node of the tree, to enable linear time
72 //! performance when used with the generic set algorithms (set_union,
73 //! etc.);
74 //!
75 //! (2) when a node being deleted has two children its successor node is
76 //! relinked into its place, rather than copied, so that the only
77 //! pointers invalidated are those referring to the deleted node.
78 //!
79 //! rbtree_algorithms is configured with a NodeTraits class, which encapsulates the
80 //! information about the node to be manipulated. NodeTraits must support the
81 //! following interface:
82 //!
83 //! <b>Typedefs</b>:
84 //!
85 //! <tt>node</tt>: The type of the node that forms the circular list
86 //!
87 //! <tt>node_ptr</tt>: A pointer to a node
88 //!
89 //! <tt>const_node_ptr</tt>: A pointer to a const node
90 //!
91 //! <tt>color</tt>: The type that can store the color of a node
92 //!
93 //! <b>Static functions</b>:
94 //!
95 //! <tt>static node_ptr get_parent(const_node_ptr n);</tt>
96 //!
97 //! <tt>static void set_parent(node_ptr n, node_ptr parent);</tt>
98 //!
99 //! <tt>static node_ptr get_left(const_node_ptr n);</tt>
100 //!
101 //! <tt>static void set_left(node_ptr n, node_ptr left);</tt>
103 //! <tt>static node_ptr get_right(const_node_ptr n);</tt>
104 //!
105 //! <tt>static void set_right(node_ptr n, node_ptr right);</tt>
106 //!
107 //! <tt>static color get_color(const_node_ptr n);</tt>
108 //!
109 //! <tt>static void set_color(node_ptr n, color c);</tt>
110 //!
111 //! <tt>static color black();</tt>
112 //!
113 //! <tt>static color red();</tt>
114 template<class NodeTraits>
115 class rbtree_algorithms
117 public:
118 typedef NodeTraits node_traits;
119 typedef typename NodeTraits::node node;
120 typedef typename NodeTraits::node_ptr node_ptr;
121 typedef typename NodeTraits::const_node_ptr const_node_ptr;
122 typedef typename NodeTraits::color color;
124 /// @cond
125 private:
127 typedef detail::tree_algorithms<NodeTraits> tree_algorithms;
129 template<class F>
130 struct rbtree_node_cloner
131 : private detail::ebo_functor_holder<F>
133 typedef detail::ebo_functor_holder<F> base_t;
135 rbtree_node_cloner(F f)
136 : base_t(f)
139 node_ptr operator()(node_ptr p)
141 node_ptr n = base_t::get()(p);
142 NodeTraits::set_color(n, NodeTraits::get_color(p));
143 return n;
147 struct rbtree_erase_fixup
149 void operator()(node_ptr to_erase, node_ptr successor)
151 //Swap color of y and z
152 color tmp(NodeTraits::get_color(successor));
153 NodeTraits::set_color(successor, NodeTraits::get_color(to_erase));
154 NodeTraits::set_color(to_erase, tmp);
158 static node_ptr uncast(const_node_ptr ptr)
160 return node_ptr(const_cast<node*>(::boost::intrusive::detail::get_pointer(ptr)));
162 /// @endcond
164 public:
165 static node_ptr begin_node(const_node_ptr header)
166 { return tree_algorithms::begin_node(header); }
168 static node_ptr end_node(const_node_ptr header)
169 { return tree_algorithms::end_node(header); }
171 //! This type is the information that will be
172 //! filled by insert_unique_check
173 typedef typename tree_algorithms::insert_commit_data insert_commit_data;
175 //! <b>Requires</b>: header1 and header2 must be the header nodes
176 //! of two trees.
177 //!
178 //! <b>Effects</b>: Swaps two trees. After the function header1 will contain
179 //! links to the second tree and header2 will have links to the first tree.
180 //!
181 //! <b>Complexity</b>: Constant.
182 //!
183 //! <b>Throws</b>: Nothing.
184 static void swap_tree(node_ptr header1, node_ptr header2)
185 { return tree_algorithms::swap_tree(header1, header2); }
187 //! <b>Requires</b>: node1 and node2 can't be header nodes
188 //! of two trees.
189 //!
190 //! <b>Effects</b>: Swaps two nodes. After the function node1 will be inserted
191 //! in the position node2 before the function. node2 will be inserted in the
192 //! position node1 had before the function.
193 //!
194 //! <b>Complexity</b>: Logarithmic.
195 //!
196 //! <b>Throws</b>: Nothing.
197 //!
198 //! <b>Note</b>: This function will break container ordering invariants if
199 //! node1 and node2 are not equivalent according to the ordering rules.
201 //!Experimental function
202 static void swap_nodes(node_ptr node1, node_ptr node2)
204 if(node1 == node2)
205 return;
207 node_ptr header1(tree_algorithms::get_header(node1)), header2(tree_algorithms::get_header(node2));
208 swap_nodes(node1, header1, node2, header2);
211 //! <b>Requires</b>: node1 and node2 can't be header nodes
212 //! of two trees with header header1 and header2.
213 //!
214 //! <b>Effects</b>: Swaps two nodes. After the function node1 will be inserted
215 //! in the position node2 before the function. node2 will be inserted in the
216 //! position node1 had before the function.
217 //!
218 //! <b>Complexity</b>: Constant.
219 //!
220 //! <b>Throws</b>: Nothing.
221 //!
222 //! <b>Note</b>: This function will break container ordering invariants if
223 //! node1 and node2 are not equivalent according to the ordering rules.
225 //!Experimental function
226 static void swap_nodes(node_ptr node1, node_ptr header1, node_ptr node2, node_ptr header2)
228 if(node1 == node2) return;
230 tree_algorithms::swap_nodes(node1, header1, node2, header2);
231 //Swap color
232 color c = NodeTraits::get_color(node1);
233 NodeTraits::set_color(node1, NodeTraits::get_color(node2));
234 NodeTraits::set_color(node2, c);
237 //! <b>Requires</b>: node_to_be_replaced must be inserted in a tree
238 //! and new_node must not be inserted in a tree.
239 //!
240 //! <b>Effects</b>: Replaces node_to_be_replaced in its position in the
241 //! tree with new_node. The tree does not need to be rebalanced
242 //!
243 //! <b>Complexity</b>: Logarithmic.
244 //!
245 //! <b>Throws</b>: Nothing.
246 //!
247 //! <b>Note</b>: This function will break container ordering invariants if
248 //! new_node is not equivalent to node_to_be_replaced according to the
249 //! ordering rules. This function is faster than erasing and inserting
250 //! the node, since no rebalancing and comparison is needed.
252 //!Experimental function
253 static void replace_node(node_ptr node_to_be_replaced, node_ptr new_node)
255 if(node_to_be_replaced == new_node)
256 return;
257 replace_node(node_to_be_replaced, tree_algorithms::get_header(node_to_be_replaced), new_node);
260 //! <b>Requires</b>: node_to_be_replaced must be inserted in a tree
261 //! with header "header" and new_node must not be inserted in a tree.
262 //!
263 //! <b>Effects</b>: Replaces node_to_be_replaced in its position in the
264 //! tree with new_node. The tree does not need to be rebalanced
265 //!
266 //! <b>Complexity</b>: Constant.
267 //!
268 //! <b>Throws</b>: Nothing.
269 //!
270 //! <b>Note</b>: This function will break container ordering invariants if
271 //! new_node is not equivalent to node_to_be_replaced according to the
272 //! ordering rules. This function is faster than erasing and inserting
273 //! the node, since no rebalancing or comparison is needed.
275 //!Experimental function
276 static void replace_node(node_ptr node_to_be_replaced, node_ptr header, node_ptr new_node)
278 tree_algorithms::replace_node(node_to_be_replaced, header, new_node);
279 NodeTraits::set_color(new_node, NodeTraits::get_color(node_to_be_replaced));
282 //! <b>Requires</b>: node is a tree node but not the header.
283 //!
284 //! <b>Effects</b>: Unlinks the node and rebalances the tree.
285 //!
286 //! <b>Complexity</b>: Average complexity is constant time.
287 //!
288 //! <b>Throws</b>: Nothing.
289 static void unlink(node_ptr node)
291 node_ptr x = NodeTraits::get_parent(node);
292 if(x){
293 while(!is_header(x))
294 x = NodeTraits::get_parent(x);
295 erase(x, node);
299 //! <b>Requires</b>: header is the header of a tree.
300 //!
301 //! <b>Effects</b>: Unlinks the leftmost node from the tree, and
302 //! updates the header link to the new leftmost node.
303 //!
304 //! <b>Complexity</b>: Average complexity is constant time.
305 //!
306 //! <b>Throws</b>: Nothing.
307 //!
308 //! <b>Notes</b>: This function breaks the tree and the tree can
309 //! only be used for more unlink_leftmost_without_rebalance calls.
310 //! This function is normally used to achieve a step by step
311 //! controlled destruction of the tree.
312 static node_ptr unlink_leftmost_without_rebalance(node_ptr header)
313 { return tree_algorithms::unlink_leftmost_without_rebalance(header); }
315 //! <b>Requires</b>: node is a node of the tree or an node initialized
316 //! by init(...).
317 //!
318 //! <b>Effects</b>: Returns true if the node is initialized by init().
319 //!
320 //! <b>Complexity</b>: Constant time.
321 //!
322 //! <b>Throws</b>: Nothing.
323 static bool unique(const_node_ptr node)
324 { return tree_algorithms::unique(node); }
326 //! <b>Requires</b>: node is a node of the tree but it's not the header.
327 //!
328 //! <b>Effects</b>: Returns the number of nodes of the subtree.
329 //!
330 //! <b>Complexity</b>: Linear time.
331 //!
332 //! <b>Throws</b>: Nothing.
333 static std::size_t count(const_node_ptr node)
334 { return tree_algorithms::count(node); }
336 //! <b>Requires</b>: header is the header node of the tree.
337 //!
338 //! <b>Effects</b>: Returns the number of nodes above the header.
339 //!
340 //! <b>Complexity</b>: Linear time.
341 //!
342 //! <b>Throws</b>: Nothing.
343 static std::size_t size(const_node_ptr header)
344 { return tree_algorithms::size(header); }
346 //! <b>Requires</b>: p is a node from the tree except the header.
347 //!
348 //! <b>Effects</b>: Returns the next node of the tree.
349 //!
350 //! <b>Complexity</b>: Average constant time.
351 //!
352 //! <b>Throws</b>: Nothing.
353 static node_ptr next_node(node_ptr p)
354 { return tree_algorithms::next_node(p); }
356 //! <b>Requires</b>: p is a node from the tree except the leftmost node.
357 //!
358 //! <b>Effects</b>: Returns the previous node of the tree.
359 //!
360 //! <b>Complexity</b>: Average constant time.
361 //!
362 //! <b>Throws</b>: Nothing.
363 static node_ptr prev_node(node_ptr p)
364 { return tree_algorithms::prev_node(p); }
366 //! <b>Requires</b>: node must not be part of any tree.
368 //! <b>Effects</b>: After the function unique(node) == true.
369 //!
370 //! <b>Complexity</b>: Constant.
371 //!
372 //! <b>Throws</b>: Nothing.
374 //! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
375 static void init(node_ptr node)
376 { tree_algorithms::init(node); }
378 //! <b>Requires</b>: node must not be part of any tree.
380 //! <b>Effects</b>: Initializes the header to represent an empty tree.
381 //! unique(header) == true.
382 //!
383 //! <b>Complexity</b>: Constant.
384 //!
385 //! <b>Throws</b>: Nothing.
387 //! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
388 static void init_header(node_ptr header)
390 tree_algorithms::init_header(header);
391 NodeTraits::set_color(header, NodeTraits::red());
394 //! <b>Requires</b>: header must be the header of a tree, z a node
395 //! of that tree and z != header.
397 //! <b>Effects</b>: Erases node "z" from the tree with header "header".
398 //!
399 //! <b>Complexity</b>: Amortized constant time.
400 //!
401 //! <b>Throws</b>: Nothing.
402 static node_ptr erase(node_ptr header, node_ptr z)
404 typename tree_algorithms::data_for_rebalance info;
405 tree_algorithms::erase(header, z, rbtree_erase_fixup(), info);
406 node_ptr x = info.x;
407 node_ptr x_parent = info.x_parent;
409 //Rebalance rbtree
410 if(NodeTraits::get_color(z) != NodeTraits::red()){
411 rebalance_after_erasure(header, x, x_parent);
413 return z;
416 //! <b>Requires</b>: "cloner" must be a function
417 //! object taking a node_ptr and returning a new cloned node of it. "disposer" must
418 //! take a node_ptr and shouldn't throw.
420 //! <b>Effects</b>: First empties target tree calling
421 //! <tt>void disposer::operator()(node_ptr)</tt> for every node of the tree
422 //! except the header.
423 //!
424 //! Then, duplicates the entire tree pointed by "source_header" cloning each
425 //! source node with <tt>node_ptr Cloner::operator()(node_ptr)</tt> to obtain
426 //! the nodes of the target tree. If "cloner" throws, the cloned target nodes
427 //! are disposed using <tt>void disposer(node_ptr)</tt>.
428 //!
429 //! <b>Complexity</b>: Linear to the number of element of the source tree plus the.
430 //! number of elements of tree target tree when calling this function.
431 //!
432 //! <b>Throws</b>: If cloner functor throws. If this happens target nodes are disposed.
433 template <class Cloner, class Disposer>
434 static void clone
435 (const_node_ptr source_header, node_ptr target_header, Cloner cloner, Disposer disposer)
437 rbtree_node_cloner<Cloner> new_cloner(cloner);
438 tree_algorithms::clone(source_header, target_header, new_cloner, disposer);
441 //! <b>Requires</b>: "disposer" must be an object function
442 //! taking a node_ptr parameter and shouldn't throw.
444 //! <b>Effects</b>: Empties the target tree calling
445 //! <tt>void disposer::operator()(node_ptr)</tt> for every node of the tree
446 //! except the header.
447 //!
448 //! <b>Complexity</b>: Linear to the number of element of the source tree plus the.
449 //! number of elements of tree target tree when calling this function.
450 //!
451 //! <b>Throws</b>: If cloner functor throws. If this happens target nodes are disposed.
452 template<class Disposer>
453 static void clear_and_dispose(node_ptr header, Disposer disposer)
454 { tree_algorithms::clear_and_dispose(header, disposer); }
456 //! <b>Requires</b>: "header" must be the header node of a tree.
457 //! KeyNodePtrCompare is a function object that induces a strict weak
458 //! ordering compatible with the strict weak ordering used to create the
459 //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
461 //! <b>Effects</b>: Returns an node_ptr to the first element that is
462 //! not less than "key" according to "comp" or "header" if that element does
463 //! not exist.
465 //! <b>Complexity</b>: Logarithmic.
466 //!
467 //! <b>Throws</b>: If "comp" throws.
468 template<class KeyType, class KeyNodePtrCompare>
469 static node_ptr lower_bound
470 (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp)
471 { return tree_algorithms::lower_bound(header, key, comp); }
473 //! <b>Requires</b>: "header" must be the header node of a tree.
474 //! KeyNodePtrCompare is a function object that induces a strict weak
475 //! ordering compatible with the strict weak ordering used to create the
476 //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
478 //! <b>Effects</b>: Returns an node_ptr to the first element that is greater
479 //! than "key" according to "comp" or "header" if that element does not exist.
481 //! <b>Complexity</b>: Logarithmic.
482 //!
483 //! <b>Throws</b>: If "comp" throws.
484 template<class KeyType, class KeyNodePtrCompare>
485 static node_ptr upper_bound
486 (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp)
487 { return tree_algorithms::upper_bound(header, key, comp); }
489 //! <b>Requires</b>: "header" must be the header node of a tree.
490 //! KeyNodePtrCompare is a function object that induces a strict weak
491 //! ordering compatible with the strict weak ordering used to create the
492 //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
494 //! <b>Effects</b>: Returns an node_ptr to the element that is equivalent to
495 //! "key" according to "comp" or "header" if that element does not exist.
497 //! <b>Complexity</b>: Logarithmic.
498 //!
499 //! <b>Throws</b>: If "comp" throws.
500 template<class KeyType, class KeyNodePtrCompare>
501 static node_ptr find
502 (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp)
503 { return tree_algorithms::find(header, key, comp); }
505 //! <b>Requires</b>: "header" must be the header node of a tree.
506 //! KeyNodePtrCompare is a function object that induces a strict weak
507 //! ordering compatible with the strict weak ordering used to create the
508 //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
510 //! <b>Effects</b>: Returns an a pair of node_ptr delimiting a range containing
511 //! all elements that are equivalent to "key" according to "comp" or an
512 //! empty range that indicates the position where those elements would be
513 //! if they there are no equivalent elements.
515 //! <b>Complexity</b>: Logarithmic.
516 //!
517 //! <b>Throws</b>: If "comp" throws.
518 template<class KeyType, class KeyNodePtrCompare>
519 static std::pair<node_ptr, node_ptr> equal_range
520 (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp)
521 { return tree_algorithms::equal_range(header, key, comp); }
523 //! <b>Requires</b>: "h" must be the header node of a tree.
524 //! NodePtrCompare is a function object that induces a strict weak
525 //! ordering compatible with the strict weak ordering used to create the
526 //! the tree. NodePtrCompare compares two node_ptrs.
528 //! <b>Effects</b>: Inserts new_node into the tree before the upper bound
529 //! according to "comp".
530 //!
531 //! <b>Complexity</b>: Average complexity for insert element is at
532 //! most logarithmic.
533 //!
534 //! <b>Throws</b>: If "comp" throws.
535 template<class NodePtrCompare>
536 static node_ptr insert_equal_upper_bound
537 (node_ptr h, node_ptr new_node, NodePtrCompare comp)
539 tree_algorithms::insert_equal_upper_bound(h, new_node, comp);
540 rebalance_after_insertion(h, new_node);
541 return new_node;
544 //! <b>Requires</b>: "h" must be the header node of a tree.
545 //! NodePtrCompare is a function object that induces a strict weak
546 //! ordering compatible with the strict weak ordering used to create the
547 //! the tree. NodePtrCompare compares two node_ptrs.
549 //! <b>Effects</b>: Inserts new_node into the tree before the lower bound
550 //! according to "comp".
551 //!
552 //! <b>Complexity</b>: Average complexity for insert element is at
553 //! most logarithmic.
554 //!
555 //! <b>Throws</b>: If "comp" throws.
556 template<class NodePtrCompare>
557 static node_ptr insert_equal_lower_bound
558 (node_ptr h, node_ptr new_node, NodePtrCompare comp)
560 tree_algorithms::insert_equal_lower_bound(h, new_node, comp);
561 rebalance_after_insertion(h, new_node);
562 return new_node;
565 //! <b>Requires</b>: "header" must be the header node of a tree.
566 //! NodePtrCompare is a function object that induces a strict weak
567 //! ordering compatible with the strict weak ordering used to create the
568 //! the tree. NodePtrCompare compares two node_ptrs. "hint" is node from
569 //! the "header"'s tree.
570 //!
571 //! <b>Effects</b>: Inserts new_node into the tree, using "hint" as a hint to
572 //! where it will be inserted. If "hint" is the upper_bound
573 //! the insertion takes constant time (two comparisons in the worst case).
575 //! <b>Complexity</b>: Logarithmic in general, but it is amortized
576 //! constant time if new_node is inserted immediately before "hint".
577 //!
578 //! <b>Throws</b>: If "comp" throws.
579 template<class NodePtrCompare>
580 static node_ptr insert_equal
581 (node_ptr header, node_ptr hint, node_ptr new_node, NodePtrCompare comp)
583 tree_algorithms::insert_equal(header, hint, new_node, comp);
584 rebalance_after_insertion(header, new_node);
585 return new_node;
588 //! <b>Requires</b>: "header" must be the header node of a tree.
589 //! KeyNodePtrCompare is a function object that induces a strict weak
590 //! ordering compatible with the strict weak ordering used to create the
591 //! the tree. NodePtrCompare compares KeyType with a node_ptr.
592 //!
593 //! <b>Effects</b>: Checks if there is an equivalent node to "key" in the
594 //! tree according to "comp" and obtains the needed information to realize
595 //! a constant-time node insertion if there is no equivalent node.
597 //! <b>Returns</b>: If there is an equivalent value
598 //! returns a pair containing a node_ptr to the already present node
599 //! and false. If there is not equivalent key can be inserted returns true
600 //! in the returned pair's boolean and fills "commit_data" that is meant to
601 //! be used with the "insert_commit" function to achieve a constant-time
602 //! insertion function.
603 //!
604 //! <b>Complexity</b>: Average complexity is at most logarithmic.
606 //! <b>Throws</b>: If "comp" throws.
607 //!
608 //! <b>Notes</b>: This function is used to improve performance when constructing
609 //! a node is expensive and the user does not want to have two equivalent nodes
610 //! in the tree: if there is an equivalent value
611 //! the constructed object must be discarded. Many times, the part of the
612 //! node that is used to impose the order is much cheaper to construct
613 //! than the node and this function offers the possibility to use that part
614 //! to check if the insertion will be successful.
616 //! If the check is successful, the user can construct the node and use
617 //! "insert_commit" to insert the node in constant-time. This gives a total
618 //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)).
620 //! "commit_data" remains valid for a subsequent "insert_unique_commit" only
621 //! if no more objects are inserted or erased from the set.
622 template<class KeyType, class KeyNodePtrCompare>
623 static std::pair<node_ptr, bool> insert_unique_check
624 (const_node_ptr header, const KeyType &key
625 ,KeyNodePtrCompare comp, insert_commit_data &commit_data)
626 { return tree_algorithms::insert_unique_check(header, key, comp, commit_data); }
628 //! <b>Requires</b>: "header" must be the header node of a tree.
629 //! KeyNodePtrCompare is a function object that induces a strict weak
630 //! ordering compatible with the strict weak ordering used to create the
631 //! the tree. NodePtrCompare compares KeyType with a node_ptr.
632 //! "hint" is node from the "header"'s tree.
633 //!
634 //! <b>Effects</b>: Checks if there is an equivalent node to "key" in the
635 //! tree according to "comp" using "hint" as a hint to where it should be
636 //! inserted and obtains the needed information to realize
637 //! a constant-time node insertion if there is no equivalent node.
638 //! If "hint" is the upper_bound the function has constant time
639 //! complexity (two comparisons in the worst case).
641 //! <b>Returns</b>: If there is an equivalent value
642 //! returns a pair containing a node_ptr to the already present node
643 //! and false. If there is not equivalent key can be inserted returns true
644 //! in the returned pair's boolean and fills "commit_data" that is meant to
645 //! be used with the "insert_commit" function to achieve a constant-time
646 //! insertion function.
647 //!
648 //! <b>Complexity</b>: Average complexity is at most logarithmic, but it is
649 //! amortized constant time if new_node should be inserted immediately before "hint".
651 //! <b>Throws</b>: If "comp" throws.
652 //!
653 //! <b>Notes</b>: This function is used to improve performance when constructing
654 //! a node is expensive and the user does not want to have two equivalent nodes
655 //! in the tree: if there is an equivalent value
656 //! the constructed object must be discarded. Many times, the part of the
657 //! node that is used to impose the order is much cheaper to construct
658 //! than the node and this function offers the possibility to use that part
659 //! to check if the insertion will be successful.
661 //! If the check is successful, the user can construct the node and use
662 //! "insert_commit" to insert the node in constant-time. This gives a total
663 //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)).
665 //! "commit_data" remains valid for a subsequent "insert_unique_commit" only
666 //! if no more objects are inserted or erased from the set.
667 template<class KeyType, class KeyNodePtrCompare>
668 static std::pair<node_ptr, bool> insert_unique_check
669 (const_node_ptr header, node_ptr hint, const KeyType &key
670 ,KeyNodePtrCompare comp, insert_commit_data &commit_data)
671 { return tree_algorithms::insert_unique_check(header, hint, key, comp, commit_data); }
673 //! <b>Requires</b>: "header" must be the header node of a tree.
674 //! "commit_data" must have been obtained from a previous call to
675 //! "insert_unique_check". No objects should have been inserted or erased
676 //! from the set between the "insert_unique_check" that filled "commit_data"
677 //! and the call to "insert_commit".
678 //!
679 //!
680 //! <b>Effects</b>: Inserts new_node in the set using the information obtained
681 //! from the "commit_data" that a previous "insert_check" filled.
683 //! <b>Complexity</b>: Constant time.
685 //! <b>Throws</b>: Nothing.
686 //!
687 //! <b>Notes</b>: This function has only sense if a "insert_unique_check" has been
688 //! previously executed to fill "commit_data". No value should be inserted or
689 //! erased between the "insert_check" and "insert_commit" calls.
690 static void insert_unique_commit
691 (node_ptr header, node_ptr new_value, const insert_commit_data &commit_data)
693 tree_algorithms::insert_unique_commit(header, new_value, commit_data);
694 rebalance_after_insertion(header, new_value);
697 //! <b>Requires</b>: "n" must be a node inserted in a tree.
699 //! <b>Effects</b>: Returns a pointer to the header node of the tree.
701 //! <b>Complexity</b>: Logarithmic.
702 //!
703 //! <b>Throws</b>: Nothing.
704 static node_ptr get_header(node_ptr n)
705 { return tree_algorithms::get_header(n); }
707 /// @cond
708 private:
710 //! <b>Requires</b>: p is a node of a tree.
711 //!
712 //! <b>Effects</b>: Returns true if p is the header of the tree.
713 //!
714 //! <b>Complexity</b>: Constant.
715 //!
716 //! <b>Throws</b>: Nothing.
717 static bool is_header(const_node_ptr p)
719 return NodeTraits::get_color(p) == NodeTraits::red() &&
720 tree_algorithms::is_header(p);
721 //return NodeTraits::get_color(p) == NodeTraits::red() &&
722 // NodeTraits::get_parent(NodeTraits::get_parent(p)) == p;
725 static void rebalance_after_erasure(node_ptr header, node_ptr x, node_ptr x_parent)
727 while(x != NodeTraits::get_parent(header) && (x == 0 || NodeTraits::get_color(x) == NodeTraits::black())){
728 if(x == NodeTraits::get_left(x_parent)){
729 node_ptr w = NodeTraits::get_right(x_parent);
730 if(NodeTraits::get_color(w) == NodeTraits::red()){
731 NodeTraits::set_color(w, NodeTraits::black());
732 NodeTraits::set_color(x_parent, NodeTraits::red());
733 tree_algorithms::rotate_left(x_parent, header);
734 w = NodeTraits::get_right(x_parent);
736 if((NodeTraits::get_left(w) == 0 || NodeTraits::get_color(NodeTraits::get_left(w)) == NodeTraits::black()) &&
737 (NodeTraits::get_right(w) == 0 || NodeTraits::get_color(NodeTraits::get_right(w)) == NodeTraits::black())){
738 NodeTraits::set_color(w, NodeTraits::red());
739 x = x_parent;
740 x_parent = NodeTraits::get_parent(x_parent);
742 else {
743 if(NodeTraits::get_right(w) == 0 || NodeTraits::get_color(NodeTraits::get_right(w)) == NodeTraits::black()){
744 NodeTraits::set_color(NodeTraits::get_left(w), NodeTraits::black());
745 NodeTraits::set_color(w, NodeTraits::red());
746 tree_algorithms::rotate_right(w, header);
747 w = NodeTraits::get_right(x_parent);
749 NodeTraits::set_color(w, NodeTraits::get_color(x_parent));
750 NodeTraits::set_color(x_parent, NodeTraits::black());
751 if(NodeTraits::get_right(w))
752 NodeTraits::set_color(NodeTraits::get_right(w), NodeTraits::black());
753 tree_algorithms::rotate_left(x_parent, header);
754 break;
757 else {
758 // same as above, with right_ <-> left_.
759 node_ptr w = NodeTraits::get_left(x_parent);
760 if(NodeTraits::get_color(w) == NodeTraits::red()){
761 NodeTraits::set_color(w, NodeTraits::black());
762 NodeTraits::set_color(x_parent, NodeTraits::red());
763 tree_algorithms::rotate_right(x_parent, header);
764 w = NodeTraits::get_left(x_parent);
766 if((NodeTraits::get_right(w) == 0 || NodeTraits::get_color(NodeTraits::get_right(w)) == NodeTraits::black()) &&
767 (NodeTraits::get_left(w) == 0 || NodeTraits::get_color(NodeTraits::get_left(w)) == NodeTraits::black())){
768 NodeTraits::set_color(w, NodeTraits::red());
769 x = x_parent;
770 x_parent = NodeTraits::get_parent(x_parent);
772 else {
773 if(NodeTraits::get_left(w) == 0 || NodeTraits::get_color(NodeTraits::get_left(w)) == NodeTraits::black()){
774 NodeTraits::set_color(NodeTraits::get_right(w), NodeTraits::black());
775 NodeTraits::set_color(w, NodeTraits::red());
776 tree_algorithms::rotate_left(w, header);
777 w = NodeTraits::get_left(x_parent);
779 NodeTraits::set_color(w, NodeTraits::get_color(x_parent));
780 NodeTraits::set_color(x_parent, NodeTraits::black());
781 if(NodeTraits::get_left(w))
782 NodeTraits::set_color(NodeTraits::get_left(w), NodeTraits::black());
783 tree_algorithms::rotate_right(x_parent, header);
784 break;
788 if(x)
789 NodeTraits::set_color(x, NodeTraits::black());
793 static void rebalance_after_insertion(node_ptr header, node_ptr p)
795 NodeTraits::set_color(p, NodeTraits::red());
796 while(p != NodeTraits::get_parent(header) && NodeTraits::get_color(NodeTraits::get_parent(p)) == NodeTraits::red()){
797 node_ptr p_parent(NodeTraits::get_parent(p));
798 node_ptr p_parent_parent(NodeTraits::get_parent(p_parent));
799 if(tree_algorithms::is_left_child(p_parent)){
800 node_ptr x = NodeTraits::get_right(p_parent_parent);
801 if(x && NodeTraits::get_color(x) == NodeTraits::red()){
802 NodeTraits::set_color(p_parent, NodeTraits::black());
803 NodeTraits::set_color(p_parent_parent, NodeTraits::red());
804 NodeTraits::set_color(x, NodeTraits::black());
805 p = p_parent_parent;
807 else {
808 if(!tree_algorithms::is_left_child(p)){
809 p = p_parent;
810 tree_algorithms::rotate_left(p, header);
812 node_ptr new_p_parent(NodeTraits::get_parent(p));
813 node_ptr new_p_parent_parent(NodeTraits::get_parent(new_p_parent));
814 NodeTraits::set_color(new_p_parent, NodeTraits::black());
815 NodeTraits::set_color(new_p_parent_parent, NodeTraits::red());
816 tree_algorithms::rotate_right(new_p_parent_parent, header);
819 else{
820 node_ptr x = NodeTraits::get_left(p_parent_parent);
821 if(x && NodeTraits::get_color(x) == NodeTraits::red()){
822 NodeTraits::set_color(p_parent, NodeTraits::black());
823 NodeTraits::set_color(p_parent_parent, NodeTraits::red());
824 NodeTraits::set_color(x, NodeTraits::black());
825 p = p_parent_parent;
827 else{
828 if(tree_algorithms::is_left_child(p)){
829 p = p_parent;
830 tree_algorithms::rotate_right(p, header);
832 node_ptr new_p_parent(NodeTraits::get_parent(p));
833 node_ptr new_p_parent_parent(NodeTraits::get_parent(new_p_parent));
834 NodeTraits::set_color(new_p_parent, NodeTraits::black());
835 NodeTraits::set_color(new_p_parent_parent, NodeTraits::red());
836 tree_algorithms::rotate_left(new_p_parent_parent, header);
840 NodeTraits::set_color(NodeTraits::get_parent(header), NodeTraits::black());
842 /// @endcond
845 } //namespace intrusive
846 } //namespace boost
848 #include <boost/intrusive/detail/config_end.hpp>
850 #endif //BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP