heap_merge.hpp 3.3 KB

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