37 ///is a data structure for storing items with specified values called \e |
37 ///is a data structure for storing items with specified values called \e |
38 ///priorities in such a way that finding the item with minimum priority is |
38 ///priorities in such a way that finding the item with minimum priority is |
39 ///efficient. \c Compare specifies the ordering of the priorities. In a heap |
39 ///efficient. \c Compare specifies the ordering of the priorities. In a heap |
40 ///one can change the priority of an item, add or erase an item, etc. |
40 ///one can change the priority of an item, add or erase an item, etc. |
41 /// |
41 /// |
42 ///\param Prio Type of the priority of the items. |
42 ///\param _Prio Type of the priority of the items. |
43 ///\param ItemIntMap A read and writable Item int map, used internally |
43 ///\param _ItemIntMap A read and writable Item int map, used internally |
44 ///to handle the cross references. |
44 ///to handle the cross references. |
45 ///\param Compare A class for the ordering of the priorities. The |
45 ///\param _Compare A class for the ordering of the priorities. The |
46 ///default is \c std::less<Prio>. |
46 ///default is \c std::less<_Prio>. |
47 /// |
47 /// |
48 ///\sa FibHeap |
48 ///\sa FibHeap |
49 ///\sa Dijkstra |
49 ///\sa Dijkstra |
50 template <typename Prio, typename ItemIntMap, |
50 template <typename _Prio, typename _ItemIntMap, |
51 typename Compare = std::less<Prio> > |
51 typename _Compare = std::less<_Prio> > |
52 class BinHeap { |
52 class BinHeap { |
53 |
53 |
54 public: |
54 public: |
55 typedef typename ItemIntMap::Key ItemType; |
55 typedef _ItemIntMap ItemIntMap; |
56 typedef Prio PrioType; |
56 typedef _Prio Prio; |
57 typedef std::pair<ItemType,PrioType> PairType; |
57 typedef typename ItemIntMap::Key Item; |
58 typedef ItemIntMap ItemIntMapType; |
58 typedef std::pair<Item,Prio> Pair; |
59 typedef Compare PrioCompare; |
59 typedef _Compare Compare; |
60 |
60 |
61 /// \brief Type to represent the items states. |
61 /// \brief Type to represent the items states. |
62 /// |
62 /// |
63 /// Each Item element have a state associated to it. It may be "in heap", |
63 /// Each Item element have a state associated to it. It may be "in heap", |
64 /// "pre heap" or "post heap". The latter two are indifferent from the |
64 /// "pre heap" or "post heap". The latter two are indifferent from the |
65 /// heap's point of view, but may be useful to the user. |
65 /// heap's point of view, but may be useful to the user. |
66 /// |
66 /// |
67 /// The ItemIntMap \e should be initialized in such way that it maps |
67 /// The ItemIntMap \e should be initialized in such way that it maps |
68 /// PRE_HEAP (-1) to any element to be put in the heap... |
68 /// PRE_HEAP (-1) to any element to be put in the heap... |
69 enum state_enum { |
69 enum State { |
70 IN_HEAP = 0, |
70 IN_HEAP = 0, |
71 PRE_HEAP = -1, |
71 PRE_HEAP = -1, |
72 POST_HEAP = -2 |
72 POST_HEAP = -2 |
73 }; |
73 }; |
74 |
74 |
75 private: |
75 private: |
76 std::vector<PairType> data; |
76 std::vector<Pair> data; |
77 Compare comp; |
77 Compare comp; |
78 ItemIntMap &iim; |
78 ItemIntMap &iim; |
79 |
79 |
80 public: |
80 public: |
81 /// \brief The constructor. |
81 /// \brief The constructor. |
120 |
120 |
121 private: |
121 private: |
122 static int parent(int i) { return (i-1)/2; } |
122 static int parent(int i) { return (i-1)/2; } |
123 |
123 |
124 static int second_child(int i) { return 2*i+2; } |
124 static int second_child(int i) { return 2*i+2; } |
125 bool less(const PairType &p1, const PairType &p2) const { |
125 bool less(const Pair &p1, const Pair &p2) const { |
126 return comp(p1.second, p2.second); |
126 return comp(p1.second, p2.second); |
127 } |
127 } |
128 |
128 |
129 int bubble_up(int hole, PairType p) { |
129 int bubble_up(int hole, Pair p) { |
130 int par = parent(hole); |
130 int par = parent(hole); |
131 while( hole>0 && less(p,data[par]) ) { |
131 while( hole>0 && less(p,data[par]) ) { |
132 move(data[par],hole); |
132 move(data[par],hole); |
133 hole = par; |
133 hole = par; |
134 par = parent(hole); |
134 par = parent(hole); |
135 } |
135 } |
136 move(p, hole); |
136 move(p, hole); |
137 return hole; |
137 return hole; |
138 } |
138 } |
139 |
139 |
140 int bubble_down(int hole, PairType p, int length) { |
140 int bubble_down(int hole, Pair p, int length) { |
141 int child = second_child(hole); |
141 int child = second_child(hole); |
142 while(child < length) { |
142 while(child < length) { |
143 if( less(data[child-1], data[child]) ) { |
143 if( less(data[child-1], data[child]) ) { |
144 --child; |
144 --child; |
145 } |
145 } |
157 ok: |
157 ok: |
158 move(p, hole); |
158 move(p, hole); |
159 return hole; |
159 return hole; |
160 } |
160 } |
161 |
161 |
162 void move(const PairType &p, int i) { |
162 void move(const Pair &p, int i) { |
163 data[i] = p; |
163 data[i] = p; |
164 iim.set(p.first, i); |
164 iim.set(p.first, i); |
165 } |
165 } |
166 |
166 |
167 public: |
167 public: |
168 /// \brief Insert a pair of item and priority into the heap. |
168 /// \brief Insert a pair of item and priority into the heap. |
169 /// |
169 /// |
170 /// Adds \c p.first to the heap with priority \c p.second. |
170 /// Adds \c p.first to the heap with priority \c p.second. |
171 /// \param p The pair to insert. |
171 /// \param p The pair to insert. |
172 void push(const PairType &p) { |
172 void push(const Pair &p) { |
173 int n = data.size(); |
173 int n = data.size(); |
174 data.resize(n+1); |
174 data.resize(n+1); |
175 bubble_up(n, p); |
175 bubble_up(n, p); |
176 } |
176 } |
177 |
177 |
178 /// \brief Insert an item into the heap with the given heap. |
178 /// \brief Insert an item into the heap with the given heap. |
179 /// |
179 /// |
180 /// Adds \c i to the heap with priority \c p. |
180 /// Adds \c i to the heap with priority \c p. |
181 /// \param i The item to insert. |
181 /// \param i The item to insert. |
182 /// \param p The priority of the item. |
182 /// \param p The priority of the item. |
183 void push(const ItemType &i, const Prio &p) { push(PairType(i,p)); } |
183 void push(const Item &i, const Prio &p) { push(Pair(i,p)); } |
184 |
184 |
185 /// \brief Returns the item with minimum priority relative to \c Compare. |
185 /// \brief Returns the item with minimum priority relative to \c Compare. |
186 /// |
186 /// |
187 /// This method returns the item with minimum priority relative to \c |
187 /// This method returns the item with minimum priority relative to \c |
188 /// Compare. |
188 /// Compare. |
189 /// \pre The heap must be nonempty. |
189 /// \pre The heap must be nonempty. |
190 ItemType top() const { |
190 Item top() const { |
191 return data[0].first; |
191 return data[0].first; |
192 } |
192 } |
193 |
193 |
194 /// \brief Returns the minimum priority relative to \c Compare. |
194 /// \brief Returns the minimum priority relative to \c Compare. |
195 /// |
195 /// |
246 /// |
246 /// |
247 /// This method calls \ref push(\c i, \c p) if \c i is not stored |
247 /// This method calls \ref push(\c i, \c p) if \c i is not stored |
248 /// in the heap and sets the priority of \c i to \c p otherwise. |
248 /// in the heap and sets the priority of \c i to \c p otherwise. |
249 /// \param i The item. |
249 /// \param i The item. |
250 /// \param p The priority. |
250 /// \param p The priority. |
251 void set(const ItemType &i, const Prio &p) { |
251 void set(const Item &i, const Prio &p) { |
252 int idx = iim[i]; |
252 int idx = iim[i]; |
253 if( idx < 0 ) { |
253 if( idx < 0 ) { |
254 push(i,p); |
254 push(i,p); |
255 } |
255 } |
256 else if( comp(p, data[idx].second) ) { |
256 else if( comp(p, data[idx].second) ) { |
257 bubble_up(idx, PairType(i,p)); |
257 bubble_up(idx, Pair(i,p)); |
258 } |
258 } |
259 else { |
259 else { |
260 bubble_down(idx, PairType(i,p), data.size()); |
260 bubble_down(idx, Pair(i,p), data.size()); |
261 } |
261 } |
262 } |
262 } |
263 |
263 |
264 /// \brief Decreases the priority of \c i to \c p. |
264 /// \brief Decreases the priority of \c i to \c p. |
265 /// |
265 /// |
266 /// This method decreases the priority of item \c i to \c p. |
266 /// This method decreases the priority of item \c i to \c p. |
267 /// \pre \c i must be stored in the heap with priority at least \c |
267 /// \pre \c i must be stored in the heap with priority at least \c |
268 /// p relative to \c Compare. |
268 /// p relative to \c Compare. |
269 /// \param i The item. |
269 /// \param i The item. |
270 /// \param p The priority. |
270 /// \param p The priority. |
271 void decrease(const ItemType &i, const Prio &p) { |
271 void decrease(const Item &i, const Prio &p) { |
272 int idx = iim[i]; |
272 int idx = iim[i]; |
273 bubble_up(idx, PairType(i,p)); |
273 bubble_up(idx, Pair(i,p)); |
274 } |
274 } |
275 |
275 |
276 /// \brief Increases the priority of \c i to \c p. |
276 /// \brief Increases the priority of \c i to \c p. |
277 /// |
277 /// |
278 /// This method sets the priority of item \c i to \c p. |
278 /// This method sets the priority of item \c i to \c p. |
279 /// \pre \c i must be stored in the heap with priority at most \c |
279 /// \pre \c i must be stored in the heap with priority at most \c |
280 /// p relative to \c Compare. |
280 /// p relative to \c Compare. |
281 /// \param i The item. |
281 /// \param i The item. |
282 /// \param p The priority. |
282 /// \param p The priority. |
283 void increase(const ItemType &i, const Prio &p) { |
283 void increase(const Item &i, const Prio &p) { |
284 int idx = iim[i]; |
284 int idx = iim[i]; |
285 bubble_down(idx, PairType(i,p), data.size()); |
285 bubble_down(idx, Pair(i,p), data.size()); |
286 } |
286 } |
287 |
287 |
288 /// \brief Returns if \c item is in, has already been in, or has |
288 /// \brief Returns if \c item is in, has already been in, or has |
289 /// never been in the heap. |
289 /// never been in the heap. |
290 /// |
290 /// |
291 /// This method returns PRE_HEAP if \c item has never been in the |
291 /// This method returns PRE_HEAP if \c item has never been in the |
292 /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP |
292 /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP |
293 /// otherwise. In the latter case it is possible that \c item will |
293 /// otherwise. In the latter case it is possible that \c item will |
294 /// get back to the heap again. |
294 /// get back to the heap again. |
295 /// \param i The item. |
295 /// \param i The item. |
296 state_enum state(const ItemType &i) const { |
296 State state(const Item &i) const { |
297 int s = iim[i]; |
297 int s = iim[i]; |
298 if( s>=0 ) |
298 if( s>=0 ) |
299 s=0; |
299 s=0; |
300 return state_enum(s); |
300 return State(s); |
301 } |
301 } |
302 |
302 |
303 /// \brief Sets the state of the \c item in the heap. |
303 /// \brief Sets the state of the \c item in the heap. |
304 /// |
304 /// |
305 /// Sets the state of the \c item in the heap. It can be used to |
305 /// Sets the state of the \c item in the heap. It can be used to |
306 /// manually clear the heap when it is important to achive the |
306 /// manually clear the heap when it is important to achive the |
307 /// better time complexity. |
307 /// better time complexity. |
308 /// \param i The item. |
308 /// \param i The item. |
309 /// \param st The state. It should not be \c IN_HEAP. |
309 /// \param st The state. It should not be \c IN_HEAP. |
310 void state(const ItemType& i, state_enum st) { |
310 void state(const Item& i, State st) { |
311 switch (st) { |
311 switch (st) { |
312 case POST_HEAP: |
312 case POST_HEAP: |
313 case PRE_HEAP: |
313 case PRE_HEAP: |
314 if (state(i) == IN_HEAP) { |
314 if (state(i) == IN_HEAP) { |
315 erase(i); |
315 erase(i); |