heap_comparison.hpp 7.2 KB

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