binomial_heap.hpp 30 KB

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