binomial_heap.hpp 31 KB

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