1 /////////////////////////////////////////////////////////////////////////////
3 // (C) Copyright Ion Gaztanaga 2007-2012
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)
9 // See http://www.boost.org/libs/intrusive for documentation.
11 /////////////////////////////////////////////////////////////////////////////
13 // Scapegoat tree algorithms are taken from the paper titled:
14 // "Scapegoat Trees" by Igal Galperin Ronald L. Rivest.
16 /////////////////////////////////////////////////////////////////////////////
17 #ifndef BOOST_INTRUSIVE_SGTREE_ALGORITHMS_HPP
18 #define BOOST_INTRUSIVE_SGTREE_ALGORITHMS_HPP
20 #include <boost/intrusive/detail/config_begin.hpp>
23 #include <boost/intrusive/intrusive_fwd.hpp>
24 #include <boost/intrusive/detail/assert.hpp>
25 #include <boost/intrusive/detail/utilities.hpp>
26 #include <boost/intrusive/detail/tree_algorithms.hpp>
27 #include <boost/intrusive/pointer_traits.hpp>
33 //! sgtree_algorithms is configured with a NodeTraits class, which encapsulates the
34 //! information about the node to be manipulated. NodeTraits must support the
35 //! following interface:
39 //! <tt>node</tt>: The type of the node that forms the circular list
41 //! <tt>node_ptr</tt>: A pointer to a node
43 //! <tt>const_node_ptr</tt>: A pointer to a const node
45 //! <b>Static functions</b>:
47 //! <tt>static node_ptr get_parent(const_node_ptr n);</tt>
49 //! <tt>static void set_parent(node_ptr n, node_ptr parent);</tt>
51 //! <tt>static node_ptr get_left(const_node_ptr n);</tt>
53 //! <tt>static void set_left(node_ptr n, node_ptr left);</tt>
55 //! <tt>static node_ptr get_right(const_node_ptr n);</tt>
57 //! <tt>static void set_right(node_ptr n, node_ptr right);</tt>
58 template<class NodeTraits>
59 class sgtree_algorithms
62 typedef typename NodeTraits::node node;
63 typedef NodeTraits node_traits;
64 typedef typename NodeTraits::node_ptr node_ptr;
65 typedef typename NodeTraits::const_node_ptr const_node_ptr;
70 typedef detail::tree_algorithms<NodeTraits> tree_algorithms;
72 static node_ptr uncast(const const_node_ptr & ptr)
73 { return pointer_traits<node_ptr>::const_cast_from(ptr); }
77 static node_ptr begin_node(const const_node_ptr & header)
78 { return tree_algorithms::begin_node(header); }
80 static node_ptr end_node(const const_node_ptr & header)
81 { return tree_algorithms::end_node(header); }
83 //! This type is the information that will be
84 //! filled by insert_unique_check
85 struct insert_commit_data
86 : tree_algorithms::insert_commit_data
91 //! <b>Requires</b>: header1 and header2 must be the header nodes
94 //! <b>Effects</b>: Swaps two trees. After the function header1 will contain
95 //! links to the second tree and header2 will have links to the first tree.
97 //! <b>Complexity</b>: Constant.
99 //! <b>Throws</b>: Nothing.
100 static void swap_tree(const node_ptr & header1, const node_ptr & header2)
101 { return tree_algorithms::swap_tree(header1, header2); }
103 //! <b>Requires</b>: node1 and node2 can't be header nodes
106 //! <b>Effects</b>: Swaps two nodes. After the function node1 will be inserted
107 //! in the position node2 before the function. node2 will be inserted in the
108 //! position node1 had before the function.
110 //! <b>Complexity</b>: Logarithmic.
112 //! <b>Throws</b>: Nothing.
114 //! <b>Note</b>: This function will break container ordering invariants if
115 //! node1 and node2 are not equivalent according to the ordering rules.
117 //!Experimental function
118 static void swap_nodes(const node_ptr & node1, const node_ptr & node2)
123 node_ptr header1(tree_algorithms::get_header(node1)), header2(tree_algorithms::get_header(node2));
124 swap_nodes(node1, header1, node2, header2);
127 //! <b>Requires</b>: node1 and node2 can't be header nodes
128 //! of two trees with header header1 and header2.
130 //! <b>Effects</b>: Swaps two nodes. After the function node1 will be inserted
131 //! in the position node2 before the function. node2 will be inserted in the
132 //! position node1 had before the function.
134 //! <b>Complexity</b>: Constant.
136 //! <b>Throws</b>: Nothing.
138 //! <b>Note</b>: This function will break container ordering invariants if
139 //! node1 and node2 are not equivalent according to the ordering rules.
141 //!Experimental function
142 static void swap_nodes(const node_ptr & node1, const node_ptr & header1, const node_ptr & node2, const node_ptr & header2)
143 { tree_algorithms::swap_nodes(node1, header1, node2, header2); }
145 //! <b>Requires</b>: node_to_be_replaced must be inserted in a tree
146 //! and new_node must not be inserted in a tree.
148 //! <b>Effects</b>: Replaces node_to_be_replaced in its position in the
149 //! tree with new_node. The tree does not need to be rebalanced
151 //! <b>Complexity</b>: Logarithmic.
153 //! <b>Throws</b>: Nothing.
155 //! <b>Note</b>: This function will break container ordering invariants if
156 //! new_node is not equivalent to node_to_be_replaced according to the
157 //! ordering rules. This function is faster than erasing and inserting
158 //! the node, since no rebalancing and comparison is needed.
160 //!Experimental function
161 static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & new_node)
163 if(node_to_be_replaced == new_node)
165 replace_node(node_to_be_replaced, tree_algorithms::get_header(node_to_be_replaced), new_node);
168 //! <b>Requires</b>: node_to_be_replaced must be inserted in a tree
169 //! with header "header" and new_node must not be inserted in a tree.
171 //! <b>Effects</b>: Replaces node_to_be_replaced in its position in the
172 //! tree with new_node. The tree does not need to be rebalanced
174 //! <b>Complexity</b>: Constant.
176 //! <b>Throws</b>: Nothing.
178 //! <b>Note</b>: This function will break container ordering invariants if
179 //! new_node is not equivalent to node_to_be_replaced according to the
180 //! ordering rules. This function is faster than erasing and inserting
181 //! the node, since no rebalancing or comparison is needed.
183 //!Experimental function
184 static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & header, const node_ptr & new_node)
185 { tree_algorithms::replace_node(node_to_be_replaced, header, new_node); }
187 //! <b>Requires</b>: node is a tree node but not the header.
189 //! <b>Effects</b>: Unlinks the node and rebalances the tree.
191 //! <b>Complexity</b>: Average complexity is constant time.
193 //! <b>Throws</b>: Nothing.
194 static void unlink(const node_ptr & node)
196 node_ptr x = NodeTraits::get_parent(node);
199 x = NodeTraits::get_parent(x);
200 tree_algorithms::erase(x, node);
204 //! <b>Requires</b>: header is the header of a tree.
206 //! <b>Effects</b>: Unlinks the leftmost node from the tree, and
207 //! updates the header link to the new leftmost node.
209 //! <b>Complexity</b>: Average complexity is constant time.
211 //! <b>Throws</b>: Nothing.
213 //! <b>Notes</b>: This function breaks the tree and the tree can
214 //! only be used for more unlink_leftmost_without_rebalance calls.
215 //! This function is normally used to achieve a step by step
216 //! controlled destruction of the tree.
217 static node_ptr unlink_leftmost_without_rebalance(const node_ptr & header)
218 { return tree_algorithms::unlink_leftmost_without_rebalance(header); }
220 //! <b>Requires</b>: node is a node of the tree or an node initialized
223 //! <b>Effects</b>: Returns true if the node is initialized by init().
225 //! <b>Complexity</b>: Constant time.
227 //! <b>Throws</b>: Nothing.
228 static bool unique(const const_node_ptr & node)
229 { return tree_algorithms::unique(node); }
231 //! <b>Requires</b>: node is a node of the tree but it's not the header.
233 //! <b>Effects</b>: Returns the number of nodes of the subtree.
235 //! <b>Complexity</b>: Linear time.
237 //! <b>Throws</b>: Nothing.
238 static std::size_t count(const const_node_ptr & node)
239 { return tree_algorithms::count(node); }
241 //! <b>Requires</b>: header is the header node of the tree.
243 //! <b>Effects</b>: Returns the number of nodes above the header.
245 //! <b>Complexity</b>: Linear time.
247 //! <b>Throws</b>: Nothing.
248 static std::size_t size(const const_node_ptr & header)
249 { return tree_algorithms::size(header); }
251 //! <b>Requires</b>: p is a node from the tree except the header.
253 //! <b>Effects</b>: Returns the next node of the tree.
255 //! <b>Complexity</b>: Average constant time.
257 //! <b>Throws</b>: Nothing.
258 static node_ptr next_node(const node_ptr & p)
259 { return tree_algorithms::next_node(p); }
261 //! <b>Requires</b>: p is a node from the tree except the leftmost node.
263 //! <b>Effects</b>: Returns the previous node of the tree.
265 //! <b>Complexity</b>: Average constant time.
267 //! <b>Throws</b>: Nothing.
268 static node_ptr prev_node(const node_ptr & p)
269 { return tree_algorithms::prev_node(p); }
271 //! <b>Requires</b>: node must not be part of any tree.
273 //! <b>Effects</b>: After the function unique(node) == true.
275 //! <b>Complexity</b>: Constant.
277 //! <b>Throws</b>: Nothing.
279 //! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
280 static void init(const node_ptr & node)
281 { tree_algorithms::init(node); }
283 //! <b>Requires</b>: node must not be part of any tree.
285 //! <b>Effects</b>: Initializes the header to represent an empty tree.
286 //! unique(header) == true.
288 //! <b>Complexity</b>: Constant.
290 //! <b>Throws</b>: Nothing.
292 //! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
293 static void init_header(const node_ptr & header)
294 { tree_algorithms::init_header(header); }
296 //! <b>Requires</b>: header must be the header of a tree, z a node
297 //! of that tree and z != header.
299 //! <b>Effects</b>: Erases node "z" from the tree with header "header".
301 //! <b>Complexity</b>: Amortized constant time.
303 //! <b>Throws</b>: Nothing.
304 template<class AlphaByMaxSize>
305 static node_ptr erase(const node_ptr & header, const node_ptr & z, std::size_t tree_size, std::size_t &max_tree_size, AlphaByMaxSize alpha_by_maxsize)
307 //typename tree_algorithms::data_for_rebalance info;
308 tree_algorithms::erase(header, z);
311 tree_size < alpha_by_maxsize(max_tree_size)){
312 tree_algorithms::rebalance(header);
313 max_tree_size = tree_size;
318 //! <b>Requires</b>: "cloner" must be a function
319 //! object taking a node_ptr and returning a new cloned node of it. "disposer" must
320 //! take a node_ptr and shouldn't throw.
322 //! <b>Effects</b>: First empties target tree calling
323 //! <tt>void disposer::operator()(const node_ptr &)</tt> for every node of the tree
324 //! except the header.
326 //! Then, duplicates the entire tree pointed by "source_header" cloning each
327 //! source node with <tt>node_ptr Cloner::operator()(const node_ptr &)</tt> to obtain
328 //! the nodes of the target tree. If "cloner" throws, the cloned target nodes
329 //! are disposed using <tt>void disposer(const node_ptr &)</tt>.
331 //! <b>Complexity</b>: Linear to the number of element of the source tree plus the.
332 //! number of elements of tree target tree when calling this function.
334 //! <b>Throws</b>: If cloner functor throws. If this happens target nodes are disposed.
335 template <class Cloner, class Disposer>
337 (const const_node_ptr & source_header, const node_ptr & target_header, Cloner cloner, Disposer disposer)
339 tree_algorithms::clone(source_header, target_header, cloner, disposer);
342 //! <b>Requires</b>: "disposer" must be an object function
343 //! taking a node_ptr parameter and shouldn't throw.
345 //! <b>Effects</b>: Empties the target tree calling
346 //! <tt>void disposer::operator()(const node_ptr &)</tt> for every node of the tree
347 //! except the header.
349 //! <b>Complexity</b>: Linear to the number of element of the source tree plus the.
350 //! number of elements of tree target tree when calling this function.
352 //! <b>Throws</b>: If cloner functor throws. If this happens target nodes are disposed.
353 template<class Disposer>
354 static void clear_and_dispose(const node_ptr & header, Disposer disposer)
355 { tree_algorithms::clear_and_dispose(header, disposer); }
357 //! <b>Requires</b>: "header" must be the header node of a tree.
358 //! KeyNodePtrCompare is a function object that induces a strict weak
359 //! ordering compatible with the strict weak ordering used to create the
360 //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
362 //! <b>Effects</b>: Returns an node_ptr to the first element that is
363 //! not less than "key" according to "comp" or "header" if that element does
366 //! <b>Complexity</b>: Logarithmic.
368 //! <b>Throws</b>: If "comp" throws.
369 template<class KeyType, class KeyNodePtrCompare>
370 static node_ptr lower_bound
371 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
372 { return tree_algorithms::lower_bound(header, key, comp); }
374 //! <b>Requires</b>: "header" must be the header node of a tree.
375 //! KeyNodePtrCompare is a function object that induces a strict weak
376 //! ordering compatible with the strict weak ordering used to create the
377 //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
379 //! <b>Effects</b>: Returns an node_ptr to the first element that is greater
380 //! than "key" according to "comp" or "header" if that element does not exist.
382 //! <b>Complexity</b>: Logarithmic.
384 //! <b>Throws</b>: If "comp" throws.
385 template<class KeyType, class KeyNodePtrCompare>
386 static node_ptr upper_bound
387 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
388 { return tree_algorithms::upper_bound(header, key, comp); }
390 //! <b>Requires</b>: "header" must be the header node of a tree.
391 //! KeyNodePtrCompare is a function object that induces a strict weak
392 //! ordering compatible with the strict weak ordering used to create the
393 //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
395 //! <b>Effects</b>: Returns an node_ptr to the element that is equivalent to
396 //! "key" according to "comp" or "header" if that element does not exist.
398 //! <b>Complexity</b>: Logarithmic.
400 //! <b>Throws</b>: If "comp" throws.
401 template<class KeyType, class KeyNodePtrCompare>
403 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
404 { return tree_algorithms::find(header, key, comp); }
406 //! <b>Requires</b>: "header" must be the header node of a tree.
407 //! KeyNodePtrCompare is a function object that induces a strict weak
408 //! ordering compatible with the strict weak ordering used to create the
409 //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
411 //! <b>Effects</b>: Returns an a pair of node_ptr delimiting a range containing
412 //! all elements that are equivalent to "key" according to "comp" or an
413 //! empty range that indicates the position where those elements would be
414 //! if they there are no equivalent elements.
416 //! <b>Complexity</b>: Logarithmic.
418 //! <b>Throws</b>: If "comp" throws.
419 template<class KeyType, class KeyNodePtrCompare>
420 static std::pair<node_ptr, node_ptr> equal_range
421 (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
422 { return tree_algorithms::equal_range(header, key, comp); }
424 //! <b>Requires</b>: "header" must be the header node of a tree.
425 //! KeyNodePtrCompare is a function object that induces a strict weak
426 //! ordering compatible with the strict weak ordering used to create the
427 //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
428 //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If
429 //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false.
431 //! <b>Effects</b>: Returns an a pair with the following criteria:
433 //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise
435 //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise
437 //! <b>Complexity</b>: Logarithmic.
439 //! <b>Throws</b>: If "comp" throws.
441 //! <b>Note</b>: This function can be more efficient than calling upper_bound
442 //! and lower_bound for lower_key and upper_key.
443 template<class KeyType, class KeyNodePtrCompare>
444 static std::pair<node_ptr, node_ptr> bounded_range
445 (const const_node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp
446 , bool left_closed, bool right_closed)
447 { return tree_algorithms::bounded_range(header, lower_key, upper_key, comp, left_closed, right_closed); }
449 //! <b>Requires</b>: "h" must be the header node of a tree.
450 //! NodePtrCompare is a function object that induces a strict weak
451 //! ordering compatible with the strict weak ordering used to create the
452 //! the tree. NodePtrCompare compares two node_ptrs.
454 //! <b>Effects</b>: Inserts new_node into the tree before the upper bound
455 //! according to "comp".
457 //! <b>Complexity</b>: Average complexity for insert element is at
458 //! most logarithmic.
460 //! <b>Throws</b>: If "comp" throws.
461 template<class NodePtrCompare, class H_Alpha>
462 static node_ptr insert_equal_upper_bound
463 (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp
464 ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size)
467 tree_algorithms::insert_equal_upper_bound(h, new_node, comp, &depth);
468 rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size);
472 //! <b>Requires</b>: "h" must be the header node of a tree.
473 //! NodePtrCompare is a function object that induces a strict weak
474 //! ordering compatible with the strict weak ordering used to create the
475 //! the tree. NodePtrCompare compares two node_ptrs.
477 //! <b>Effects</b>: Inserts new_node into the tree before the lower bound
478 //! according to "comp".
480 //! <b>Complexity</b>: Average complexity for insert element is at
481 //! most logarithmic.
483 //! <b>Throws</b>: If "comp" throws.
484 template<class NodePtrCompare, class H_Alpha>
485 static node_ptr insert_equal_lower_bound
486 (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp
487 ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size)
490 tree_algorithms::insert_equal_lower_bound(h, new_node, comp, &depth);
491 rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size);
495 //! <b>Requires</b>: "header" must be the header node of a tree.
496 //! NodePtrCompare is a function object that induces a strict weak
497 //! ordering compatible with the strict weak ordering used to create the
498 //! the tree. NodePtrCompare compares two node_ptrs. "hint" is node from
499 //! the "header"'s tree.
501 //! <b>Effects</b>: Inserts new_node into the tree, using "hint" as a hint to
502 //! where it will be inserted. If "hint" is the upper_bound
503 //! the insertion takes constant time (two comparisons in the worst case).
505 //! <b>Complexity</b>: Logarithmic in general, but it is amortized
506 //! constant time if new_node is inserted immediately before "hint".
508 //! <b>Throws</b>: If "comp" throws.
509 template<class NodePtrCompare, class H_Alpha>
510 static node_ptr insert_equal
511 (const node_ptr & header, const node_ptr & hint, const node_ptr & new_node, NodePtrCompare comp
512 ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size)
515 tree_algorithms::insert_equal(header, hint, new_node, comp, &depth);
516 rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size);
520 //! <b>Requires</b>: "header" must be the header node of a tree.
521 //! KeyNodePtrCompare is a function object that induces a strict weak
522 //! ordering compatible with the strict weak ordering used to create the
523 //! the tree. NodePtrCompare compares KeyType with a node_ptr.
525 //! <b>Effects</b>: Checks if there is an equivalent node to "key" in the
526 //! tree according to "comp" and obtains the needed information to realize
527 //! a constant-time node insertion if there is no equivalent node.
529 //! <b>Returns</b>: If there is an equivalent value
530 //! returns a pair containing a node_ptr to the already present node
531 //! and false. If there is not equivalent key can be inserted returns true
532 //! in the returned pair's boolean and fills "commit_data" that is meant to
533 //! be used with the "insert_commit" function to achieve a constant-time
534 //! insertion function.
536 //! <b>Complexity</b>: Average complexity is at most logarithmic.
538 //! <b>Throws</b>: If "comp" throws.
540 //! <b>Notes</b>: This function is used to improve performance when constructing
541 //! a node is expensive and the user does not want to have two equivalent nodes
542 //! in the tree: if there is an equivalent value
543 //! the constructed object must be discarded. Many times, the part of the
544 //! node that is used to impose the order is much cheaper to construct
545 //! than the node and this function offers the possibility to use that part
546 //! to check if the insertion will be successful.
548 //! If the check is successful, the user can construct the node and use
549 //! "insert_commit" to insert the node in constant-time. This gives a total
550 //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)).
552 //! "commit_data" remains valid for a subsequent "insert_unique_commit" only
553 //! if no more objects are inserted or erased from the set.
554 template<class KeyType, class KeyNodePtrCompare>
555 static std::pair<node_ptr, bool> insert_unique_check
556 (const const_node_ptr & header, const KeyType &key
557 ,KeyNodePtrCompare comp, insert_commit_data &commit_data)
560 std::pair<node_ptr, bool> ret =
561 tree_algorithms::insert_unique_check(header, key, comp, commit_data, &depth);
562 commit_data.depth = depth;
567 //! <b>Requires</b>: "header" must be the header node of a tree.
568 //! "pos" must be a valid iterator or header (end) node.
569 //! "pos" must be an iterator pointing to the successor to "new_node"
570 //! once inserted according to the order of already inserted nodes. This function does not
571 //! check "pos" and this precondition must be guaranteed by the caller.
573 //! <b>Effects</b>: Inserts new_node into the tree before "pos".
575 //! <b>Complexity</b>: Constant-time.
577 //! <b>Throws</b>: Nothing.
579 //! <b>Note</b>: If "pos" is not the successor of the newly inserted "new_node"
580 //! tree invariants might be broken.
581 template<class H_Alpha>
582 static node_ptr insert_before
583 (const node_ptr & header, const node_ptr & pos, const node_ptr & new_node
584 ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size)
587 tree_algorithms::insert_before(header, pos, new_node, &depth);
588 rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size);
592 //! <b>Requires</b>: "header" must be the header node of a tree.
593 //! "new_node" must be, according to the used ordering no less than the
594 //! greatest inserted key.
596 //! <b>Effects</b>: Inserts new_node into the tree before "pos".
598 //! <b>Complexity</b>: Constant-time.
600 //! <b>Throws</b>: Nothing.
602 //! <b>Note</b>: If "new_node" is less than the greatest inserted key
603 //! tree invariants are broken. This function is slightly faster than
604 //! using "insert_before".
605 template<class H_Alpha>
606 static void push_back(const node_ptr & header, const node_ptr & new_node
607 ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size)
610 tree_algorithms::push_back(header, new_node, &depth);
611 rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size);
614 //! <b>Requires</b>: "header" must be the header node of a tree.
615 //! "new_node" must be, according to the used ordering, no greater than the
616 //! lowest inserted key.
618 //! <b>Effects</b>: Inserts new_node into the tree before "pos".
620 //! <b>Complexity</b>: Constant-time.
622 //! <b>Throws</b>: Nothing.
624 //! <b>Note</b>: If "new_node" is greater than the lowest inserted key
625 //! tree invariants are broken. This function is slightly faster than
626 //! using "insert_before".
627 template<class H_Alpha>
628 static void push_front(const node_ptr & header, const node_ptr & new_node
629 ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size)
632 tree_algorithms::push_front(header, new_node, &depth);
633 rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size);
636 //! <b>Requires</b>: "header" must be the header node of a tree.
637 //! KeyNodePtrCompare is a function object that induces a strict weak
638 //! ordering compatible with the strict weak ordering used to create the
639 //! the tree. NodePtrCompare compares KeyType with a node_ptr.
640 //! "hint" is node from the "header"'s tree.
642 //! <b>Effects</b>: Checks if there is an equivalent node to "key" in the
643 //! tree according to "comp" using "hint" as a hint to where it should be
644 //! inserted and obtains the needed information to realize
645 //! a constant-time node insertion if there is no equivalent node.
646 //! If "hint" is the upper_bound the function has constant time
647 //! complexity (two comparisons in the worst case).
649 //! <b>Returns</b>: If there is an equivalent value
650 //! returns a pair containing a node_ptr to the already present node
651 //! and false. If there is not equivalent key can be inserted returns true
652 //! in the returned pair's boolean and fills "commit_data" that is meant to
653 //! be used with the "insert_commit" function to achieve a constant-time
654 //! insertion function.
656 //! <b>Complexity</b>: Average complexity is at most logarithmic, but it is
657 //! amortized constant time if new_node should be inserted immediately before "hint".
659 //! <b>Throws</b>: If "comp" throws.
661 //! <b>Notes</b>: This function is used to improve performance when constructing
662 //! a node is expensive and the user does not want to have two equivalent nodes
663 //! in the tree: if there is an equivalent value
664 //! the constructed object must be discarded. Many times, the part of the
665 //! node that is used to impose the order is much cheaper to construct
666 //! than the node and this function offers the possibility to use that part
667 //! to check if the insertion will be successful.
669 //! If the check is successful, the user can construct the node and use
670 //! "insert_commit" to insert the node in constant-time. This gives a total
671 //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)).
673 //! "commit_data" remains valid for a subsequent "insert_unique_commit" only
674 //! if no more objects are inserted or erased from the set.
675 template<class KeyType, class KeyNodePtrCompare>
676 static std::pair<node_ptr, bool> insert_unique_check
677 (const const_node_ptr & header, const node_ptr &hint, const KeyType &key
678 ,KeyNodePtrCompare comp, insert_commit_data &commit_data)
681 std::pair<node_ptr, bool> ret =
682 tree_algorithms::insert_unique_check
683 (header, hint, key, comp, commit_data, &depth);
684 commit_data.depth = depth;
688 //! <b>Requires</b>: "header" must be the header node of a tree.
689 //! "commit_data" must have been obtained from a previous call to
690 //! "insert_unique_check". No objects should have been inserted or erased
691 //! from the set between the "insert_unique_check" that filled "commit_data"
692 //! and the call to "insert_commit".
695 //! <b>Effects</b>: Inserts new_node in the set using the information obtained
696 //! from the "commit_data" that a previous "insert_check" filled.
698 //! <b>Complexity</b>: Constant time.
700 //! <b>Throws</b>: Nothing.
702 //! <b>Notes</b>: This function has only sense if a "insert_unique_check" has been
703 //! previously executed to fill "commit_data". No value should be inserted or
704 //! erased between the "insert_check" and "insert_commit" calls.
705 template<class H_Alpha>
706 static void insert_unique_commit
707 (const node_ptr & header, const node_ptr & new_value, const insert_commit_data &commit_data
708 ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size)
710 tree_algorithms::insert_unique_commit(header, new_value, commit_data);
711 rebalance_after_insertion(new_value, commit_data.depth, tree_size+1, h_alpha, max_tree_size);
714 //! <b>Requires</b>: header must be the header of a tree.
716 //! <b>Effects</b>: Rebalances the tree.
718 //! <b>Throws</b>: Nothing.
720 //! <b>Complexity</b>: Linear.
721 static void rebalance(const node_ptr & header)
722 { tree_algorithms::rebalance(header); }
724 //! <b>Requires</b>: old_root is a node of a tree.
726 //! <b>Effects</b>: Rebalances the subtree rooted at old_root.
728 //! <b>Returns</b>: The new root of the subtree.
730 //! <b>Throws</b>: Nothing.
732 //! <b>Complexity</b>: Linear.
733 static node_ptr rebalance_subtree(const node_ptr & old_root)
734 { return tree_algorithms::rebalance_subtree(old_root); }
736 //! <b>Requires</b>: "n" must be a node inserted in a tree.
738 //! <b>Effects</b>: Returns a pointer to the header node of the tree.
740 //! <b>Complexity</b>: Logarithmic.
742 //! <b>Throws</b>: Nothing.
743 static node_ptr get_header(const node_ptr & n)
744 { return tree_algorithms::get_header(n); }
749 //! <b>Requires</b>: p is a node of a tree.
751 //! <b>Effects</b>: Returns true if p is the header of the tree.
753 //! <b>Complexity</b>: Constant.
755 //! <b>Throws</b>: Nothing.
756 static bool is_header(const const_node_ptr & p)
757 { return tree_algorithms::is_header(p); }
759 template<class H_Alpha>
760 static void rebalance_after_insertion
761 (const node_ptr &x, std::size_t depth
762 , std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size)
764 if(tree_size > max_tree_size)
765 max_tree_size = tree_size;
767 if(tree_size != 1 && depth > h_alpha(tree_size)){
768 //Find the first non height-balanced node
769 //as described in the section 4.2 of the paper.
770 //This method is the alternative method described
771 //in the paper. Authors claim that this method
772 //may tend to yield more balanced trees on the average
773 //than the weight balanced method.
775 std::size_t size = 1;
777 for(std::size_t i = 1; true; ++i){
778 bool rebalance = false;
780 BOOST_INTRUSIVE_INVARIANT_ASSERT(tree_size == count(s));
783 else if(i > h_alpha(size)){
784 node_ptr s_parent = NodeTraits::get_parent(s);
785 node_ptr s_parent_left = NodeTraits::get_left(s_parent);
786 size += 1 + tree_algorithms::count
787 ( s_parent_left == s ? NodeTraits::get_right(s_parent) : s_parent_left );
792 rebalance_subtree(s);
802 } //namespace intrusive
805 #include <boost/intrusive/detail/config_end.hpp>
807 #endif //BOOST_INTRUSIVE_SGTREE_ALGORITHMS_HPP