31 |
31 |
32 ///\ingroup auxdat |
32 ///\ingroup auxdat |
33 /// |
33 /// |
34 ///\brief A Binary Heap implementation. |
34 ///\brief A Binary Heap implementation. |
35 /// |
35 /// |
36 ///This class implements the \e binary \e heap data structure. A \e heap |
36 ///This class implements the \e binary \e heap data structure. |
37 ///is a data structure for storing items with specified values called \e |
37 /// |
38 ///priorities in such a way that finding the item with minimum priority is |
38 ///A \e heap is a data structure for storing items with specified values |
39 ///efficient. \c Compare specifies the ordering of the priorities. In a heap |
39 ///called \e priorities in such a way that finding the item with minimum |
40 ///one can change the priority of an item, add or erase an item, etc. |
40 ///priority is efficient. \c Comp specifies the ordering of the priorities. |
|
41 ///In a heap one can change the priority of an item, add or erase an |
|
42 ///item, etc. |
41 /// |
43 /// |
42 ///\tparam _Prio Type of the priority of the items. |
44 ///\tparam PR Type of the priority of the items. |
43 ///\tparam _ItemIntMap A read and writable Item int map, used internally |
45 ///\tparam IM A read and writable item map with int values, used internally |
44 ///to handle the cross references. |
46 ///to handle the cross references. |
45 ///\tparam _Compare A class for the ordering of the priorities. The |
47 ///\tparam Comp A functor class for the ordering of the priorities. |
46 ///default is \c std::less<_Prio>. |
48 ///The default is \c std::less<PR>. |
47 /// |
49 /// |
48 ///\sa FibHeap |
50 ///\sa FibHeap |
49 ///\sa Dijkstra |
51 ///\sa Dijkstra |
50 template <typename _Prio, typename _ItemIntMap, |
52 template <typename PR, typename IM, typename Comp = std::less<PR> > |
51 typename _Compare = std::less<_Prio> > |
|
52 class BinHeap { |
53 class BinHeap { |
53 |
54 |
54 public: |
55 public: |
55 ///\e |
56 ///\e |
56 typedef _ItemIntMap ItemIntMap; |
57 typedef IM ItemIntMap; |
57 ///\e |
58 ///\e |
58 typedef _Prio Prio; |
59 typedef PR Prio; |
59 ///\e |
60 ///\e |
60 typedef typename ItemIntMap::Key Item; |
61 typedef typename ItemIntMap::Key Item; |
61 ///\e |
62 ///\e |
62 typedef std::pair<Item,Prio> Pair; |
63 typedef std::pair<Item,Prio> Pair; |
63 ///\e |
64 ///\e |
64 typedef _Compare Compare; |
65 typedef Comp Compare; |
65 |
66 |
66 /// \brief Type to represent the items states. |
67 /// \brief Type to represent the items states. |
67 /// |
68 /// |
68 /// Each Item element have a state associated to it. It may be "in heap", |
69 /// Each Item element have a state associated to it. It may be "in heap", |
69 /// "pre heap" or "post heap". The latter two are indifferent from the |
70 /// "pre heap" or "post heap". The latter two are indifferent from the |
70 /// heap's point of view, but may be useful to the user. |
71 /// heap's point of view, but may be useful to the user. |
71 /// |
72 /// |
72 /// The ItemIntMap \e should be initialized in such way that it maps |
73 /// The item-int map must be initialized in such way that it assigns |
73 /// PRE_HEAP (-1) to any element to be put in the heap... |
74 /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap. |
74 enum State { |
75 enum State { |
75 IN_HEAP = 0, |
76 IN_HEAP = 0, ///< \e |
76 PRE_HEAP = -1, |
77 PRE_HEAP = -1, ///< \e |
77 POST_HEAP = -2 |
78 POST_HEAP = -2 ///< \e |
78 }; |
79 }; |
79 |
80 |
80 private: |
81 private: |
81 std::vector<Pair> data; |
82 std::vector<Pair> _data; |
82 Compare comp; |
83 Compare _comp; |
83 ItemIntMap &iim; |
84 ItemIntMap &_iim; |
84 |
85 |
85 public: |
86 public: |
86 /// \brief The constructor. |
87 /// \brief The constructor. |
87 /// |
88 /// |
88 /// The constructor. |
89 /// The constructor. |
89 /// \param _iim should be given to the constructor, since it is used |
90 /// \param map should be given to the constructor, since it is used |
|
91 /// internally to handle the cross references. The value of the map |
|
92 /// must be \c PRE_HEAP (<tt>-1</tt>) for every item. |
|
93 explicit BinHeap(ItemIntMap &map) : _iim(map) {} |
|
94 |
|
95 /// \brief The constructor. |
|
96 /// |
|
97 /// The constructor. |
|
98 /// \param map should be given to the constructor, since it is used |
90 /// internally to handle the cross references. The value of the map |
99 /// internally to handle the cross references. The value of the map |
91 /// should be PRE_HEAP (-1) for each element. |
100 /// should be PRE_HEAP (-1) for each element. |
92 explicit BinHeap(ItemIntMap &_iim) : iim(_iim) {} |
101 /// |
93 |
102 /// \param comp The comparator function object. |
94 /// \brief The constructor. |
103 BinHeap(ItemIntMap &map, const Compare &comp) |
95 /// |
104 : _iim(map), _comp(comp) {} |
96 /// The constructor. |
|
97 /// \param _iim should be given to the constructor, since it is used |
|
98 /// internally to handle the cross references. The value of the map |
|
99 /// should be PRE_HEAP (-1) for each element. |
|
100 /// |
|
101 /// \param _comp The comparator function object. |
|
102 BinHeap(ItemIntMap &_iim, const Compare &_comp) |
|
103 : iim(_iim), comp(_comp) {} |
|
104 |
105 |
105 |
106 |
106 /// The number of items stored in the heap. |
107 /// The number of items stored in the heap. |
107 /// |
108 /// |
108 /// \brief Returns the number of items stored in the heap. |
109 /// \brief Returns the number of items stored in the heap. |
109 int size() const { return data.size(); } |
110 int size() const { return _data.size(); } |
110 |
111 |
111 /// \brief Checks if the heap stores no items. |
112 /// \brief Checks if the heap stores no items. |
112 /// |
113 /// |
113 /// Returns \c true if and only if the heap stores no items. |
114 /// Returns \c true if and only if the heap stores no items. |
114 bool empty() const { return data.empty(); } |
115 bool empty() const { return _data.empty(); } |
115 |
116 |
116 /// \brief Make empty this heap. |
117 /// \brief Make empty this heap. |
117 /// |
118 /// |
118 /// Make empty this heap. It does not change the cross reference map. |
119 /// Make empty this heap. It does not change the cross reference map. |
119 /// If you want to reuse what is not surely empty you should first clear |
120 /// If you want to reuse what is not surely empty you should first clear |
120 /// the heap and after that you should set the cross reference map for |
121 /// the heap and after that you should set the cross reference map for |
121 /// each item to \c PRE_HEAP. |
122 /// each item to \c PRE_HEAP. |
122 void clear() { |
123 void clear() { |
123 data.clear(); |
124 _data.clear(); |
124 } |
125 } |
125 |
126 |
126 private: |
127 private: |
127 static int parent(int i) { return (i-1)/2; } |
128 static int parent(int i) { return (i-1)/2; } |
128 |
129 |
129 static int second_child(int i) { return 2*i+2; } |
130 static int second_child(int i) { return 2*i+2; } |
130 bool less(const Pair &p1, const Pair &p2) const { |
131 bool less(const Pair &p1, const Pair &p2) const { |
131 return comp(p1.second, p2.second); |
132 return _comp(p1.second, p2.second); |
132 } |
133 } |
133 |
134 |
134 int bubble_up(int hole, Pair p) { |
135 int bubble_up(int hole, Pair p) { |
135 int par = parent(hole); |
136 int par = parent(hole); |
136 while( hole>0 && less(p,data[par]) ) { |
137 while( hole>0 && less(p,_data[par]) ) { |
137 move(data[par],hole); |
138 move(_data[par],hole); |
138 hole = par; |
139 hole = par; |
139 par = parent(hole); |
140 par = parent(hole); |
140 } |
141 } |
141 move(p, hole); |
142 move(p, hole); |
142 return hole; |
143 return hole; |
143 } |
144 } |
144 |
145 |
145 int bubble_down(int hole, Pair p, int length) { |
146 int bubble_down(int hole, Pair p, int length) { |
146 int child = second_child(hole); |
147 int child = second_child(hole); |
147 while(child < length) { |
148 while(child < length) { |
148 if( less(data[child-1], data[child]) ) { |
149 if( less(_data[child-1], _data[child]) ) { |
149 --child; |
150 --child; |
150 } |
151 } |
151 if( !less(data[child], p) ) |
152 if( !less(_data[child], p) ) |
152 goto ok; |
153 goto ok; |
153 move(data[child], hole); |
154 move(_data[child], hole); |
154 hole = child; |
155 hole = child; |
155 child = second_child(hole); |
156 child = second_child(hole); |
156 } |
157 } |
157 child--; |
158 child--; |
158 if( child<length && less(data[child], p) ) { |
159 if( child<length && less(_data[child], p) ) { |
159 move(data[child], hole); |
160 move(_data[child], hole); |
160 hole=child; |
161 hole=child; |
161 } |
162 } |
162 ok: |
163 ok: |
163 move(p, hole); |
164 move(p, hole); |
164 return hole; |
165 return hole; |
165 } |
166 } |
166 |
167 |
167 void move(const Pair &p, int i) { |
168 void move(const Pair &p, int i) { |
168 data[i] = p; |
169 _data[i] = p; |
169 iim.set(p.first, i); |
170 _iim.set(p.first, i); |
170 } |
171 } |
171 |
172 |
172 public: |
173 public: |
173 /// \brief Insert a pair of item and priority into the heap. |
174 /// \brief Insert a pair of item and priority into the heap. |
174 /// |
175 /// |
175 /// Adds \c p.first to the heap with priority \c p.second. |
176 /// Adds \c p.first to the heap with priority \c p.second. |
176 /// \param p The pair to insert. |
177 /// \param p The pair to insert. |
177 void push(const Pair &p) { |
178 void push(const Pair &p) { |
178 int n = data.size(); |
179 int n = _data.size(); |
179 data.resize(n+1); |
180 _data.resize(n+1); |
180 bubble_up(n, p); |
181 bubble_up(n, p); |
181 } |
182 } |
182 |
183 |
183 /// \brief Insert an item into the heap with the given heap. |
184 /// \brief Insert an item into the heap with the given heap. |
184 /// |
185 /// |
191 /// |
192 /// |
192 /// This method returns the item with minimum priority relative to \c |
193 /// This method returns the item with minimum priority relative to \c |
193 /// Compare. |
194 /// Compare. |
194 /// \pre The heap must be nonempty. |
195 /// \pre The heap must be nonempty. |
195 Item top() const { |
196 Item top() const { |
196 return data[0].first; |
197 return _data[0].first; |
197 } |
198 } |
198 |
199 |
199 /// \brief Returns the minimum priority relative to \c Compare. |
200 /// \brief Returns the minimum priority relative to \c Compare. |
200 /// |
201 /// |
201 /// It returns the minimum priority relative to \c Compare. |
202 /// It returns the minimum priority relative to \c Compare. |
202 /// \pre The heap must be nonempty. |
203 /// \pre The heap must be nonempty. |
203 Prio prio() const { |
204 Prio prio() const { |
204 return data[0].second; |
205 return _data[0].second; |
205 } |
206 } |
206 |
207 |
207 /// \brief Deletes the item with minimum priority relative to \c Compare. |
208 /// \brief Deletes the item with minimum priority relative to \c Compare. |
208 /// |
209 /// |
209 /// This method deletes the item with minimum priority relative to \c |
210 /// This method deletes the item with minimum priority relative to \c |
210 /// Compare from the heap. |
211 /// Compare from the heap. |
211 /// \pre The heap must be non-empty. |
212 /// \pre The heap must be non-empty. |
212 void pop() { |
213 void pop() { |
213 int n = data.size()-1; |
214 int n = _data.size()-1; |
214 iim.set(data[0].first, POST_HEAP); |
215 _iim.set(_data[0].first, POST_HEAP); |
215 if (n > 0) { |
216 if (n > 0) { |
216 bubble_down(0, data[n], n); |
217 bubble_down(0, _data[n], n); |
217 } |
218 } |
218 data.pop_back(); |
219 _data.pop_back(); |
219 } |
220 } |
220 |
221 |
221 /// \brief Deletes \c i from the heap. |
222 /// \brief Deletes \c i from the heap. |
222 /// |
223 /// |
223 /// This method deletes item \c i from the heap. |
224 /// This method deletes item \c i from the heap. |
224 /// \param i The item to erase. |
225 /// \param i The item to erase. |
225 /// \pre The item should be in the heap. |
226 /// \pre The item should be in the heap. |
226 void erase(const Item &i) { |
227 void erase(const Item &i) { |
227 int h = iim[i]; |
228 int h = _iim[i]; |
228 int n = data.size()-1; |
229 int n = _data.size()-1; |
229 iim.set(data[h].first, POST_HEAP); |
230 _iim.set(_data[h].first, POST_HEAP); |
230 if( h < n ) { |
231 if( h < n ) { |
231 if ( bubble_up(h, data[n]) == h) { |
232 if ( bubble_up(h, _data[n]) == h) { |
232 bubble_down(h, data[n], n); |
233 bubble_down(h, _data[n], n); |
233 } |
234 } |
234 } |
235 } |
235 data.pop_back(); |
236 _data.pop_back(); |
236 } |
237 } |
237 |
238 |
238 |
239 |
239 /// \brief Returns the priority of \c i. |
240 /// \brief Returns the priority of \c i. |
240 /// |
241 /// |
241 /// This function returns the priority of item \c i. |
242 /// This function returns the priority of item \c i. |
|
243 /// \param i The item. |
242 /// \pre \c i must be in the heap. |
244 /// \pre \c i must be in the heap. |
243 /// \param i The item. |
|
244 Prio operator[](const Item &i) const { |
245 Prio operator[](const Item &i) const { |
245 int idx = iim[i]; |
246 int idx = _iim[i]; |
246 return data[idx].second; |
247 return _data[idx].second; |
247 } |
248 } |
248 |
249 |
249 /// \brief \c i gets to the heap with priority \c p independently |
250 /// \brief \c i gets to the heap with priority \c p independently |
250 /// if \c i was already there. |
251 /// if \c i was already there. |
251 /// |
252 /// |
252 /// This method calls \ref push(\c i, \c p) if \c i is not stored |
253 /// This method calls \ref push(\c i, \c p) if \c i is not stored |
253 /// in the heap and sets the priority of \c i to \c p otherwise. |
254 /// in the heap and sets the priority of \c i to \c p otherwise. |
254 /// \param i The item. |
255 /// \param i The item. |
255 /// \param p The priority. |
256 /// \param p The priority. |
256 void set(const Item &i, const Prio &p) { |
257 void set(const Item &i, const Prio &p) { |
257 int idx = iim[i]; |
258 int idx = _iim[i]; |
258 if( idx < 0 ) { |
259 if( idx < 0 ) { |
259 push(i,p); |
260 push(i,p); |
260 } |
261 } |
261 else if( comp(p, data[idx].second) ) { |
262 else if( _comp(p, _data[idx].second) ) { |
262 bubble_up(idx, Pair(i,p)); |
263 bubble_up(idx, Pair(i,p)); |
263 } |
264 } |
264 else { |
265 else { |
265 bubble_down(idx, Pair(i,p), data.size()); |
266 bubble_down(idx, Pair(i,p), _data.size()); |
266 } |
267 } |
267 } |
268 } |
268 |
269 |
269 /// \brief Decreases the priority of \c i to \c p. |
270 /// \brief Decreases the priority of \c i to \c p. |
270 /// |
271 /// |
271 /// This method decreases the priority of item \c i to \c p. |
272 /// This method decreases the priority of item \c i to \c p. |
|
273 /// \param i The item. |
|
274 /// \param p The priority. |
272 /// \pre \c i must be stored in the heap with priority at least \c |
275 /// \pre \c i must be stored in the heap with priority at least \c |
273 /// p relative to \c Compare. |
276 /// p relative to \c Compare. |
|
277 void decrease(const Item &i, const Prio &p) { |
|
278 int idx = _iim[i]; |
|
279 bubble_up(idx, Pair(i,p)); |
|
280 } |
|
281 |
|
282 /// \brief Increases the priority of \c i to \c p. |
|
283 /// |
|
284 /// This method sets the priority of item \c i to \c p. |
274 /// \param i The item. |
285 /// \param i The item. |
275 /// \param p The priority. |
286 /// \param p The priority. |
276 void decrease(const Item &i, const Prio &p) { |
|
277 int idx = iim[i]; |
|
278 bubble_up(idx, Pair(i,p)); |
|
279 } |
|
280 |
|
281 /// \brief Increases the priority of \c i to \c p. |
|
282 /// |
|
283 /// This method sets the priority of item \c i to \c p. |
|
284 /// \pre \c i must be stored in the heap with priority at most \c |
287 /// \pre \c i must be stored in the heap with priority at most \c |
285 /// p relative to \c Compare. |
288 /// p relative to \c Compare. |
286 /// \param i The item. |
|
287 /// \param p The priority. |
|
288 void increase(const Item &i, const Prio &p) { |
289 void increase(const Item &i, const Prio &p) { |
289 int idx = iim[i]; |
290 int idx = _iim[i]; |
290 bubble_down(idx, Pair(i,p), data.size()); |
291 bubble_down(idx, Pair(i,p), _data.size()); |
291 } |
292 } |
292 |
293 |
293 /// \brief Returns if \c item is in, has already been in, or has |
294 /// \brief Returns if \c item is in, has already been in, or has |
294 /// never been in the heap. |
295 /// never been in the heap. |
295 /// |
296 /// |