ordered_adaptor_iterator.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // boost heap: ordered iterator helper classes for container adaptors
  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_DETAIL_ORDERED_ADAPTOR_ITERATOR_HPP
  9. #define BOOST_HEAP_DETAIL_ORDERED_ADAPTOR_ITERATOR_HPP
  10. #include <cassert>
  11. #include <limits>
  12. #include <boost/assert.hpp>
  13. #include <boost/heap/detail/tree_iterator.hpp>
  14. #include <boost/iterator/iterator_adaptor.hpp>
  15. #include <boost/concept_check.hpp>
  16. namespace boost {
  17. namespace heap {
  18. namespace detail {
  19. /* ordered iterator helper classes for container adaptors
  20. *
  21. * Requirements for Dispatcher:
  22. *
  23. * * static size_type max_index(const ContainerType * heap); // return maximum index
  24. * * static bool is_leaf(const ContainerType * heap, size_type index); // return if index denotes a leaf
  25. * * static std::pair<size_type, size_type> get_child_nodes(const ContainerType * heap, size_type index); // get index range of child nodes
  26. * * static internal_type const & get_internal_value(const ContainerType * heap, size_type index); // get internal value at index
  27. * * static value_type const & get_value(internal_type const & arg) const; // get value_type from internal_type
  28. *
  29. * */
  30. template <typename ValueType,
  31. typename InternalType,
  32. typename ContainerType,
  33. typename Alloc,
  34. typename ValueCompare,
  35. typename Dispatcher
  36. >
  37. class ordered_adaptor_iterator:
  38. public boost::iterator_facade<ordered_adaptor_iterator<ValueType,
  39. InternalType,
  40. ContainerType,
  41. Alloc,
  42. ValueCompare,
  43. Dispatcher>,
  44. ValueType,
  45. boost::forward_traversal_tag
  46. >,
  47. Dispatcher
  48. {
  49. friend class boost::iterator_core_access;
  50. struct compare_by_heap_value:
  51. ValueCompare
  52. {
  53. const ContainerType * container;
  54. compare_by_heap_value (const ContainerType * container, ValueCompare const & cmp):
  55. ValueCompare(cmp), container(container)
  56. {}
  57. bool operator()(size_t lhs, size_t rhs)
  58. {
  59. BOOST_ASSERT(lhs <= Dispatcher::max_index(container));
  60. BOOST_ASSERT(rhs <= Dispatcher::max_index(container));
  61. return ValueCompare::operator()(Dispatcher::get_internal_value(container, lhs),
  62. Dispatcher::get_internal_value(container, rhs));
  63. }
  64. };
  65. const ContainerType * container;
  66. size_t current_index; // current index: special value -1 denotes `end' iterator
  67. public:
  68. ordered_adaptor_iterator(void):
  69. container(NULL), current_index((std::numeric_limits<size_t>::max)()),
  70. unvisited_nodes(compare_by_heap_value(NULL, ValueCompare()))
  71. {}
  72. ordered_adaptor_iterator(const ContainerType * container, ValueCompare const & cmp):
  73. container(container), current_index(container->size()),
  74. unvisited_nodes(compare_by_heap_value(container, ValueCompare()))
  75. {}
  76. ordered_adaptor_iterator(size_t initial_index, const ContainerType * container, ValueCompare const & cmp):
  77. container(container), current_index(initial_index),
  78. unvisited_nodes(compare_by_heap_value(container, cmp))
  79. {
  80. discover_nodes(initial_index);
  81. }
  82. private:
  83. bool equal (ordered_adaptor_iterator const & rhs) const
  84. {
  85. if (current_index != rhs.current_index)
  86. return false;
  87. if (container != rhs.container) // less likely than first check
  88. return false;
  89. return true;
  90. }
  91. void increment(void)
  92. {
  93. if (unvisited_nodes.empty())
  94. current_index = Dispatcher::max_index(container) + 1;
  95. else {
  96. current_index = unvisited_nodes.top();
  97. unvisited_nodes.pop();
  98. discover_nodes(current_index);
  99. }
  100. }
  101. ValueType const & dereference() const
  102. {
  103. BOOST_ASSERT(current_index <= Dispatcher::max_index(container));
  104. return Dispatcher::get_value(Dispatcher::get_internal_value(container, current_index));
  105. }
  106. void discover_nodes(size_t index)
  107. {
  108. if (Dispatcher::is_leaf(container, index))
  109. return;
  110. std::pair<size_t, size_t> child_range = Dispatcher::get_child_nodes(container, index);
  111. for (size_t i = child_range.first; i <= child_range.second; ++i)
  112. unvisited_nodes.push(i);
  113. }
  114. std::priority_queue<size_t,
  115. std::vector<size_t, typename boost::allocator_rebind<Alloc, size_t>::type>,
  116. compare_by_heap_value
  117. > unvisited_nodes;
  118. };
  119. } /* namespace detail */
  120. } /* namespace heap */
  121. } /* namespace boost */
  122. #endif /* BOOST_HEAP_DETAIL_ORDERED_ADAPTOR_ITERATOR_HPP */