File indexing completed on 2025-01-18 09:37:10
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_D_ARY_HEAP_HPP
0012 #define BOOST_D_ARY_HEAP_HPP
0013
0014 #include <vector>
0015 #include <cstddef>
0016 #include <algorithm>
0017 #include <utility>
0018 #include <boost/assert.hpp>
0019 #include <boost/static_assert.hpp>
0020 #include <boost/shared_array.hpp>
0021 #include <boost/property_map/property_map.hpp>
0022
0023
0024
0025
0026
0027
0028 namespace boost
0029 {
0030
0031
0032
0033 template < typename PropMap >
0034 inline void property_map_swap(PropMap prop_map,
0035 const typename boost::property_traits< PropMap >::key_type& ka,
0036 const typename boost::property_traits< PropMap >::key_type& kb)
0037 {
0038 typename boost::property_traits< PropMap >::value_type va
0039 = get(prop_map, ka);
0040 put(prop_map, ka, get(prop_map, kb));
0041 put(prop_map, kb, va);
0042 }
0043
0044 namespace detail
0045 {
0046 template < typename Value > class fixed_max_size_vector
0047 {
0048 boost::shared_array< Value > m_data;
0049 std::size_t m_size;
0050
0051 public:
0052 typedef std::size_t size_type;
0053 fixed_max_size_vector(std::size_t max_size)
0054 : m_data(new Value[max_size]), m_size(0)
0055 {
0056 }
0057 std::size_t size() const { return m_size; }
0058 bool empty() const { return m_size == 0; }
0059 Value& operator[](std::size_t i) { return m_data[i]; }
0060 const Value& operator[](std::size_t i) const { return m_data[i]; }
0061 void push_back(Value v) { m_data[m_size++] = v; }
0062 void pop_back() { --m_size; }
0063 Value& back() { return m_data[m_size - 1]; }
0064 const Value& back() const { return m_data[m_size - 1]; }
0065 };
0066 }
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093 template < typename Value, std::size_t Arity, typename IndexInHeapPropertyMap,
0094 typename DistanceMap, typename Compare = std::less< Value >,
0095 typename Container = std::vector< Value > >
0096 class d_ary_heap_indirect
0097 {
0098 BOOST_STATIC_ASSERT(Arity >= 2);
0099
0100 public:
0101 typedef typename Container::size_type size_type;
0102 typedef Value value_type;
0103 typedef typename boost::property_traits< DistanceMap >::value_type key_type;
0104 typedef DistanceMap key_map;
0105
0106 d_ary_heap_indirect(DistanceMap distance,
0107 IndexInHeapPropertyMap index_in_heap,
0108 const Compare& compare = Compare(), const Container& data = Container())
0109 : compare(compare)
0110 , data(data)
0111 , distance(distance)
0112 , index_in_heap(index_in_heap)
0113 {
0114 }
0115
0116
0117
0118 size_type size() const { return data.size(); }
0119
0120 bool empty() const { return data.empty(); }
0121
0122 void push(const Value& v)
0123 {
0124 size_type index = data.size();
0125 data.push_back(v);
0126 put(index_in_heap, v, index);
0127 preserve_heap_property_up(index);
0128 verify_heap();
0129 }
0130
0131 Value& top()
0132 {
0133 BOOST_ASSERT(!this->empty());
0134 return data[0];
0135 }
0136
0137 const Value& top() const
0138 {
0139 BOOST_ASSERT(!this->empty());
0140 return data[0];
0141 }
0142
0143 void pop()
0144 {
0145 BOOST_ASSERT(!this->empty());
0146 put(index_in_heap, data[0], (size_type)(-1));
0147 if (data.size() != 1)
0148 {
0149 data[0] = data.back();
0150 put(index_in_heap, data[0], (size_type)(0));
0151 data.pop_back();
0152 preserve_heap_property_down();
0153 verify_heap();
0154 }
0155 else
0156 {
0157 data.pop_back();
0158 }
0159 }
0160
0161
0162
0163
0164
0165 void update(const Value& v)
0166 {
0167 size_type index = get(index_in_heap, v);
0168 preserve_heap_property_up(index);
0169 verify_heap();
0170 }
0171
0172 bool contains(const Value& v) const
0173 {
0174 size_type index = get(index_in_heap, v);
0175 return (index != (size_type)(-1));
0176 }
0177
0178 void push_or_update(const Value& v)
0179 {
0180 size_type index = get(index_in_heap, v);
0181 if (index == (size_type)(-1))
0182 {
0183 index = data.size();
0184 data.push_back(v);
0185 put(index_in_heap, v, index);
0186 }
0187 preserve_heap_property_up(index);
0188 verify_heap();
0189 }
0190
0191 DistanceMap keys() const { return distance; }
0192
0193 private:
0194 Compare compare;
0195 Container data;
0196 DistanceMap distance;
0197 IndexInHeapPropertyMap index_in_heap;
0198
0199
0200
0201 typedef typename boost::property_traits< DistanceMap >::value_type
0202 distance_type;
0203
0204
0205 static size_type parent(size_type index) { return (index - 1) / Arity; }
0206
0207
0208 static size_type first_child(size_type index)
0209 {
0210 return index * Arity + 1;
0211 }
0212
0213
0214 void swap_heap_elements(size_type index_a, size_type index_b)
0215 {
0216 using std::swap;
0217 Value value_a = data[index_a];
0218 Value value_b = data[index_b];
0219 data[index_a] = value_b;
0220 data[index_b] = value_a;
0221 put(index_in_heap, value_a, index_b);
0222 put(index_in_heap, value_b, index_a);
0223 }
0224
0225
0226 bool compare_indirect(const Value& a, const Value& b) const
0227 {
0228 return compare(get(distance, a), get(distance, b));
0229 }
0230
0231
0232 void verify_heap() const
0233 {
0234
0235
0236 #if 0
0237 for (size_t i = 1; i < data.size(); ++i) {
0238 if (compare_indirect(data[i], data[parent(i)])) {
0239 BOOST_ASSERT (!"Element is smaller than its parent");
0240 }
0241 }
0242 #endif
0243 }
0244
0245
0246
0247 void preserve_heap_property_up(size_type index)
0248 {
0249 size_type orig_index = index;
0250 size_type num_levels_moved = 0;
0251
0252
0253
0254 if (index == 0)
0255 return;
0256 Value currently_being_moved = data[index];
0257 distance_type currently_being_moved_dist
0258 = get(distance, currently_being_moved);
0259 for (;;)
0260 {
0261 if (index == 0)
0262 break;
0263 size_type parent_index = parent(index);
0264 Value parent_value = data[parent_index];
0265 if (compare(
0266 currently_being_moved_dist, get(distance, parent_value)))
0267 {
0268 ++num_levels_moved;
0269 index = parent_index;
0270 continue;
0271 }
0272 else
0273 {
0274 break;
0275 }
0276 }
0277
0278
0279 index = orig_index;
0280 for (size_type i = 0; i < num_levels_moved; ++i)
0281 {
0282 size_type parent_index = parent(index);
0283 Value parent_value = data[parent_index];
0284 put(index_in_heap, parent_value, index);
0285 data[index] = parent_value;
0286 index = parent_index;
0287 }
0288 data[index] = currently_being_moved;
0289 put(index_in_heap, currently_being_moved, index);
0290 verify_heap();
0291 }
0292
0293
0294
0295 void preserve_heap_property_down()
0296 {
0297 if (data.empty())
0298 return;
0299 size_type index = 0;
0300 Value currently_being_moved = data[0];
0301 distance_type currently_being_moved_dist
0302 = get(distance, currently_being_moved);
0303 size_type heap_size = data.size();
0304 Value* data_ptr = &data[0];
0305 for (;;)
0306 {
0307 size_type first_child_index = first_child(index);
0308 if (first_child_index >= heap_size)
0309 break;
0310 Value* child_base_ptr = data_ptr + first_child_index;
0311 size_type smallest_child_index = 0;
0312 distance_type smallest_child_dist
0313 = get(distance, child_base_ptr[smallest_child_index]);
0314 if (first_child_index + Arity <= heap_size)
0315 {
0316
0317 for (size_t i = 1; i < Arity; ++i)
0318 {
0319 Value i_value = child_base_ptr[i];
0320 distance_type i_dist = get(distance, i_value);
0321 if (compare(i_dist, smallest_child_dist))
0322 {
0323 smallest_child_index = i;
0324 smallest_child_dist = i_dist;
0325 }
0326 }
0327 }
0328 else
0329 {
0330 for (size_t i = 1; i < heap_size - first_child_index; ++i)
0331 {
0332 distance_type i_dist = get(distance, child_base_ptr[i]);
0333 if (compare(i_dist, smallest_child_dist))
0334 {
0335 smallest_child_index = i;
0336 smallest_child_dist = i_dist;
0337 }
0338 }
0339 }
0340 if (compare(smallest_child_dist, currently_being_moved_dist))
0341 {
0342 swap_heap_elements(
0343 smallest_child_index + first_child_index, index);
0344 index = smallest_child_index + first_child_index;
0345 continue;
0346 }
0347 else
0348 {
0349 break;
0350 }
0351 }
0352 verify_heap();
0353 }
0354 };
0355
0356 }
0357
0358 #endif