heap_comparison.hpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. // boost heap: heap node helper classes
  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_DETAIL_HEAP_COMPARISON_HPP
  9. #define BOOST_HEAP_DETAIL_HEAP_COMPARISON_HPP
  10. #include <boost/assert.hpp>
  11. #include <boost/static_assert.hpp>
  12. #include <boost/concept/assert.hpp>
  13. #include <boost/heap/heap_concepts.hpp>
  14. #ifdef BOOST_HEAP_SANITYCHECKS
  15. #define BOOST_HEAP_ASSERT BOOST_ASSERT
  16. #else
  17. #define BOOST_HEAP_ASSERT(expression)
  18. #endif
  19. namespace boost {
  20. namespace heap {
  21. namespace detail {
  22. template <typename Heap1, typename Heap2>
  23. bool value_equality(Heap1 const & lhs, Heap2 const & rhs,
  24. typename Heap1::value_type lval, typename Heap2::value_type rval)
  25. {
  26. typename Heap1::value_compare const & cmp = lhs.value_comp();
  27. bool ret = !(cmp(lval, rval)) && !(cmp(rval, lval));
  28. // if this assertion is triggered, the value_compare objects of lhs and rhs return different values
  29. BOOST_ASSERT((ret == (!(rhs.value_comp()(lval, rval)) && !(rhs.value_comp()(rval, lval)))));
  30. return ret;
  31. }
  32. template <typename Heap1, typename Heap2>
  33. bool value_compare(Heap1 const & lhs, Heap2 const & rhs,
  34. typename Heap1::value_type lval, typename Heap2::value_type rval)
  35. {
  36. typename Heap1::value_compare const & cmp = lhs.value_comp();
  37. bool ret = cmp(lval, rval);
  38. // if this assertion is triggered, the value_compare objects of lhs and rhs return different values
  39. BOOST_ASSERT((ret == rhs.value_comp()(lval, rval)));
  40. return ret;
  41. }
  42. struct heap_equivalence_copy
  43. {
  44. template <typename Heap1, typename Heap2>
  45. bool operator()(Heap1 const & lhs, Heap2 const & rhs)
  46. {
  47. BOOST_CONCEPT_ASSERT((boost::heap::PriorityQueue<Heap1>));
  48. BOOST_CONCEPT_ASSERT((boost::heap::PriorityQueue<Heap2>));
  49. // if this assertion is triggered, the value_compare types are incompatible
  50. BOOST_STATIC_ASSERT((boost::is_same<typename Heap1::value_compare, typename Heap2::value_compare>::value));
  51. if (Heap1::constant_time_size && Heap2::constant_time_size)
  52. if (lhs.size() != rhs.size())
  53. return false;
  54. if (lhs.empty() && rhs.empty())
  55. return true;
  56. Heap1 lhs_copy(lhs);
  57. Heap2 rhs_copy(rhs);
  58. while (true) {
  59. if (!value_equality(lhs_copy, rhs_copy, lhs_copy.top(), rhs_copy.top()))
  60. return false;
  61. lhs_copy.pop();
  62. rhs_copy.pop();
  63. if (lhs_copy.empty() && rhs_copy.empty())
  64. return true;
  65. if (lhs_copy.empty())
  66. return false;
  67. if (rhs_copy.empty())
  68. return false;
  69. }
  70. }
  71. };
  72. struct heap_equivalence_iteration
  73. {
  74. template <typename Heap1, typename Heap2>
  75. bool operator()(Heap1 const & lhs, Heap2 const & rhs)
  76. {
  77. BOOST_CONCEPT_ASSERT((boost::heap::PriorityQueue<Heap1>));
  78. BOOST_CONCEPT_ASSERT((boost::heap::PriorityQueue<Heap2>));
  79. // if this assertion is triggered, the value_compare types are incompatible
  80. BOOST_STATIC_ASSERT((boost::is_same<typename Heap1::value_compare, typename Heap2::value_compare>::value));
  81. if (Heap1::constant_time_size && Heap2::constant_time_size)
  82. if (lhs.size() != rhs.size())
  83. return false;
  84. if (lhs.empty() && rhs.empty())
  85. return true;
  86. typename Heap1::ordered_iterator it1 = lhs.ordered_begin();
  87. typename Heap1::ordered_iterator it1_end = lhs.ordered_end();
  88. typename Heap1::ordered_iterator it2 = rhs.ordered_begin();
  89. typename Heap1::ordered_iterator it2_end = rhs.ordered_end();
  90. while (true) {
  91. if (!value_equality(lhs, rhs, *it1, *it2))
  92. return false;
  93. ++it1;
  94. ++it2;
  95. if (it1 == it1_end && it2 == it2_end)
  96. return true;
  97. if (it1 == it1_end || it2 == it2_end)
  98. return false;
  99. }
  100. }
  101. };
  102. template <typename Heap1,
  103. typename Heap2
  104. >
  105. bool heap_equality(Heap1 const & lhs, Heap2 const & rhs)
  106. {
  107. const bool use_ordered_iterators = Heap1::has_ordered_iterators && Heap2::has_ordered_iterators;
  108. typedef typename boost::mpl::if_c<use_ordered_iterators,
  109. heap_equivalence_iteration,
  110. heap_equivalence_copy
  111. >::type equivalence_check;
  112. equivalence_check eq_check;
  113. return eq_check(lhs, rhs);
  114. }
  115. struct heap_compare_iteration
  116. {
  117. template <typename Heap1,
  118. typename Heap2
  119. >
  120. bool operator()(Heap1 const & lhs, Heap2 const & rhs)
  121. {
  122. typename Heap1::size_type left_size = lhs.size();
  123. typename Heap2::size_type right_size = rhs.size();
  124. if (left_size < right_size)
  125. return true;
  126. if (left_size > right_size)
  127. return false;
  128. typename Heap1::ordered_iterator it1 = lhs.ordered_begin();
  129. typename Heap1::ordered_iterator it1_end = lhs.ordered_end();
  130. typename Heap1::ordered_iterator it2 = rhs.ordered_begin();
  131. typename Heap1::ordered_iterator it2_end = rhs.ordered_end();
  132. while (true) {
  133. if (value_compare(lhs, rhs, *it1, *it2))
  134. return true;
  135. if (value_compare(lhs, rhs, *it2, *it1))
  136. return false;
  137. ++it1;
  138. ++it2;
  139. if (it1 == it1_end && it2 == it2_end)
  140. return true;
  141. if (it1 == it1_end || it2 == it2_end)
  142. return false;
  143. }
  144. }
  145. };
  146. struct heap_compare_copy
  147. {
  148. template <typename Heap1,
  149. typename Heap2
  150. >
  151. bool operator()(Heap1 const & lhs, Heap2 const & rhs)
  152. {
  153. typename Heap1::size_type left_size = lhs.size();
  154. typename Heap2::size_type right_size = rhs.size();
  155. if (left_size < right_size)
  156. return true;
  157. if (left_size > right_size)
  158. return false;
  159. Heap1 lhs_copy(lhs);
  160. Heap2 rhs_copy(rhs);
  161. while (true) {
  162. if (value_compare(lhs_copy, rhs_copy, lhs_copy.top(), rhs_copy.top()))
  163. return true;
  164. if (value_compare(lhs_copy, rhs_copy, rhs_copy.top(), lhs_copy.top()))
  165. return false;
  166. lhs_copy.pop();
  167. rhs_copy.pop();
  168. if (lhs_copy.empty() && rhs_copy.empty())
  169. return false;
  170. }
  171. }
  172. };
  173. template <typename Heap1,
  174. typename Heap2
  175. >
  176. bool heap_compare(Heap1 const & lhs, Heap2 const & rhs)
  177. {
  178. const bool use_ordered_iterators = Heap1::has_ordered_iterators && Heap2::has_ordered_iterators;
  179. typedef typename boost::mpl::if_c<use_ordered_iterators,
  180. heap_compare_iteration,
  181. heap_compare_copy
  182. >::type compare_check;
  183. compare_check check_object;
  184. return check_object(lhs, rhs);
  185. }
  186. } /* namespace detail */
  187. } /* namespace heap */
  188. } /* namespace boost */
  189. #undef BOOST_HEAP_ASSERT
  190. #endif // BOOST_HEAP_DETAIL_HEAP_COMPARISON_HPP