34 ///\brief Fibonacci Heap. |
34 ///\brief Fibonacci Heap. |
35 /// |
35 /// |
36 ///This class implements the \e Fibonacci \e heap data structure. A \e heap |
36 ///This class implements the \e Fibonacci \e heap data structure. A \e heap |
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 CMP 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 ///The methods \ref increase and \ref erase are not efficient in a Fibonacci |
42 ///The methods \ref increase and \ref erase are not efficient in a Fibonacci |
43 ///heap. In case of many calls to these operations, it is better to use a |
43 ///heap. In case of many calls to these operations, it is better to use a |
44 ///\ref BinHeap "binary heap". |
44 ///\ref BinHeap "binary heap". |
45 /// |
45 /// |
46 ///\param _Prio Type of the priority of the items. |
46 ///\param PRIO Type of the priority of the items. |
47 ///\param _ItemIntMap A read and writable Item int map, used internally |
47 ///\param IM A read and writable Item int map, used internally |
48 ///to handle the cross references. |
48 ///to handle the cross references. |
49 ///\param _Compare A class for the ordering of the priorities. The |
49 ///\param CMP A class for the ordering of the priorities. The |
50 ///default is \c std::less<_Prio>. |
50 ///default is \c std::less<PRIO>. |
51 /// |
51 /// |
52 ///\sa BinHeap |
52 ///\sa BinHeap |
53 ///\sa Dijkstra |
53 ///\sa Dijkstra |
54 #ifdef DOXYGEN |
54 #ifdef DOXYGEN |
55 template <typename _Prio, |
55 template <typename PRIO, typename IM, typename CMP> |
56 typename _ItemIntMap, |
|
57 typename _Compare> |
|
58 #else |
56 #else |
59 template <typename _Prio, |
57 template <typename PRIO, typename IM, typename CMP = std::less<PRIO> > |
60 typename _ItemIntMap, |
|
61 typename _Compare = std::less<_Prio> > |
|
62 #endif |
58 #endif |
63 class FibHeap { |
59 class FibHeap { |
64 public: |
60 public: |
65 ///\e |
61 ///\e |
66 typedef _ItemIntMap ItemIntMap; |
62 typedef IM ItemIntMap; |
67 ///\e |
63 ///\e |
68 typedef _Prio Prio; |
64 typedef PRIO Prio; |
69 ///\e |
65 ///\e |
70 typedef typename ItemIntMap::Key Item; |
66 typedef typename ItemIntMap::Key Item; |
71 ///\e |
67 ///\e |
72 typedef std::pair<Item,Prio> Pair; |
68 typedef std::pair<Item,Prio> Pair; |
73 ///\e |
69 ///\e |
74 typedef _Compare Compare; |
70 typedef CMP Compare; |
75 |
71 |
76 private: |
72 private: |
77 class store; |
73 class Store; |
78 |
74 |
79 std::vector<store> container; |
75 std::vector<Store> _data; |
80 int minimum; |
76 int _minimum; |
81 ItemIntMap &iimap; |
77 ItemIntMap &_iim; |
82 Compare comp; |
78 Compare _comp; |
83 int num_items; |
79 int _num; |
84 |
80 |
85 public: |
81 public: |
86 ///Status of the nodes |
82 |
|
83 /// \brief Type to represent the items states. |
|
84 /// |
|
85 /// Each Item element have a state associated to it. It may be "in heap", |
|
86 /// "pre heap" or "post heap". The latter two are indifferent from the |
|
87 /// heap's point of view, but may be useful to the user. |
|
88 /// |
|
89 /// The item-int map must be initialized in such way that it assigns |
|
90 /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap. |
87 enum State { |
91 enum State { |
88 ///The node is in the heap |
92 IN_HEAP = 0, ///< = 0. |
89 IN_HEAP = 0, |
93 PRE_HEAP = -1, ///< = -1. |
90 ///The node has never been in the heap |
94 POST_HEAP = -2 ///< = -2. |
91 PRE_HEAP = -1, |
|
92 ///The node was in the heap but it got out of it |
|
93 POST_HEAP = -2 |
|
94 }; |
95 }; |
95 |
96 |
96 /// \brief The constructor |
97 /// \brief The constructor |
97 /// |
98 /// |
98 /// \c _iimap should be given to the constructor, since it is |
99 /// \c map should be given to the constructor, since it is |
99 /// used internally to handle the cross references. |
100 /// used internally to handle the cross references. |
100 explicit FibHeap(ItemIntMap &_iimap) |
101 explicit FibHeap(ItemIntMap &map) |
101 : minimum(0), iimap(_iimap), num_items() {} |
102 : _minimum(0), _iim(map), _num() {} |
102 |
103 |
103 /// \brief The constructor |
104 /// \brief The constructor |
104 /// |
105 /// |
105 /// \c _iimap should be given to the constructor, since it is used |
106 /// \c map should be given to the constructor, since it is used |
106 /// internally to handle the cross references. \c _comp is an |
107 /// internally to handle the cross references. \c comp is an |
107 /// object for ordering of the priorities. |
108 /// object for ordering of the priorities. |
108 FibHeap(ItemIntMap &_iimap, const Compare &_comp) |
109 FibHeap(ItemIntMap &map, const Compare &comp) |
109 : minimum(0), iimap(_iimap), comp(_comp), num_items() {} |
110 : _minimum(0), _iim(map), _comp(comp), _num() {} |
110 |
111 |
111 /// \brief The number of items stored in the heap. |
112 /// \brief The number of items stored in the heap. |
112 /// |
113 /// |
113 /// Returns the number of items stored in the heap. |
114 /// Returns the number of items stored in the heap. |
114 int size() const { return num_items; } |
115 int size() const { return _num; } |
115 |
116 |
116 /// \brief Checks if the heap stores no items. |
117 /// \brief Checks if the heap stores no items. |
117 /// |
118 /// |
118 /// Returns \c true if and only if the heap stores no items. |
119 /// Returns \c true if and only if the heap stores no items. |
119 bool empty() const { return num_items==0; } |
120 bool empty() const { return _num==0; } |
120 |
121 |
121 /// \brief Make empty this heap. |
122 /// \brief Make empty this heap. |
122 /// |
123 /// |
123 /// Make empty this heap. It does not change the cross reference |
124 /// Make empty this heap. It does not change the cross reference |
124 /// map. If you want to reuse a heap what is not surely empty you |
125 /// map. If you want to reuse a heap what is not surely empty you |
125 /// should first clear the heap and after that you should set the |
126 /// should first clear the heap and after that you should set the |
126 /// cross reference map for each item to \c PRE_HEAP. |
127 /// cross reference map for each item to \c PRE_HEAP. |
127 void clear() { |
128 void clear() { |
128 container.clear(); minimum = 0; num_items = 0; |
129 _data.clear(); _minimum = 0; _num = 0; |
129 } |
130 } |
130 |
131 |
131 /// \brief \c item gets to the heap with priority \c value independently |
132 /// \brief \c item gets to the heap with priority \c value independently |
132 /// if \c item was already there. |
133 /// if \c item was already there. |
133 /// |
134 /// |
134 /// This method calls \ref push(\c item, \c value) if \c item is not |
135 /// This method calls \ref push(\c item, \c value) if \c item is not |
135 /// stored in the heap and it calls \ref decrease(\c item, \c value) or |
136 /// stored in the heap and it calls \ref decrease(\c item, \c value) or |
136 /// \ref increase(\c item, \c value) otherwise. |
137 /// \ref increase(\c item, \c value) otherwise. |
137 void set (const Item& item, const Prio& value) { |
138 void set (const Item& item, const Prio& value) { |
138 int i=iimap[item]; |
139 int i=_iim[item]; |
139 if ( i >= 0 && container[i].in ) { |
140 if ( i >= 0 && _data[i].in ) { |
140 if ( comp(value, container[i].prio) ) decrease(item, value); |
141 if ( _comp(value, _data[i].prio) ) decrease(item, value); |
141 if ( comp(container[i].prio, value) ) increase(item, value); |
142 if ( _comp(_data[i].prio, value) ) increase(item, value); |
142 } else push(item, value); |
143 } else push(item, value); |
143 } |
144 } |
144 |
145 |
145 /// \brief Adds \c item to the heap with priority \c value. |
146 /// \brief Adds \c item to the heap with priority \c value. |
146 /// |
147 /// |
147 /// Adds \c item to the heap with priority \c value. |
148 /// Adds \c item to the heap with priority \c value. |
148 /// \pre \c item must not be stored in the heap. |
149 /// \pre \c item must not be stored in the heap. |
149 void push (const Item& item, const Prio& value) { |
150 void push (const Item& item, const Prio& value) { |
150 int i=iimap[item]; |
151 int i=_iim[item]; |
151 if ( i < 0 ) { |
152 if ( i < 0 ) { |
152 int s=container.size(); |
153 int s=_data.size(); |
153 iimap.set( item, s ); |
154 _iim.set( item, s ); |
154 store st; |
155 Store st; |
155 st.name=item; |
156 st.name=item; |
156 container.push_back(st); |
157 _data.push_back(st); |
157 i=s; |
158 i=s; |
158 } else { |
159 } else { |
159 container[i].parent=container[i].child=-1; |
160 _data[i].parent=_data[i].child=-1; |
160 container[i].degree=0; |
161 _data[i].degree=0; |
161 container[i].in=true; |
162 _data[i].in=true; |
162 container[i].marked=false; |
163 _data[i].marked=false; |
163 } |
164 } |
164 |
165 |
165 if ( num_items ) { |
166 if ( _num ) { |
166 container[container[minimum].right_neighbor].left_neighbor=i; |
167 _data[_data[_minimum].right_neighbor].left_neighbor=i; |
167 container[i].right_neighbor=container[minimum].right_neighbor; |
168 _data[i].right_neighbor=_data[_minimum].right_neighbor; |
168 container[minimum].right_neighbor=i; |
169 _data[_minimum].right_neighbor=i; |
169 container[i].left_neighbor=minimum; |
170 _data[i].left_neighbor=_minimum; |
170 if ( comp( value, container[minimum].prio) ) minimum=i; |
171 if ( _comp( value, _data[_minimum].prio) ) _minimum=i; |
171 } else { |
172 } else { |
172 container[i].right_neighbor=container[i].left_neighbor=i; |
173 _data[i].right_neighbor=_data[i].left_neighbor=i; |
173 minimum=i; |
174 _minimum=i; |
174 } |
175 } |
175 container[i].prio=value; |
176 _data[i].prio=value; |
176 ++num_items; |
177 ++_num; |
177 } |
178 } |
178 |
179 |
179 /// \brief Returns the item with minimum priority relative to \c Compare. |
180 /// \brief Returns the item with minimum priority relative to \c Compare. |
180 /// |
181 /// |
181 /// This method returns the item with minimum priority relative to \c |
182 /// This method returns the item with minimum priority relative to \c |
182 /// Compare. |
183 /// Compare. |
183 /// \pre The heap must be nonempty. |
184 /// \pre The heap must be nonempty. |
184 Item top() const { return container[minimum].name; } |
185 Item top() const { return _data[_minimum].name; } |
185 |
186 |
186 /// \brief Returns the minimum priority relative to \c Compare. |
187 /// \brief Returns the minimum priority relative to \c Compare. |
187 /// |
188 /// |
188 /// It returns the minimum priority relative to \c Compare. |
189 /// It returns the minimum priority relative to \c Compare. |
189 /// \pre The heap must be nonempty. |
190 /// \pre The heap must be nonempty. |
190 const Prio& prio() const { return container[minimum].prio; } |
191 const Prio& prio() const { return _data[_minimum].prio; } |
191 |
192 |
192 /// \brief Returns the priority of \c item. |
193 /// \brief Returns the priority of \c item. |
193 /// |
194 /// |
194 /// It returns the priority of \c item. |
195 /// It returns the priority of \c item. |
195 /// \pre \c item must be in the heap. |
196 /// \pre \c item must be in the heap. |
196 const Prio& operator[](const Item& item) const { |
197 const Prio& operator[](const Item& item) const { |
197 return container[iimap[item]].prio; |
198 return _data[_iim[item]].prio; |
198 } |
199 } |
199 |
200 |
200 /// \brief Deletes the item with minimum priority relative to \c Compare. |
201 /// \brief Deletes the item with minimum priority relative to \c Compare. |
201 /// |
202 /// |
202 /// This method deletes the item with minimum priority relative to \c |
203 /// This method deletes the item with minimum priority relative to \c |
203 /// Compare from the heap. |
204 /// Compare from the heap. |
204 /// \pre The heap must be non-empty. |
205 /// \pre The heap must be non-empty. |
205 void pop() { |
206 void pop() { |
206 /*The first case is that there are only one root.*/ |
207 /*The first case is that there are only one root.*/ |
207 if ( container[minimum].left_neighbor==minimum ) { |
208 if ( _data[_minimum].left_neighbor==_minimum ) { |
208 container[minimum].in=false; |
209 _data[_minimum].in=false; |
209 if ( container[minimum].degree!=0 ) { |
210 if ( _data[_minimum].degree!=0 ) { |
210 makeroot(container[minimum].child); |
211 makeroot(_data[_minimum].child); |
211 minimum=container[minimum].child; |
212 _minimum=_data[_minimum].child; |
212 balance(); |
213 balance(); |
213 } |
214 } |
214 } else { |
215 } else { |
215 int right=container[minimum].right_neighbor; |
216 int right=_data[_minimum].right_neighbor; |
216 unlace(minimum); |
217 unlace(_minimum); |
217 container[minimum].in=false; |
218 _data[_minimum].in=false; |
218 if ( container[minimum].degree > 0 ) { |
219 if ( _data[_minimum].degree > 0 ) { |
219 int left=container[minimum].left_neighbor; |
220 int left=_data[_minimum].left_neighbor; |
220 int child=container[minimum].child; |
221 int child=_data[_minimum].child; |
221 int last_child=container[child].left_neighbor; |
222 int last_child=_data[child].left_neighbor; |
222 |
223 |
223 makeroot(child); |
224 makeroot(child); |
224 |
225 |
225 container[left].right_neighbor=child; |
226 _data[left].right_neighbor=child; |
226 container[child].left_neighbor=left; |
227 _data[child].left_neighbor=left; |
227 container[right].left_neighbor=last_child; |
228 _data[right].left_neighbor=last_child; |
228 container[last_child].right_neighbor=right; |
229 _data[last_child].right_neighbor=right; |
229 } |
230 } |
230 minimum=right; |
231 _minimum=right; |
231 balance(); |
232 balance(); |
232 } // the case where there are more roots |
233 } // the case where there are more roots |
233 --num_items; |
234 --_num; |
234 } |
235 } |
235 |
236 |
236 /// \brief Deletes \c item from the heap. |
237 /// \brief Deletes \c item from the heap. |
237 /// |
238 /// |
238 /// This method deletes \c item from the heap, if \c item was already |
239 /// This method deletes \c item from the heap, if \c item was already |
239 /// stored in the heap. It is quite inefficient in Fibonacci heaps. |
240 /// stored in the heap. It is quite inefficient in Fibonacci heaps. |
240 void erase (const Item& item) { |
241 void erase (const Item& item) { |
241 int i=iimap[item]; |
242 int i=_iim[item]; |
242 |
243 |
243 if ( i >= 0 && container[i].in ) { |
244 if ( i >= 0 && _data[i].in ) { |
244 if ( container[i].parent!=-1 ) { |
245 if ( _data[i].parent!=-1 ) { |
245 int p=container[i].parent; |
246 int p=_data[i].parent; |
246 cut(i,p); |
247 cut(i,p); |
247 cascade(p); |
248 cascade(p); |
248 } |
249 } |
249 minimum=i; //As if its prio would be -infinity |
250 _minimum=i; //As if its prio would be -infinity |
250 pop(); |
251 pop(); |
251 } |
252 } |
252 } |
253 } |
253 |
254 |
254 /// \brief Decreases the priority of \c item to \c value. |
255 /// \brief Decreases the priority of \c item to \c value. |
255 /// |
256 /// |
256 /// This method decreases the priority of \c item to \c value. |
257 /// This method decreases the priority of \c item to \c value. |
257 /// \pre \c item must be stored in the heap with priority at least \c |
258 /// \pre \c item must be stored in the heap with priority at least \c |
258 /// value relative to \c Compare. |
259 /// value relative to \c Compare. |
259 void decrease (Item item, const Prio& value) { |
260 void decrease (Item item, const Prio& value) { |
260 int i=iimap[item]; |
261 int i=_iim[item]; |
261 container[i].prio=value; |
262 _data[i].prio=value; |
262 int p=container[i].parent; |
263 int p=_data[i].parent; |
263 |
264 |
264 if ( p!=-1 && comp(value, container[p].prio) ) { |
265 if ( p!=-1 && _comp(value, _data[p].prio) ) { |
265 cut(i,p); |
266 cut(i,p); |
266 cascade(p); |
267 cascade(p); |
267 } |
268 } |
268 if ( comp(value, container[minimum].prio) ) minimum=i; |
269 if ( _comp(value, _data[_minimum].prio) ) _minimum=i; |
269 } |
270 } |
270 |
271 |
271 /// \brief Increases the priority of \c item to \c value. |
272 /// \brief Increases the priority of \c item to \c value. |
272 /// |
273 /// |
273 /// This method sets the priority of \c item to \c value. Though |
274 /// This method sets the priority of \c item to \c value. Though |