• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // boost heap: fibonacci heap
2 //
3 // Copyright (C) 2010 Tim Blechmann
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 
9 #ifndef BOOST_HEAP_FIBONACCI_HEAP_HPP
10 #define BOOST_HEAP_FIBONACCI_HEAP_HPP
11 
12 #include <algorithm>
13 #include <utility>
14 #include <vector>
15 
16 #include <boost/array.hpp>
17 #include <boost/assert.hpp>
18 
19 #include <boost/heap/detail/heap_comparison.hpp>
20 #include <boost/heap/detail/heap_node.hpp>
21 #include <boost/heap/detail/stable_heap.hpp>
22 #include <boost/heap/detail/tree_iterator.hpp>
23 #include <boost/type_traits/integral_constant.hpp>
24 
25 #ifdef BOOST_HAS_PRAGMA_ONCE
26 #pragma once
27 #endif
28 
29 
30 #ifndef BOOST_DOXYGEN_INVOKED
31 #ifdef BOOST_HEAP_SANITYCHECKS
32 #define BOOST_HEAP_ASSERT BOOST_ASSERT
33 #else
34 #define BOOST_HEAP_ASSERT(expression)
35 #endif
36 #endif
37 
38 namespace boost  {
39 namespace heap   {
40 namespace detail {
41 
42 typedef parameter::parameters<boost::parameter::optional<tag::allocator>,
43                               boost::parameter::optional<tag::compare>,
44                               boost::parameter::optional<tag::stable>,
45                               boost::parameter::optional<tag::constant_time_size>,
46                               boost::parameter::optional<tag::stability_counter_type>
47                              > fibonacci_heap_signature;
48 
49 template <typename T, typename Parspec>
50 struct make_fibonacci_heap_base
51 {
52     static const bool constant_time_size = parameter::binding<Parspec,
53                                                               tag::constant_time_size,
54                                                               boost::true_type
55                                                              >::type::value;
56 
57     typedef typename detail::make_heap_base<T, Parspec, constant_time_size>::type base_type;
58     typedef typename detail::make_heap_base<T, Parspec, constant_time_size>::allocator_argument allocator_argument;
59     typedef typename detail::make_heap_base<T, Parspec, constant_time_size>::compare_argument compare_argument;
60     typedef marked_heap_node<typename base_type::internal_type> node_type;
61 
62     typedef typename boost::allocator_rebind<allocator_argument, node_type>::type allocator_type;
63 
64     struct type:
65         base_type,
66         allocator_type
67     {
typeboost::heap::detail::make_fibonacci_heap_base::type68         type(compare_argument const & arg):
69             base_type(arg)
70         {}
71 
typeboost::heap::detail::make_fibonacci_heap_base::type72         type(type const & rhs):
73             base_type(static_cast<base_type const &>(rhs)),
74             allocator_type(static_cast<allocator_type const &>(rhs))
75         {}
76 
operator =boost::heap::detail::make_fibonacci_heap_base::type77         type & operator=(type const & rhs)
78         {
79             base_type::operator=(static_cast<base_type const &>(rhs));
80             allocator_type::operator=(static_cast<allocator_type const &>(rhs));
81             return *this;
82         }
83 
84 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
typeboost::heap::detail::make_fibonacci_heap_base::type85         type(type && rhs):
86             base_type(std::move(static_cast<base_type&>(rhs))),
87             allocator_type(std::move(static_cast<allocator_type&>(rhs)))
88         {}
89 
operator =boost::heap::detail::make_fibonacci_heap_base::type90         type & operator=(type && rhs)
91         {
92             base_type::operator=(std::move(static_cast<base_type&>(rhs)));
93             allocator_type::operator=(std::move(static_cast<allocator_type&>(rhs)));
94             return *this;
95         }
96 #endif
97     };
98 };
99 
100 }
101 
102 
103 
104 /**
105  * \class fibonacci_heap
106  * \brief fibonacci heap
107  *
108  * The template parameter T is the type to be managed by the container.
109  * The user can specify additional options and if no options are provided default options are used.
110  *
111  * The container supports the following options:
112  * - \c boost::heap::stable<>, defaults to \c stable<false>
113  * - \c boost::heap::compare<>, defaults to \c compare<std::less<T> >
114  * - \c boost::heap::allocator<>, defaults to \c allocator<std::allocator<T> >
115  * - \c boost::heap::constant_time_size<>, defaults to \c constant_time_size<true>
116  * - \c boost::heap::stability_counter_type<>, defaults to \c stability_counter_type<boost::uintmax_t>
117  *
118  */
119 #ifdef BOOST_DOXYGEN_INVOKED
120 template<class T, class ...Options>
121 #else
122 template <typename T,
123           class A0 = boost::parameter::void_,
124           class A1 = boost::parameter::void_,
125           class A2 = boost::parameter::void_,
126           class A3 = boost::parameter::void_,
127           class A4 = boost::parameter::void_
128          >
129 #endif
130 class fibonacci_heap:
131     private detail::make_fibonacci_heap_base<T,
132                                              typename detail::fibonacci_heap_signature::bind<A0, A1, A2, A3, A4>::type
133                                             >::type
134 {
135     typedef typename detail::fibonacci_heap_signature::bind<A0, A1, A2, A3, A4>::type bound_args;
136     typedef detail::make_fibonacci_heap_base<T, bound_args> base_maker;
137     typedef typename base_maker::type super_t;
138 
139     typedef typename super_t::size_holder_type size_holder;
140     typedef typename super_t::internal_type internal_type;
141     typedef typename base_maker::allocator_argument allocator_argument;
142 
143     template <typename Heap1, typename Heap2>
144     friend struct heap_merge_emulate;
145 
146 private:
147 #ifndef BOOST_DOXYGEN_INVOKED
148     struct implementation_defined:
149         detail::extract_allocator_types<typename base_maker::allocator_argument>
150     {
151         typedef T value_type;
152         typedef typename detail::extract_allocator_types<typename base_maker::allocator_argument>::size_type size_type;
153         typedef typename detail::extract_allocator_types<typename base_maker::allocator_argument>::reference reference;
154 
155         typedef typename base_maker::compare_argument value_compare;
156         typedef typename base_maker::allocator_type allocator_type;
157 
158         typedef typename boost::allocator_pointer<allocator_type>::type node_pointer;
159         typedef typename boost::allocator_const_pointer<allocator_type>::type const_node_pointer;
160 
161         typedef detail::heap_node_list node_list_type;
162         typedef typename node_list_type::iterator node_list_iterator;
163         typedef typename node_list_type::const_iterator node_list_const_iterator;
164 
165         typedef typename base_maker::node_type node;
166 
167         typedef detail::value_extractor<value_type, internal_type, super_t> value_extractor;
168         typedef typename super_t::internal_compare internal_compare;
169         typedef detail::node_handle<node_pointer, super_t, reference> handle_type;
170 
171         typedef detail::recursive_tree_iterator<node,
172                                                 node_list_const_iterator,
173                                                 const value_type,
174                                                 value_extractor,
175                                                 detail::list_iterator_converter<node, node_list_type>
176                                                > iterator;
177         typedef iterator const_iterator;
178 
179         typedef detail::tree_iterator<node,
180                                       const value_type,
181                                       allocator_type,
182                                       value_extractor,
183                                       detail::list_iterator_converter<node, node_list_type>,
184                                       true,
185                                       true,
186                                       value_compare
187                                     > ordered_iterator;
188     };
189 
190     typedef typename implementation_defined::node node;
191     typedef typename implementation_defined::node_pointer node_pointer;
192     typedef typename implementation_defined::node_list_type node_list_type;
193     typedef typename implementation_defined::node_list_iterator node_list_iterator;
194     typedef typename implementation_defined::node_list_const_iterator node_list_const_iterator;
195     typedef typename implementation_defined::internal_compare internal_compare;
196 #endif
197 
198 public:
199     typedef T value_type;
200 
201     typedef typename implementation_defined::size_type size_type;
202     typedef typename implementation_defined::difference_type difference_type;
203     typedef typename implementation_defined::value_compare value_compare;
204     typedef typename implementation_defined::allocator_type allocator_type;
205     typedef typename implementation_defined::reference reference;
206     typedef typename implementation_defined::const_reference const_reference;
207     typedef typename implementation_defined::pointer pointer;
208     typedef typename implementation_defined::const_pointer const_pointer;
209     /// \copydoc boost::heap::priority_queue::iterator
210     typedef typename implementation_defined::iterator iterator;
211     typedef typename implementation_defined::const_iterator const_iterator;
212     typedef typename implementation_defined::ordered_iterator ordered_iterator;
213 
214     typedef typename implementation_defined::handle_type handle_type;
215 
216     static const bool constant_time_size = base_maker::constant_time_size;
217     static const bool has_ordered_iterators = true;
218     static const bool is_mergable = true;
219     static const bool is_stable = detail::extract_stable<bound_args>::value;
220     static const bool has_reserve = false;
221 
222     /// \copydoc boost::heap::priority_queue::priority_queue(value_compare const &)
fibonacci_heap(value_compare const & cmp=value_compare ())223     explicit fibonacci_heap(value_compare const & cmp = value_compare()):
224         super_t(cmp), top_element(0)
225     {}
226 
227     /// \copydoc boost::heap::priority_queue::priority_queue(priority_queue const &)
fibonacci_heap(fibonacci_heap const & rhs)228     fibonacci_heap(fibonacci_heap const & rhs):
229         super_t(rhs), top_element(0)
230     {
231         if (rhs.empty())
232             return;
233 
234         clone_forest(rhs);
235         size_holder::set_size(rhs.size());
236     }
237 
238 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
239     /// \copydoc boost::heap::priority_queue::priority_queue(priority_queue &&)
fibonacci_heap(fibonacci_heap && rhs)240     fibonacci_heap(fibonacci_heap && rhs):
241         super_t(std::move(rhs)), top_element(rhs.top_element)
242     {
243         roots.splice(roots.begin(), rhs.roots);
244         rhs.top_element = NULL;
245     }
246 
247     /// \copydoc boost::heap::priority_queue::operator=(priority_queue &&)
operator =(fibonacci_heap && rhs)248     fibonacci_heap & operator=(fibonacci_heap && rhs)
249     {
250         clear();
251 
252         super_t::operator=(std::move(rhs));
253         roots.splice(roots.begin(), rhs.roots);
254         top_element = rhs.top_element;
255         rhs.top_element = NULL;
256         return *this;
257     }
258 #endif
259 
260     /// \copydoc boost::heap::priority_queue::operator=(priority_queue const &)
operator =(fibonacci_heap const & rhs)261     fibonacci_heap & operator=(fibonacci_heap const & rhs)
262     {
263         clear();
264         size_holder::set_size(rhs.size());
265         static_cast<super_t&>(*this) = rhs;
266 
267         if (rhs.empty())
268             top_element = NULL;
269         else
270             clone_forest(rhs);
271         return *this;
272     }
273 
~fibonacci_heap(void)274     ~fibonacci_heap(void)
275     {
276         clear();
277     }
278 
279     /// \copydoc boost::heap::priority_queue::empty
empty(void) const280     bool empty(void) const
281     {
282         if (constant_time_size)
283             return size() == 0;
284         else
285             return roots.empty();
286     }
287 
288     /// \copydoc boost::heap::priority_queue::size
size(void) const289     size_type size(void) const
290     {
291         if (constant_time_size)
292             return size_holder::get_size();
293 
294         if (empty())
295             return 0;
296         else
297             return detail::count_list_nodes<node, node_list_type>(roots);
298     }
299 
300     /// \copydoc boost::heap::priority_queue::max_size
max_size(void) const301     size_type max_size(void) const
302     {
303         const allocator_type& alloc = *this;
304         return boost::allocator_max_size(alloc);
305     }
306 
307     /// \copydoc boost::heap::priority_queue::clear
clear(void)308     void clear(void)
309     {
310         typedef detail::node_disposer<node, typename node_list_type::value_type, allocator_type> disposer;
311         roots.clear_and_dispose(disposer(*this));
312 
313         size_holder::set_size(0);
314         top_element = NULL;
315     }
316 
317     /// \copydoc boost::heap::priority_queue::get_allocator
get_allocator(void) const318     allocator_type get_allocator(void) const
319     {
320         return *this;
321     }
322 
323     /// \copydoc boost::heap::priority_queue::swap
swap(fibonacci_heap & rhs)324     void swap(fibonacci_heap & rhs)
325     {
326         super_t::swap(rhs);
327         std::swap(top_element, rhs.top_element);
328         roots.swap(rhs.roots);
329     }
330 
331 
332     /// \copydoc boost::heap::priority_queue::top
top(void) const333     value_type const & top(void) const
334     {
335         BOOST_ASSERT(!empty());
336 
337         return super_t::get_value(top_element->value);
338     }
339 
340     /**
341      * \b Effects: Adds a new element to the priority queue. Returns handle to element
342      *
343      * \b Complexity: Constant.
344      *
345      * \b Note: Does not invalidate iterators.
346      *
347      * */
push(value_type const & v)348     handle_type push(value_type const & v)
349     {
350         size_holder::increment();
351 
352         allocator_type& alloc = *this;
353         node_pointer n = alloc.allocate(1);
354         new(n) node(super_t::make_node(v));
355         roots.push_front(*n);
356 
357         if (!top_element || super_t::operator()(top_element->value, n->value))
358             top_element = n;
359         return handle_type(n);
360     }
361 
362 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
363     /**
364      * \b Effects: Adds a new element to the priority queue. The element is directly constructed in-place. Returns handle to element.
365      *
366      * \b Complexity: Constant.
367      *
368      * \b Note: Does not invalidate iterators.
369      *
370      * */
371     template <class... Args>
emplace(Args &&...args)372     handle_type emplace(Args&&... args)
373     {
374         size_holder::increment();
375 
376         allocator_type& alloc = *this;
377         node_pointer n = alloc.allocate(1);
378         new(n) node(super_t::make_node(std::forward<Args>(args)...));
379         roots.push_front(*n);
380 
381         if (!top_element || super_t::operator()(top_element->value, n->value))
382             top_element = n;
383         return handle_type(n);
384     }
385 #endif
386 
387     /**
388      * \b Effects: Removes the top element from the priority queue.
389      *
390      * \b Complexity: Logarithmic (amortized). Linear (worst case).
391      *
392      * */
pop(void)393     void pop(void)
394     {
395         BOOST_ASSERT(!empty());
396 
397         node_pointer element = top_element;
398         roots.erase(node_list_type::s_iterator_to(*element));
399 
400         finish_erase_or_pop(element);
401     }
402 
403     /**
404      * \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
405      *
406      * \b Complexity: Logarithmic if current value < v, Constant otherwise.
407      *
408      * */
update(handle_type handle,const_reference v)409     void update (handle_type handle, const_reference v)
410     {
411         if (super_t::operator()(super_t::get_value(handle.node_->value), v))
412             increase(handle, v);
413         else
414             decrease(handle, v);
415     }
416 
417     /** \copydoc boost::heap::fibonacci_heap::update(handle_type, const_reference)
418      *
419      * \b Rationale: The lazy update function is a modification of the traditional update, that just invalidates
420      *               the iterator to the object referred to by the handle.
421      * */
update_lazy(handle_type handle,const_reference v)422     void update_lazy(handle_type handle, const_reference v)
423     {
424         handle.node_->value = super_t::make_node(v);
425         update_lazy(handle);
426     }
427 
428     /**
429      * \b Effects: Updates the heap after the element handled by \c handle has been changed.
430      *
431      * \b Complexity: Logarithmic.
432      *
433      * \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
434      * */
update(handle_type handle)435     void update (handle_type handle)
436     {
437         update_lazy(handle);
438         consolidate();
439     }
440 
441     /** \copydoc boost::heap::fibonacci_heap::update (handle_type handle)
442      *
443      * \b Rationale: The lazy update function is a modification of the traditional update, that just invalidates
444      *               the iterator to the object referred to by the handle.
445      * */
update_lazy(handle_type handle)446     void update_lazy (handle_type handle)
447     {
448         node_pointer n = handle.node_;
449         node_pointer parent = n->get_parent();
450 
451         if (parent) {
452             n->parent = NULL;
453             roots.splice(roots.begin(), parent->children, node_list_type::s_iterator_to(*n));
454         }
455         add_children_to_root(n);
456 
457         if (super_t::operator()(top_element->value, n->value))
458             top_element = n;
459     }
460 
461 
462      /**
463      * \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
464      *
465      * \b Complexity: Constant.
466      *
467      * \b Note: The new value is expected to be greater than the current one
468      * */
increase(handle_type handle,const_reference v)469     void increase (handle_type handle, const_reference v)
470     {
471         handle.node_->value = super_t::make_node(v);
472         increase(handle);
473     }
474 
475     /**
476      * \b Effects: Updates the heap after the element handled by \c handle has been changed.
477      *
478      * \b Complexity: Constant.
479      *
480      * \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
481      * */
increase(handle_type handle)482     void increase (handle_type handle)
483     {
484         node_pointer n = handle.node_;
485 
486         if (n->parent) {
487             if (super_t::operator()(n->get_parent()->value, n->value)) {
488                 node_pointer parent = n->get_parent();
489                 cut(n);
490                 cascading_cut(parent);
491             }
492         }
493 
494         if (super_t::operator()(top_element->value, n->value)) {
495             top_element = n;
496             return;
497         }
498     }
499 
500     /**
501      * \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
502      *
503      * \b Complexity: Logarithmic.
504      *
505      * \b Note: The new value is expected to be less than the current one
506      * */
decrease(handle_type handle,const_reference v)507     void decrease (handle_type handle, const_reference v)
508     {
509         handle.node_->value = super_t::make_node(v);
510         decrease(handle);
511     }
512 
513     /**
514      * \b Effects: Updates the heap after the element handled by \c handle has been changed.
515      *
516      * \b Complexity: Logarithmic.
517      *
518      * \b Note: The new value is expected to be less than the current one. If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
519      * */
decrease(handle_type handle)520     void decrease (handle_type handle)
521     {
522         update(handle);
523     }
524 
525     /**
526      * \b Effects: Removes the element handled by \c handle from the priority_queue.
527      *
528      * \b Complexity: Logarithmic.
529      * */
erase(handle_type const & handle)530     void erase(handle_type const & handle)
531     {
532         node_pointer element = handle.node_;
533         node_pointer parent = element->get_parent();
534 
535         if (parent)
536             parent->children.erase(node_list_type::s_iterator_to(*element));
537         else
538             roots.erase(node_list_type::s_iterator_to(*element));
539 
540         finish_erase_or_pop(element);
541     }
542 
543     /// \copydoc boost::heap::priority_queue::begin
begin(void) const544     iterator begin(void) const
545     {
546         return iterator(roots.begin());
547     }
548 
549     /// \copydoc boost::heap::priority_queue::end
end(void) const550     iterator end(void) const
551     {
552         return iterator(roots.end());
553     }
554 
555 
556     /**
557      * \b Effects: Returns an ordered iterator to the first element contained in the priority queue.
558      *
559      * \b Note: Ordered iterators traverse the priority queue in heap order.
560      * */
ordered_begin(void) const561     ordered_iterator ordered_begin(void) const
562     {
563         return ordered_iterator(roots.begin(), roots.end(), top_element, super_t::value_comp());
564     }
565 
566     /**
567      * \b Effects: Returns an ordered iterator to the end of the priority queue.
568      *
569      * \b Note: Ordered iterators traverse the priority queue in heap order.
570      * */
ordered_end(void) const571     ordered_iterator ordered_end(void) const
572     {
573         return ordered_iterator(NULL, super_t::value_comp());
574     }
575 
576     /**
577      * \b Effects: Merge with priority queue rhs.
578      *
579      * \b Complexity: Constant.
580      *
581      * */
merge(fibonacci_heap & rhs)582     void merge(fibonacci_heap & rhs)
583     {
584         size_holder::add(rhs.get_size());
585 
586         if (!top_element ||
587             (rhs.top_element && super_t::operator()(top_element->value, rhs.top_element->value)))
588             top_element = rhs.top_element;
589 
590         roots.splice(roots.end(), rhs.roots);
591 
592         rhs.top_element = NULL;
593         rhs.set_size(0);
594 
595         super_t::set_stability_count((std::max)(super_t::get_stability_count(),
596                                      rhs.get_stability_count()));
597         rhs.set_stability_count(0);
598     }
599 
600     /// \copydoc boost::heap::d_ary_heap_mutable::s_handle_from_iterator
s_handle_from_iterator(iterator const & it)601     static handle_type s_handle_from_iterator(iterator const & it)
602     {
603         node * ptr = const_cast<node *>(it.get_node());
604         return handle_type(ptr);
605     }
606 
607     /// \copydoc boost::heap::priority_queue::value_comp
value_comp(void) const608     value_compare const & value_comp(void) const
609     {
610         return super_t::value_comp();
611     }
612 
613     /// \copydoc boost::heap::priority_queue::operator<(HeapType const & rhs) const
614     template <typename HeapType>
operator <(HeapType const & rhs) const615     bool operator<(HeapType const & rhs) const
616     {
617         return detail::heap_compare(*this, rhs);
618     }
619 
620     /// \copydoc boost::heap::priority_queue::operator>(HeapType const & rhs) const
621     template <typename HeapType>
operator >(HeapType const & rhs) const622     bool operator>(HeapType const & rhs) const
623     {
624         return detail::heap_compare(rhs, *this);
625     }
626 
627     /// \copydoc boost::heap::priority_queue::operator>=(HeapType const & rhs) const
628     template <typename HeapType>
operator >=(HeapType const & rhs) const629     bool operator>=(HeapType const & rhs) const
630     {
631         return !operator<(rhs);
632     }
633 
634     /// \copydoc boost::heap::priority_queue::operator<=(HeapType const & rhs) const
635     template <typename HeapType>
operator <=(HeapType const & rhs) const636     bool operator<=(HeapType const & rhs) const
637     {
638         return !operator>(rhs);
639     }
640 
641     /// \copydoc boost::heap::priority_queue::operator==(HeapType const & rhs) const
642     template <typename HeapType>
operator ==(HeapType const & rhs) const643     bool operator==(HeapType const & rhs) const
644     {
645         return detail::heap_equality(*this, rhs);
646     }
647 
648     /// \copydoc boost::heap::priority_queue::operator!=(HeapType const & rhs) const
649     template <typename HeapType>
operator !=(HeapType const & rhs) const650     bool operator!=(HeapType const & rhs) const
651     {
652         return !(*this == rhs);
653     }
654 
655 private:
656 #if !defined(BOOST_DOXYGEN_INVOKED)
clone_forest(fibonacci_heap const & rhs)657     void clone_forest(fibonacci_heap const & rhs)
658     {
659         BOOST_HEAP_ASSERT(roots.empty());
660         typedef typename node::template node_cloner<allocator_type> node_cloner;
661         roots.clone_from(rhs.roots, node_cloner(*this, NULL), detail::nop_disposer());
662 
663         top_element = detail::find_max_child<node_list_type, node, internal_compare>(roots, super_t::get_internal_cmp());
664     }
665 
cut(node_pointer n)666     void cut(node_pointer n)
667     {
668         node_pointer parent = n->get_parent();
669         roots.splice(roots.begin(), parent->children, node_list_type::s_iterator_to(*n));
670         n->parent = 0;
671         n->mark = false;
672     }
673 
cascading_cut(node_pointer n)674     void cascading_cut(node_pointer n)
675     {
676         node_pointer parent = n->get_parent();
677 
678         if (parent) {
679             if (!parent->mark)
680                 parent->mark = true;
681             else {
682                 cut(n);
683                 cascading_cut(parent);
684             }
685         }
686     }
687 
add_children_to_root(node_pointer n)688     void add_children_to_root(node_pointer n)
689     {
690         for (node_list_iterator it = n->children.begin(); it != n->children.end(); ++it) {
691             node_pointer child = static_cast<node_pointer>(&*it);
692             child->parent = 0;
693         }
694 
695         roots.splice(roots.end(), n->children);
696     }
697 
consolidate(void)698     void consolidate(void)
699     {
700         if (roots.empty())
701             return;
702 
703         static const size_type max_log2 = sizeof(size_type) * 8;
704         boost::array<node_pointer, max_log2> aux;
705         aux.assign(NULL);
706 
707         node_list_iterator it = roots.begin();
708         top_element = static_cast<node_pointer>(&*it);
709 
710         do {
711             node_pointer n = static_cast<node_pointer>(&*it);
712             ++it;
713             size_type node_rank = n->child_count();
714 
715             if (aux[node_rank] == NULL)
716                 aux[node_rank] = n;
717             else {
718                 do {
719                     node_pointer other = aux[node_rank];
720                     if (super_t::operator()(n->value, other->value))
721                         std::swap(n, other);
722 
723                     if (other->parent)
724                         n->children.splice(n->children.end(), other->parent->children, node_list_type::s_iterator_to(*other));
725                     else
726                         n->children.splice(n->children.end(), roots, node_list_type::s_iterator_to(*other));
727 
728                     other->parent = n;
729 
730                     aux[node_rank] = NULL;
731                     node_rank = n->child_count();
732                 } while (aux[node_rank] != NULL);
733                 aux[node_rank] = n;
734             }
735 
736             if (!super_t::operator()(n->value, top_element->value))
737                 top_element = n;
738         }
739         while (it != roots.end());
740     }
741 
finish_erase_or_pop(node_pointer erased_node)742     void finish_erase_or_pop(node_pointer erased_node)
743     {
744         add_children_to_root(erased_node);
745 
746         erased_node->~node();
747         allocator_type& alloc = *this;
748         alloc.deallocate(erased_node, 1);
749 
750         size_holder::decrement();
751         if (!empty())
752             consolidate();
753         else
754             top_element = NULL;
755     }
756 
757     mutable node_pointer top_element;
758     node_list_type roots;
759 #endif
760 };
761 
762 } /* namespace heap */
763 } /* namespace boost */
764 
765 #undef BOOST_HEAP_ASSERT
766 
767 #endif /* BOOST_HEAP_FIBONACCI_HEAP_HPP */
768