heap_merge.hpp 3.5 KB

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