annotate DEPENDENCIES/generic/include/boost/heap/binomial_heap.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // boost heap: binomial heap
Chris@16 2 //
Chris@16 3 // Copyright (C) 2010 Tim Blechmann
Chris@16 4 //
Chris@16 5 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 6 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 7 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 8
Chris@16 9 #ifndef BOOST_HEAP_BINOMIAL_HEAP_HPP
Chris@16 10 #define BOOST_HEAP_BINOMIAL_HEAP_HPP
Chris@16 11
Chris@16 12 #include <algorithm>
Chris@16 13 #include <utility>
Chris@16 14 #include <vector>
Chris@16 15
Chris@16 16 #include <boost/assert.hpp>
Chris@16 17
Chris@16 18 #include <boost/heap/detail/heap_comparison.hpp>
Chris@16 19 #include <boost/heap/detail/heap_node.hpp>
Chris@16 20 #include <boost/heap/detail/stable_heap.hpp>
Chris@16 21 #include <boost/heap/detail/tree_iterator.hpp>
Chris@16 22
Chris@101 23 #ifdef BOOST_HAS_PRAGMA_ONCE
Chris@101 24 #pragma once
Chris@101 25 #endif
Chris@101 26
Chris@16 27 #ifndef BOOST_DOXYGEN_INVOKED
Chris@16 28 #ifdef BOOST_HEAP_SANITYCHECKS
Chris@16 29 #define BOOST_HEAP_ASSERT BOOST_ASSERT
Chris@16 30 #else
Chris@16 31 #define BOOST_HEAP_ASSERT(expression)
Chris@16 32 #endif
Chris@16 33 #endif
Chris@16 34
Chris@16 35 namespace boost {
Chris@16 36 namespace heap {
Chris@16 37 namespace detail {
Chris@16 38
Chris@16 39 typedef parameter::parameters<boost::parameter::optional<tag::allocator>,
Chris@16 40 boost::parameter::optional<tag::compare>,
Chris@16 41 boost::parameter::optional<tag::stable>,
Chris@16 42 boost::parameter::optional<tag::constant_time_size>,
Chris@16 43 boost::parameter::optional<tag::stability_counter_type>
Chris@16 44 > binomial_heap_signature;
Chris@16 45
Chris@16 46 template <typename T, typename Parspec>
Chris@16 47 struct make_binomial_heap_base
Chris@16 48 {
Chris@16 49 static const bool constant_time_size = parameter::binding<Parspec,
Chris@16 50 tag::constant_time_size,
Chris@16 51 boost::mpl::true_
Chris@16 52 >::type::value;
Chris@16 53 typedef typename detail::make_heap_base<T, Parspec, constant_time_size>::type base_type;
Chris@16 54 typedef typename detail::make_heap_base<T, Parspec, constant_time_size>::allocator_argument allocator_argument;
Chris@16 55 typedef typename detail::make_heap_base<T, Parspec, constant_time_size>::compare_argument compare_argument;
Chris@16 56
Chris@16 57 typedef parent_pointing_heap_node<typename base_type::internal_type> node_type;
Chris@16 58
Chris@16 59 typedef typename allocator_argument::template rebind<node_type>::other allocator_type;
Chris@16 60
Chris@16 61 struct type:
Chris@16 62 base_type,
Chris@16 63 allocator_type
Chris@16 64 {
Chris@16 65 type(compare_argument const & arg):
Chris@16 66 base_type(arg)
Chris@16 67 {}
Chris@16 68
Chris@16 69 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 70 type(type const & rhs):
Chris@16 71 base_type(rhs), allocator_type(rhs)
Chris@16 72 {}
Chris@16 73
Chris@16 74 type(type && rhs):
Chris@16 75 base_type(std::move(static_cast<base_type&>(rhs))),
Chris@16 76 allocator_type(std::move(static_cast<allocator_type&>(rhs)))
Chris@16 77 {}
Chris@16 78
Chris@16 79 type & operator=(type && rhs)
Chris@16 80 {
Chris@16 81 base_type::operator=(std::move(static_cast<base_type&>(rhs)));
Chris@16 82 allocator_type::operator=(std::move(static_cast<allocator_type&>(rhs)));
Chris@16 83 return *this;
Chris@16 84 }
Chris@16 85
Chris@16 86 type & operator=(type const & rhs)
Chris@16 87 {
Chris@16 88 base_type::operator=(static_cast<base_type const &>(rhs));
Chris@16 89 allocator_type::operator=(static_cast<allocator_type const &>(rhs));
Chris@16 90 return *this;
Chris@16 91 }
Chris@16 92 #endif
Chris@16 93 };
Chris@16 94 };
Chris@16 95
Chris@16 96 }
Chris@16 97
Chris@16 98 /**
Chris@16 99 * \class binomial_heap
Chris@16 100 * \brief binomial heap
Chris@16 101 *
Chris@16 102 * The template parameter T is the type to be managed by the container.
Chris@16 103 * The user can specify additional options and if no options are provided default options are used.
Chris@16 104 *
Chris@16 105 * The container supports the following options:
Chris@16 106 * - \c boost::heap::stable<>, defaults to \c stable<false>
Chris@16 107 * - \c boost::heap::compare<>, defaults to \c compare<std::less<T> >
Chris@16 108 * - \c boost::heap::allocator<>, defaults to \c allocator<std::allocator<T> >
Chris@16 109 * - \c boost::heap::constant_time_size<>, defaults to \c constant_time_size<true>
Chris@16 110 * - \c boost::heap::stability_counter_type<>, defaults to \c stability_counter_type<boost::uintmax_t>
Chris@16 111 *
Chris@16 112 */
Chris@16 113 #ifdef BOOST_DOXYGEN_INVOKED
Chris@16 114 template<class T, class ...Options>
Chris@16 115 #else
Chris@16 116 template <typename T,
Chris@16 117 class A0 = boost::parameter::void_,
Chris@16 118 class A1 = boost::parameter::void_,
Chris@16 119 class A2 = boost::parameter::void_,
Chris@16 120 class A3 = boost::parameter::void_
Chris@16 121 >
Chris@16 122 #endif
Chris@16 123 class binomial_heap:
Chris@16 124 private detail::make_binomial_heap_base<T,
Chris@16 125 typename detail::binomial_heap_signature::bind<A0, A1, A2, A3>::type
Chris@16 126 >::type
Chris@16 127 {
Chris@16 128 typedef typename detail::binomial_heap_signature::bind<A0, A1, A2, A3>::type bound_args;
Chris@16 129 typedef detail::make_binomial_heap_base<T, bound_args> base_maker;
Chris@16 130 typedef typename base_maker::type super_t;
Chris@16 131
Chris@16 132 typedef typename super_t::internal_type internal_type;
Chris@16 133 typedef typename super_t::size_holder_type size_holder;
Chris@101 134 typedef typename super_t::stability_counter_type stability_counter_type;
Chris@16 135 typedef typename base_maker::allocator_argument allocator_argument;
Chris@16 136
Chris@16 137 template <typename Heap1, typename Heap2>
Chris@16 138 friend struct heap_merge_emulate;
Chris@16 139
Chris@16 140 public:
Chris@16 141 static const bool constant_time_size = super_t::constant_time_size;
Chris@16 142 static const bool has_ordered_iterators = true;
Chris@16 143 static const bool is_mergable = true;
Chris@16 144 static const bool is_stable = detail::extract_stable<bound_args>::value;
Chris@16 145 static const bool has_reserve = false;
Chris@16 146
Chris@16 147 private:
Chris@16 148 #ifndef BOOST_DOXYGEN_INVOKED
Chris@16 149 struct implementation_defined:
Chris@16 150 detail::extract_allocator_types<typename base_maker::allocator_argument>
Chris@16 151 {
Chris@16 152 typedef T value_type;
Chris@16 153 typedef typename detail::extract_allocator_types<typename base_maker::allocator_argument>::size_type size_type;
Chris@16 154 typedef typename detail::extract_allocator_types<typename base_maker::allocator_argument>::reference reference;
Chris@16 155
Chris@16 156 typedef typename base_maker::compare_argument value_compare;
Chris@16 157 typedef typename base_maker::allocator_type allocator_type;
Chris@16 158 typedef typename base_maker::node_type node;
Chris@16 159
Chris@16 160 typedef typename allocator_type::pointer node_pointer;
Chris@16 161 typedef typename allocator_type::const_pointer const_node_pointer;
Chris@16 162
Chris@16 163 typedef detail::node_handle<node_pointer, super_t, reference> handle_type;
Chris@16 164
Chris@16 165 typedef typename base_maker::node_type node_type;
Chris@16 166
Chris@16 167 typedef boost::intrusive::list<detail::heap_node_base<false>,
Chris@16 168 boost::intrusive::constant_time_size<true>
Chris@16 169 > node_list_type;
Chris@16 170
Chris@16 171 typedef typename node_list_type::iterator node_list_iterator;
Chris@16 172 typedef typename node_list_type::const_iterator node_list_const_iterator;
Chris@16 173 typedef detail::value_extractor<value_type, internal_type, super_t> value_extractor;
Chris@16 174
Chris@16 175 typedef detail::recursive_tree_iterator<node_type,
Chris@16 176 node_list_const_iterator,
Chris@16 177 const value_type,
Chris@16 178 value_extractor,
Chris@16 179 detail::list_iterator_converter<node_type, node_list_type>
Chris@16 180 > iterator;
Chris@16 181 typedef iterator const_iterator;
Chris@16 182
Chris@16 183 typedef detail::tree_iterator<node_type,
Chris@16 184 const value_type,
Chris@16 185 allocator_type,
Chris@16 186 value_extractor,
Chris@16 187 detail::list_iterator_converter<node_type, node_list_type>,
Chris@16 188 true,
Chris@16 189 true,
Chris@16 190 value_compare
Chris@16 191 > ordered_iterator;
Chris@16 192 };
Chris@16 193 #endif
Chris@16 194
Chris@16 195 public:
Chris@16 196 typedef T value_type;
Chris@16 197
Chris@16 198 typedef typename implementation_defined::size_type size_type;
Chris@16 199 typedef typename implementation_defined::difference_type difference_type;
Chris@16 200 typedef typename implementation_defined::value_compare value_compare;
Chris@16 201 typedef typename implementation_defined::allocator_type allocator_type;
Chris@16 202 typedef typename implementation_defined::reference reference;
Chris@16 203 typedef typename implementation_defined::const_reference const_reference;
Chris@16 204 typedef typename implementation_defined::pointer pointer;
Chris@16 205 typedef typename implementation_defined::const_pointer const_pointer;
Chris@16 206 /// \copydoc boost::heap::priority_queue::iterator
Chris@16 207 typedef typename implementation_defined::iterator iterator;
Chris@16 208 typedef typename implementation_defined::const_iterator const_iterator;
Chris@16 209 typedef typename implementation_defined::ordered_iterator ordered_iterator;
Chris@16 210
Chris@16 211 typedef typename implementation_defined::handle_type handle_type;
Chris@16 212
Chris@16 213 private:
Chris@16 214 typedef typename implementation_defined::node_type node_type;
Chris@16 215 typedef typename implementation_defined::node_list_type node_list_type;
Chris@16 216 typedef typename implementation_defined::node_pointer node_pointer;
Chris@16 217 typedef typename implementation_defined::const_node_pointer const_node_pointer;
Chris@16 218 typedef typename implementation_defined::node_list_iterator node_list_iterator;
Chris@16 219 typedef typename implementation_defined::node_list_const_iterator node_list_const_iterator;
Chris@16 220
Chris@16 221 typedef typename super_t::internal_compare internal_compare;
Chris@16 222
Chris@16 223 public:
Chris@16 224 /// \copydoc boost::heap::priority_queue::priority_queue(value_compare const &)
Chris@16 225 explicit binomial_heap(value_compare const & cmp = value_compare()):
Chris@16 226 super_t(cmp), top_element(0)
Chris@16 227 {}
Chris@16 228
Chris@16 229 /// \copydoc boost::heap::priority_queue::priority_queue(priority_queue const &)
Chris@16 230 binomial_heap(binomial_heap const & rhs):
Chris@16 231 super_t(rhs), top_element(0)
Chris@16 232 {
Chris@16 233 if (rhs.empty())
Chris@16 234 return;
Chris@16 235
Chris@16 236 clone_forest(rhs);
Chris@16 237 size_holder::set_size(rhs.get_size());
Chris@16 238 }
Chris@16 239
Chris@16 240 /// \copydoc boost::heap::priority_queue::operator=(priority_queue const &)
Chris@16 241 binomial_heap & operator=(binomial_heap const & rhs)
Chris@16 242 {
Chris@16 243 clear();
Chris@16 244 size_holder::set_size(rhs.get_size());
Chris@16 245 static_cast<super_t&>(*this) = rhs;
Chris@16 246
Chris@16 247 if (rhs.empty())
Chris@16 248 top_element = NULL;
Chris@16 249 else
Chris@16 250 clone_forest(rhs);
Chris@16 251 return *this;
Chris@16 252 }
Chris@16 253
Chris@16 254 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 255 /// \copydoc boost::heap::priority_queue::priority_queue(priority_queue &&)
Chris@16 256 binomial_heap(binomial_heap && rhs):
Chris@16 257 super_t(std::move(rhs)), top_element(rhs.top_element)
Chris@16 258 {
Chris@16 259 trees.splice(trees.begin(), rhs.trees);
Chris@16 260 rhs.top_element = NULL;
Chris@16 261 }
Chris@16 262
Chris@16 263 /// \copydoc boost::heap::priority_queue::operator=(priority_queue &&)
Chris@16 264 binomial_heap & operator=(binomial_heap && rhs)
Chris@16 265 {
Chris@16 266 clear();
Chris@16 267 super_t::operator=(std::move(rhs));
Chris@16 268 trees.splice(trees.begin(), rhs.trees);
Chris@16 269 top_element = rhs.top_element;
Chris@16 270 rhs.top_element = NULL;
Chris@16 271 return *this;
Chris@16 272 }
Chris@16 273 #endif
Chris@16 274
Chris@16 275 ~binomial_heap(void)
Chris@16 276 {
Chris@16 277 clear();
Chris@16 278 }
Chris@16 279
Chris@16 280 /// \copydoc boost::heap::priority_queue::empty
Chris@16 281 bool empty(void) const
Chris@16 282 {
Chris@16 283 return top_element == NULL;
Chris@16 284 }
Chris@16 285
Chris@16 286 /**
Chris@16 287 * \b Effects: Returns the number of elements contained in the priority queue.
Chris@16 288 *
Chris@16 289 * \b Complexity: Constant, if configured with constant_time_size<true>, otherwise linear.
Chris@16 290 *
Chris@16 291 * */
Chris@16 292 size_type size(void) const
Chris@16 293 {
Chris@16 294 if (constant_time_size)
Chris@16 295 return size_holder::get_size();
Chris@16 296
Chris@16 297 if (empty())
Chris@16 298 return 0;
Chris@16 299 else
Chris@16 300 return detail::count_list_nodes<node_type, node_list_type>(trees);
Chris@16 301 }
Chris@16 302
Chris@16 303 /// \copydoc boost::heap::priority_queue::max_size
Chris@16 304 size_type max_size(void) const
Chris@16 305 {
Chris@16 306 return allocator_type::max_size();
Chris@16 307 }
Chris@16 308
Chris@16 309 /// \copydoc boost::heap::priority_queue::clear
Chris@16 310 void clear(void)
Chris@16 311 {
Chris@16 312 typedef detail::node_disposer<node_type, typename node_list_type::value_type, allocator_type> disposer;
Chris@16 313 trees.clear_and_dispose(disposer(*this));
Chris@16 314
Chris@16 315 size_holder::set_size(0);
Chris@16 316 top_element = NULL;
Chris@16 317 }
Chris@16 318
Chris@16 319 /// \copydoc boost::heap::priority_queue::get_allocator
Chris@16 320 allocator_type get_allocator(void) const
Chris@16 321 {
Chris@16 322 return *this;
Chris@16 323 }
Chris@16 324
Chris@16 325 /// \copydoc boost::heap::priority_queue::swap
Chris@16 326 void swap(binomial_heap & rhs)
Chris@16 327 {
Chris@16 328 super_t::swap(rhs);
Chris@16 329 std::swap(top_element, rhs.top_element);
Chris@16 330 trees.swap(rhs.trees);
Chris@16 331 }
Chris@16 332
Chris@16 333 /// \copydoc boost::heap::priority_queue::top
Chris@16 334 const_reference top(void) const
Chris@16 335 {
Chris@16 336 BOOST_ASSERT(!empty());
Chris@16 337
Chris@16 338 return super_t::get_value(top_element->value);
Chris@16 339 }
Chris@16 340
Chris@16 341 /**
Chris@16 342 * \b Effects: Adds a new element to the priority queue. Returns handle to element
Chris@16 343 *
Chris@16 344 * \b Complexity: Logarithmic.
Chris@16 345 *
Chris@16 346 * */
Chris@16 347 handle_type push(value_type const & v)
Chris@16 348 {
Chris@16 349 node_pointer n = allocator_type::allocate(1);
Chris@16 350 new(n) node_type(super_t::make_node(v));
Chris@16 351
Chris@16 352 insert_node(trees.begin(), n);
Chris@16 353
Chris@16 354 if (!top_element || super_t::operator()(top_element->value, n->value))
Chris@16 355 top_element = n;
Chris@16 356
Chris@16 357 size_holder::increment();
Chris@16 358 sanity_check();
Chris@16 359 return handle_type(n);
Chris@16 360 }
Chris@16 361
Chris@16 362 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
Chris@16 363 /**
Chris@16 364 * \b Effects: Adds a new element to the priority queue. The element is directly constructed in-place. Returns handle to element.
Chris@16 365 *
Chris@16 366 * \b Complexity: Logarithmic.
Chris@16 367 *
Chris@16 368 * */
Chris@16 369 template <class... Args>
Chris@16 370 handle_type emplace(Args&&... args)
Chris@16 371 {
Chris@16 372 node_pointer n = allocator_type::allocate(1);
Chris@16 373 new(n) node_type(super_t::make_node(std::forward<Args>(args)...));
Chris@16 374
Chris@16 375 insert_node(trees.begin(), n);
Chris@16 376
Chris@16 377 if (!top_element || super_t::operator()(top_element->value, n->value))
Chris@16 378 top_element = n;
Chris@16 379
Chris@16 380 size_holder::increment();
Chris@16 381 sanity_check();
Chris@16 382 return handle_type(n);
Chris@16 383 }
Chris@16 384 #endif
Chris@16 385
Chris@16 386 /**
Chris@16 387 * \b Effects: Removes the top element from the priority queue.
Chris@16 388 *
Chris@16 389 * \b Complexity: Logarithmic.
Chris@16 390 *
Chris@16 391 * */
Chris@16 392 void pop(void)
Chris@16 393 {
Chris@16 394 BOOST_ASSERT(!empty());
Chris@16 395
Chris@16 396 node_pointer element = top_element;
Chris@16 397
Chris@16 398 trees.erase(node_list_type::s_iterator_to(*element));
Chris@16 399 size_holder::decrement();
Chris@16 400
Chris@16 401 if (element->child_count()) {
Chris@16 402 size_type sz = (1 << element->child_count()) - 1;
Chris@101 403
Chris@16 404 binomial_heap children(value_comp(), element->children, sz);
Chris@101 405 if (trees.empty()) {
Chris@101 406 stability_counter_type stability_count = super_t::get_stability_count();
Chris@16 407 swap(children);
Chris@101 408 super_t::set_stability_count(stability_count);
Chris@101 409 } else
Chris@16 410 merge_and_clear_nodes(children);
Chris@101 411
Chris@16 412 }
Chris@16 413
Chris@16 414 if (trees.empty())
Chris@16 415 top_element = NULL;
Chris@16 416 else
Chris@16 417 update_top_element();
Chris@16 418
Chris@16 419 element->~node_type();
Chris@16 420 allocator_type::deallocate(element, 1);
Chris@16 421 sanity_check();
Chris@16 422 }
Chris@16 423
Chris@16 424 /**
Chris@16 425 * \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
Chris@16 426 *
Chris@16 427 * \b Complexity: Logarithmic.
Chris@16 428 *
Chris@16 429 * */
Chris@16 430 void update (handle_type handle, const_reference v)
Chris@16 431 {
Chris@16 432 if (super_t::operator()(super_t::get_value(handle.node_->value), v))
Chris@16 433 increase(handle, v);
Chris@16 434 else
Chris@16 435 decrease(handle, v);
Chris@16 436 }
Chris@16 437
Chris@16 438 /**
Chris@16 439 * \b Effects: Updates the heap after the element handled by \c handle has been changed.
Chris@16 440 *
Chris@16 441 * \b Complexity: Logarithmic.
Chris@16 442 *
Chris@16 443 * \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
Chris@16 444 * */
Chris@16 445 void update (handle_type handle)
Chris@16 446 {
Chris@16 447 node_pointer this_node = handle.node_;
Chris@16 448
Chris@16 449 if (this_node->parent) {
Chris@16 450 if (super_t::operator()(super_t::get_value(this_node->parent->value), super_t::get_value(this_node->value)))
Chris@16 451 increase(handle);
Chris@16 452 else
Chris@16 453 decrease(handle);
Chris@16 454 }
Chris@16 455 else
Chris@16 456 decrease(handle);
Chris@16 457 }
Chris@16 458
Chris@16 459 /**
Chris@16 460 * \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
Chris@16 461 *
Chris@16 462 * \b Complexity: Logarithmic.
Chris@16 463 *
Chris@16 464 * \b Note: The new value is expected to be greater than the current one
Chris@16 465 * */
Chris@16 466 void increase (handle_type handle, const_reference v)
Chris@16 467 {
Chris@16 468 handle.node_->value = super_t::make_node(v);
Chris@16 469 increase(handle);
Chris@16 470 }
Chris@16 471
Chris@16 472 /**
Chris@16 473 * \b Effects: Updates the heap after the element handled by \c handle has been changed.
Chris@16 474 *
Chris@16 475 * \b Complexity: Logarithmic.
Chris@16 476 *
Chris@16 477 * \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
Chris@16 478 * */
Chris@16 479 void increase (handle_type handle)
Chris@16 480 {
Chris@16 481 node_pointer n = handle.node_;
Chris@16 482 siftup(n, *this);
Chris@16 483
Chris@16 484 update_top_element();
Chris@16 485 sanity_check();
Chris@16 486 }
Chris@16 487
Chris@16 488 /**
Chris@16 489 * \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
Chris@16 490 *
Chris@16 491 * \b Complexity: Logarithmic.
Chris@16 492 *
Chris@16 493 * \b Note: The new value is expected to be less than the current one
Chris@16 494 * */
Chris@16 495 void decrease (handle_type handle, const_reference v)
Chris@16 496 {
Chris@16 497 handle.node_->value = super_t::make_node(v);
Chris@16 498 decrease(handle);
Chris@16 499 }
Chris@16 500
Chris@16 501 /**
Chris@16 502 * \b Effects: Updates the heap after the element handled by \c handle has been changed.
Chris@16 503 *
Chris@16 504 * \b Complexity: Logarithmic.
Chris@16 505 *
Chris@16 506 * \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!
Chris@16 507 * */
Chris@16 508 void decrease (handle_type handle)
Chris@16 509 {
Chris@16 510 node_pointer n = handle.node_;
Chris@16 511
Chris@16 512 siftdown(n);
Chris@16 513
Chris@16 514 if (n == top_element)
Chris@16 515 update_top_element();
Chris@16 516 }
Chris@16 517
Chris@16 518 /**
Chris@16 519 * \b Effects: Merge with priority queue rhs.
Chris@16 520 *
Chris@16 521 * \b Complexity: Logarithmic.
Chris@16 522 *
Chris@16 523 * */
Chris@16 524 void merge(binomial_heap & rhs)
Chris@16 525 {
Chris@16 526 if (rhs.empty())
Chris@16 527 return;
Chris@16 528
Chris@16 529 if (empty()) {
Chris@16 530 swap(rhs);
Chris@16 531 return;
Chris@16 532 }
Chris@16 533
Chris@16 534 size_type new_size = size_holder::get_size() + rhs.get_size();
Chris@16 535 merge_and_clear_nodes(rhs);
Chris@16 536
Chris@16 537 size_holder::set_size(new_size);
Chris@16 538 rhs.set_size(0);
Chris@16 539 rhs.top_element = NULL;
Chris@16 540
Chris@16 541 super_t::set_stability_count((std::max)(super_t::get_stability_count(),
Chris@16 542 rhs.get_stability_count()));
Chris@16 543 rhs.set_stability_count(0);
Chris@16 544 }
Chris@16 545
Chris@16 546 public:
Chris@16 547 /// \copydoc boost::heap::priority_queue::begin
Chris@16 548 iterator begin(void) const
Chris@16 549 {
Chris@16 550 return iterator(trees.begin());
Chris@16 551 }
Chris@16 552
Chris@16 553 /// \copydoc boost::heap::priority_queue::end
Chris@16 554 iterator end(void) const
Chris@16 555 {
Chris@16 556 return iterator(trees.end());
Chris@16 557 }
Chris@16 558
Chris@16 559 /// \copydoc boost::heap::fibonacci_heap::ordered_begin
Chris@16 560 ordered_iterator ordered_begin(void) const
Chris@16 561 {
Chris@16 562 return ordered_iterator(trees.begin(), trees.end(), top_element, super_t::value_comp());
Chris@16 563 }
Chris@16 564
Chris@16 565 /// \copydoc boost::heap::fibonacci_heap::ordered_end
Chris@16 566 ordered_iterator ordered_end(void) const
Chris@16 567 {
Chris@16 568 return ordered_iterator(NULL, super_t::value_comp());
Chris@16 569 }
Chris@16 570
Chris@16 571 /**
Chris@16 572 * \b Effects: Removes the element handled by \c handle from the priority_queue.
Chris@16 573 *
Chris@16 574 * \b Complexity: Logarithmic.
Chris@16 575 * */
Chris@16 576 void erase(handle_type handle)
Chris@16 577 {
Chris@16 578 node_pointer n = handle.node_;
Chris@16 579 siftup(n, force_inf());
Chris@16 580 top_element = n;
Chris@16 581 pop();
Chris@16 582 }
Chris@16 583
Chris@16 584 /// \copydoc boost::heap::d_ary_heap_mutable::s_handle_from_iterator
Chris@16 585 static handle_type s_handle_from_iterator(iterator const & it)
Chris@16 586 {
Chris@16 587 node_type * ptr = const_cast<node_type *>(it.get_node());
Chris@16 588 return handle_type(ptr);
Chris@16 589 }
Chris@16 590
Chris@16 591 /// \copydoc boost::heap::priority_queue::value_comp
Chris@16 592 value_compare const & value_comp(void) const
Chris@16 593 {
Chris@16 594 return super_t::value_comp();
Chris@16 595 }
Chris@16 596
Chris@16 597 /// \copydoc boost::heap::priority_queue::operator<(HeapType const & rhs) const
Chris@16 598 template <typename HeapType>
Chris@16 599 bool operator<(HeapType const & rhs) const
Chris@16 600 {
Chris@16 601 return detail::heap_compare(*this, rhs);
Chris@16 602 }
Chris@16 603
Chris@16 604 /// \copydoc boost::heap::priority_queue::operator>(HeapType const & rhs) const
Chris@16 605 template <typename HeapType>
Chris@16 606 bool operator>(HeapType const & rhs) const
Chris@16 607 {
Chris@16 608 return detail::heap_compare(rhs, *this);
Chris@16 609 }
Chris@16 610
Chris@16 611 /// \copydoc boost::heap::priority_queue::operator>=(HeapType const & rhs) const
Chris@16 612 template <typename HeapType>
Chris@16 613 bool operator>=(HeapType const & rhs) const
Chris@16 614 {
Chris@16 615 return !operator<(rhs);
Chris@16 616 }
Chris@16 617
Chris@16 618 /// \copydoc boost::heap::priority_queue::operator<=(HeapType const & rhs) const
Chris@16 619 template <typename HeapType>
Chris@16 620 bool operator<=(HeapType const & rhs) const
Chris@16 621 {
Chris@16 622 return !operator>(rhs);
Chris@16 623 }
Chris@16 624
Chris@16 625 /// \copydoc boost::heap::priority_queue::operator==(HeapType const & rhs) const
Chris@16 626 template <typename HeapType>
Chris@16 627 bool operator==(HeapType const & rhs) const
Chris@16 628 {
Chris@16 629 return detail::heap_equality(*this, rhs);
Chris@16 630 }
Chris@16 631
Chris@16 632 /// \copydoc boost::heap::priority_queue::operator!=(HeapType const & rhs) const
Chris@16 633 template <typename HeapType>
Chris@16 634 bool operator!=(HeapType const & rhs) const
Chris@16 635 {
Chris@16 636 return !(*this == rhs);
Chris@16 637 }
Chris@16 638
Chris@16 639 private:
Chris@16 640 #if !defined(BOOST_DOXYGEN_INVOKED)
Chris@16 641 void merge_and_clear_nodes(binomial_heap & rhs)
Chris@16 642 {
Chris@16 643 BOOST_HEAP_ASSERT (!empty());
Chris@16 644 BOOST_HEAP_ASSERT (!rhs.empty());
Chris@16 645
Chris@16 646 node_list_iterator this_iterator = trees.begin();
Chris@16 647 node_pointer carry_node = NULL;
Chris@16 648
Chris@16 649 while (!rhs.trees.empty()) {
Chris@16 650 node_pointer rhs_node = static_cast<node_pointer>(&rhs.trees.front());
Chris@16 651 size_type rhs_degree = rhs_node->child_count();
Chris@16 652
Chris@16 653 if (super_t::operator()(top_element->value, rhs_node->value))
Chris@16 654 top_element = rhs_node;
Chris@16 655
Chris@16 656 try_again:
Chris@16 657 node_pointer this_node = static_cast<node_pointer>(&*this_iterator);
Chris@16 658 size_type this_degree = this_node->child_count();
Chris@16 659 sorted_by_degree();
Chris@16 660 rhs.sorted_by_degree();
Chris@16 661
Chris@16 662 if (this_degree == rhs_degree) {
Chris@16 663 if (carry_node) {
Chris@16 664 if (carry_node->child_count() < this_degree) {
Chris@16 665 trees.insert(this_iterator, *carry_node);
Chris@16 666 carry_node = NULL;
Chris@16 667 } else {
Chris@16 668 rhs.trees.pop_front();
Chris@16 669 carry_node = merge_trees(carry_node, rhs_node);
Chris@16 670 }
Chris@16 671 ++this_iterator;
Chris@16 672 } else {
Chris@16 673 this_iterator = trees.erase(this_iterator);
Chris@16 674 rhs.trees.pop_front();
Chris@16 675 carry_node = merge_trees(this_node, rhs_node);
Chris@16 676 }
Chris@16 677
Chris@16 678 if (this_iterator == trees.end())
Chris@16 679 break;
Chris@16 680 else
Chris@16 681 continue;
Chris@16 682 }
Chris@16 683
Chris@16 684 if (this_degree < rhs_degree) {
Chris@16 685 if (carry_node) {
Chris@16 686 if (carry_node->child_count() < this_degree) {
Chris@16 687 trees.insert(this_iterator, *carry_node);
Chris@16 688 carry_node = NULL;
Chris@16 689 ++this_iterator;
Chris@16 690 } else if (carry_node->child_count() == rhs_degree) {
Chris@16 691 rhs.trees.pop_front();
Chris@16 692 carry_node = merge_trees(carry_node, rhs_node);
Chris@16 693 continue;
Chris@16 694 } else {
Chris@16 695 this_iterator = trees.erase(this_iterator);
Chris@16 696 carry_node = merge_trees(this_node, carry_node);
Chris@16 697 }
Chris@16 698 goto try_again;
Chris@16 699 } else {
Chris@16 700 ++this_iterator;
Chris@16 701 if (this_iterator == trees.end())
Chris@16 702 break;
Chris@16 703 goto try_again;
Chris@16 704 }
Chris@16 705
Chris@16 706 if (this_iterator == trees.end())
Chris@16 707 break;
Chris@16 708 else
Chris@16 709 continue;
Chris@16 710 }
Chris@16 711
Chris@16 712 if (this_degree > rhs_degree) {
Chris@16 713 rhs.trees.pop_front();
Chris@16 714 if (carry_node) {
Chris@16 715 if (carry_node->child_count() < rhs_degree) {
Chris@16 716 trees.insert(this_iterator, *carry_node);
Chris@16 717 trees.insert(this_iterator, *rhs_node);
Chris@16 718 carry_node = NULL;
Chris@16 719 } else
Chris@16 720 carry_node = merge_trees(rhs_node, carry_node);
Chris@16 721 } else
Chris@16 722 trees.insert(this_iterator, *rhs_node);
Chris@16 723 }
Chris@16 724 }
Chris@16 725
Chris@16 726 if (!rhs.trees.empty()) {
Chris@16 727 if (carry_node) {
Chris@16 728 node_list_iterator rhs_it = rhs.trees.begin();
Chris@16 729 while (static_cast<node_pointer>(&*rhs_it)->child_count() < carry_node->child_count())
Chris@16 730 ++rhs_it;
Chris@16 731 rhs.insert_node(rhs_it, carry_node);
Chris@16 732 rhs.increment();
Chris@16 733 sorted_by_degree();
Chris@16 734 rhs.sorted_by_degree();
Chris@16 735 if (trees.empty()) {
Chris@16 736 trees.splice(trees.end(), rhs.trees, rhs.trees.begin(), rhs.trees.end());
Chris@16 737 update_top_element();
Chris@16 738 } else
Chris@16 739 merge_and_clear_nodes(rhs);
Chris@16 740 } else
Chris@16 741 trees.splice(trees.end(), rhs.trees, rhs.trees.begin(), rhs.trees.end());
Chris@16 742 return;
Chris@16 743 }
Chris@16 744
Chris@16 745 if (carry_node)
Chris@16 746 insert_node(this_iterator, carry_node);
Chris@16 747 }
Chris@16 748
Chris@16 749 void clone_forest(binomial_heap const & rhs)
Chris@16 750 {
Chris@16 751 BOOST_HEAP_ASSERT(trees.empty());
Chris@16 752 typedef typename node_type::template node_cloner<allocator_type> node_cloner;
Chris@16 753 trees.clone_from(rhs.trees, node_cloner(*this, NULL), detail::nop_disposer());
Chris@16 754
Chris@16 755 update_top_element();
Chris@16 756 }
Chris@16 757
Chris@16 758 struct force_inf
Chris@16 759 {
Chris@16 760 template <typename X>
Chris@16 761 bool operator()(X const &, X const &) const
Chris@16 762 {
Chris@16 763 return false;
Chris@16 764 }
Chris@16 765 };
Chris@16 766
Chris@16 767 template <typename Compare>
Chris@16 768 void siftup(node_pointer n, Compare const & cmp)
Chris@16 769 {
Chris@16 770 while (n->parent) {
Chris@16 771 node_pointer parent = n->parent;
Chris@16 772 node_pointer grand_parent = parent->parent;
Chris@16 773 if (cmp(n->value, parent->value))
Chris@16 774 return;
Chris@16 775
Chris@16 776 n->remove_from_parent();
Chris@16 777
Chris@16 778 n->swap_children(parent);
Chris@16 779 n->update_children();
Chris@16 780 parent->update_children();
Chris@16 781
Chris@16 782 if (grand_parent) {
Chris@16 783 parent->remove_from_parent();
Chris@16 784 grand_parent->add_child(n);
Chris@16 785 } else {
Chris@16 786 node_list_iterator it = trees.erase(node_list_type::s_iterator_to(*parent));
Chris@16 787 trees.insert(it, *n);
Chris@16 788 }
Chris@16 789 n->add_child(parent);
Chris@16 790 BOOST_HEAP_ASSERT(parent->child_count() == n->child_count());
Chris@16 791 }
Chris@16 792 }
Chris@16 793
Chris@16 794 void siftdown(node_pointer n)
Chris@16 795 {
Chris@16 796 while (n->child_count()) {
Chris@16 797 node_pointer max_child = detail::find_max_child<node_list_type, node_type, internal_compare>(n->children, super_t::get_internal_cmp());
Chris@16 798
Chris@16 799 if (super_t::operator()(max_child->value, n->value))
Chris@16 800 return;
Chris@16 801
Chris@16 802 max_child->remove_from_parent();
Chris@16 803
Chris@16 804 n->swap_children(max_child);
Chris@16 805 n->update_children();
Chris@16 806 max_child->update_children();
Chris@16 807
Chris@16 808 node_pointer parent = n->parent;
Chris@16 809 if (parent) {
Chris@16 810 n->remove_from_parent();
Chris@16 811 max_child->add_child(n);
Chris@16 812 parent->add_child(max_child);
Chris@16 813 } else {
Chris@16 814 node_list_iterator position = trees.erase(node_list_type::s_iterator_to(*n));
Chris@16 815 max_child->add_child(n);
Chris@16 816 trees.insert(position, *max_child);
Chris@16 817 }
Chris@16 818 }
Chris@16 819 }
Chris@16 820
Chris@16 821 void insert_node(node_list_iterator it, node_pointer n)
Chris@16 822 {
Chris@16 823 if (it != trees.end())
Chris@16 824 BOOST_HEAP_ASSERT(static_cast<node_pointer>(&*it)->child_count() >= n->child_count());
Chris@16 825
Chris@16 826 while(true) {
Chris@16 827 BOOST_HEAP_ASSERT(!n->is_linked());
Chris@16 828 if (it == trees.end())
Chris@16 829 break;
Chris@16 830
Chris@16 831 node_pointer this_node = static_cast<node_pointer>(&*it);
Chris@16 832 size_type this_degree = this_node->child_count();
Chris@16 833 size_type n_degree = n->child_count();
Chris@16 834 if (this_degree == n_degree) {
Chris@16 835 BOOST_HEAP_ASSERT(it->is_linked());
Chris@16 836 it = trees.erase(it);
Chris@16 837
Chris@16 838 n = merge_trees(n, this_node);
Chris@16 839 } else
Chris@16 840 break;
Chris@16 841 }
Chris@16 842 trees.insert(it, *n);
Chris@16 843 }
Chris@16 844
Chris@16 845 // private constructor, just used in pop()
Chris@16 846 explicit binomial_heap(value_compare const & cmp, node_list_type & child_list, size_type size):
Chris@16 847 super_t(cmp)
Chris@16 848 {
Chris@16 849 size_holder::set_size(size);
Chris@16 850 if (size)
Chris@16 851 top_element = static_cast<node_pointer>(&*child_list.begin()); // not correct, but we will reset it later
Chris@16 852 else
Chris@16 853 top_element = NULL;
Chris@16 854
Chris@16 855 for (node_list_iterator it = child_list.begin(); it != child_list.end(); ++it) {
Chris@16 856 node_pointer n = static_cast<node_pointer>(&*it);
Chris@16 857 n->parent = NULL;
Chris@16 858 }
Chris@16 859
Chris@16 860 trees.splice(trees.end(), child_list, child_list.begin(), child_list.end());
Chris@16 861
Chris@16 862 trees.sort(detail::cmp_by_degree<node_type>());
Chris@16 863 }
Chris@16 864
Chris@16 865 node_pointer merge_trees (node_pointer node1, node_pointer node2)
Chris@16 866 {
Chris@16 867 BOOST_HEAP_ASSERT(node1->child_count() == node2->child_count());
Chris@16 868
Chris@16 869 if (super_t::operator()(node1->value, node2->value))
Chris@16 870 std::swap(node1, node2);
Chris@16 871
Chris@16 872 if (node2->parent)
Chris@16 873 node2->remove_from_parent();
Chris@16 874
Chris@16 875 node1->add_child(node2);
Chris@16 876 return node1;
Chris@16 877 }
Chris@16 878
Chris@16 879 void update_top_element(void)
Chris@16 880 {
Chris@16 881 top_element = detail::find_max_child<node_list_type, node_type, internal_compare>(trees, super_t::get_internal_cmp());
Chris@16 882 }
Chris@16 883
Chris@16 884 void sorted_by_degree(void) const
Chris@16 885 {
Chris@16 886 #ifdef BOOST_HEAP_SANITYCHECKS
Chris@16 887 int degree = -1;
Chris@16 888
Chris@16 889 for (node_list_const_iterator it = trees.begin(); it != trees.end(); ++it) {
Chris@16 890 const_node_pointer n = static_cast<const_node_pointer>(&*it);
Chris@16 891 BOOST_HEAP_ASSERT(int(n->child_count()) > degree);
Chris@16 892 degree = n->child_count();
Chris@16 893
Chris@16 894 BOOST_HEAP_ASSERT((detail::is_heap<node_type, super_t>(n, *this)));
Chris@16 895
Chris@16 896 size_type child_nodes = detail::count_nodes<node_type>(n);
Chris@16 897 BOOST_HEAP_ASSERT(child_nodes == size_type(1 << static_cast<const_node_pointer>(&*it)->child_count()));
Chris@16 898 }
Chris@16 899 #endif
Chris@16 900 }
Chris@16 901
Chris@16 902 void sanity_check(void)
Chris@16 903 {
Chris@16 904 #ifdef BOOST_HEAP_SANITYCHECKS
Chris@16 905 sorted_by_degree();
Chris@16 906
Chris@16 907 if (!empty()) {
Chris@16 908 node_pointer found_top = detail::find_max_child<node_list_type, node_type, internal_compare>(trees, super_t::get_internal_cmp());
Chris@16 909 BOOST_HEAP_ASSERT(top_element == found_top);
Chris@16 910 }
Chris@16 911
Chris@16 912 if (constant_time_size) {
Chris@16 913 size_t counted = detail::count_list_nodes<node_type, node_list_type>(trees);
Chris@16 914 size_t stored = size_holder::get_size();
Chris@16 915 BOOST_HEAP_ASSERT(counted == stored);
Chris@16 916 }
Chris@16 917 #endif
Chris@16 918 }
Chris@16 919
Chris@16 920 node_pointer top_element;
Chris@16 921 node_list_type trees;
Chris@16 922 #endif // BOOST_DOXYGEN_INVOKED
Chris@16 923 };
Chris@16 924
Chris@16 925
Chris@16 926 } /* namespace heap */
Chris@16 927 } /* namespace boost */
Chris@16 928
Chris@16 929 #undef BOOST_HEAP_ASSERT
Chris@16 930
Chris@16 931 #endif /* BOOST_HEAP_D_ARY_HEAP_HPP */