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