heap_merge.hpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // boost heap: heap merge algorithms
  2. //
  3. // Copyright (C) 2011 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_MERGE_HPP
  9. #define BOOST_HEAP_MERGE_HPP
  10. #include <algorithm>
  11. #include <boost/concept/assert.hpp>
  12. #include <boost/heap/heap_concepts.hpp>
  13. #include <boost/type_traits/conditional.hpp>
  14. #include <boost/type_traits/is_same.hpp>
  15. #ifdef BOOST_HAS_PRAGMA_ONCE
  16. #pragma once
  17. #endif
  18. namespace boost {
  19. namespace heap {
  20. namespace detail {
  21. template <typename Heap1, typename Heap2>
  22. struct heap_merge_emulate
  23. {
  24. struct dummy_reserver
  25. {
  26. static void reserve (Heap1 & lhs, std::size_t required_size)
  27. {}
  28. };
  29. struct reserver
  30. {
  31. static void reserve (Heap1 & lhs, std::size_t required_size)
  32. {
  33. lhs.reserve(required_size);
  34. }
  35. };
  36. typedef typename boost::conditional<Heap1::has_reserve,
  37. reserver,
  38. dummy_reserver>::type space_reserver;
  39. static void merge(Heap1 & lhs, Heap2 & rhs)
  40. {
  41. if (Heap1::constant_time_size && Heap2::constant_time_size) {
  42. if (Heap1::has_reserve) {
  43. std::size_t required_size = lhs.size() + rhs.size();
  44. space_reserver::reserve(lhs, required_size);
  45. }
  46. }
  47. // FIXME: container adaptors could benefit from first appending all elements and then restoring the heap order
  48. // FIXME: optimize: if we have ordered iterators and we can efficiently insert keys with a below the lowest key in the heap
  49. // d-ary, b and fibonacci heaps fall into this category
  50. while (!rhs.empty()) {
  51. lhs.push(rhs.top());
  52. rhs.pop();
  53. }
  54. lhs.set_stability_count((std::max)(lhs.get_stability_count(),
  55. rhs.get_stability_count()));
  56. rhs.set_stability_count(0);
  57. }
  58. };
  59. template <typename Heap>
  60. struct heap_merge_same_mergable
  61. {
  62. static void merge(Heap & lhs, Heap & rhs)
  63. {
  64. lhs.merge(rhs);
  65. }
  66. };
  67. template <typename Heap>
  68. struct heap_merge_same
  69. {
  70. static const bool is_mergable = Heap::is_mergable;
  71. typedef typename boost::conditional<is_mergable,
  72. heap_merge_same_mergable<Heap>,
  73. heap_merge_emulate<Heap, Heap>
  74. >::type heap_merger;
  75. static void merge(Heap & lhs, Heap & rhs)
  76. {
  77. heap_merger::merge(lhs, rhs);
  78. }
  79. };
  80. } /* namespace detail */
  81. /** merge rhs into lhs
  82. *
  83. * \b Effect: lhs contains all elements that have been part of rhs, rhs is empty.
  84. *
  85. * */
  86. template <typename Heap1,
  87. typename Heap2
  88. >
  89. void heap_merge(Heap1 & lhs, Heap2 & rhs)
  90. {
  91. BOOST_CONCEPT_ASSERT((boost::heap::PriorityQueue<Heap1>));
  92. BOOST_CONCEPT_ASSERT((boost::heap::PriorityQueue<Heap2>));
  93. // if this assertion is triggered, the value_compare types are incompatible
  94. BOOST_STATIC_ASSERT((boost::is_same<typename Heap1::value_compare, typename Heap2::value_compare>::value));
  95. const bool same_heaps = boost::is_same<Heap1, Heap2>::value;
  96. typedef typename boost::conditional<same_heaps,
  97. detail::heap_merge_same<Heap1>,
  98. detail::heap_merge_emulate<Heap1, Heap2>
  99. >::type heap_merger;
  100. heap_merger::merge(lhs, rhs);
  101. }
  102. } /* namespace heap */
  103. } /* namespace boost */
  104. #endif /* BOOST_HEAP_MERGE_HPP */