binomial_heap.hpp 30 KB

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