.
3 #ifndef HUGO_FIB_HEAP_H
4 #define HUGO_FIB_HEAP_H
7 ///\brief Fibonacci Heap implementation.
15 /// An implementation of the Fibonacci Heap.
18 This class implements the \e Fibonacci \e heap data structure. A \e
19 heap is a data structure for storing items with specified priorities,
20 such that finding the item with minimum priority is efficient. In a
21 heap one can change the priority of an item, and to add or erase an
24 The methods \ref increase and \ref erase are not efficient, in
25 case of many calls to these operations, it is better to use
28 /param Item The type of the items to be stored.
29 /param Prio The type of the priority of the items.
30 /param ItemIntMap A read and writable Item int map, for the usage of
32 /param Compare A class for the comparison of the priorities. The
33 default is \c std::less<Prio>.
38 template <typename Item,
43 template <typename Item,
46 typename Compare = std::less<Prio> >
50 typedef Prio PrioType;
55 std::vector<store> container;
61 ///\todo It is use nowhere
62 ///\todo It doesn't conform to the naming conventions.
72 FibHeap(ItemIntMap &_iimap) : minimum(0), iimap(_iimap), num_items() {}
73 FibHeap(ItemIntMap &_iimap, const Compare &_comp) : minimum(0),
74 iimap(_iimap), comp(_comp), num_items() {}
76 ///The number of items stored in the heap.
79 Returns the number of items stored in the heap.
81 int size() const { return num_items; }
83 ///Checks if the heap stores no items.
86 Returns true iff the heap stores no items.
88 bool empty() const { return num_items==0; }
90 ///Item \c item gets to the heap with priority \c value independently if \c item was already there.
93 This method calls \ref push(item, value) if \c item is not
94 stored in the heap, and it calls \ref decrease(it, \c value) or
95 \ref increase(it, \c value) otherwise.
97 void set (Item const item, PrioType const value); //vigyazat: az implementacioban it van
99 ///Adds \c item to the heap with priority \c value.
102 Adds \c item to the heap with priority \c value.
103 \pre \c item must not be stored in the heap.
105 void push (Item const it, PrioType const value); /*vigyazat: az implementacioban it van*/
108 ///Returns the item having the minimum priority w.r.t. Compare.
111 This method returns the item having the minimum priority w.r.t. Compare.
112 \pre The heap must be nonempty.
114 Item top() const { return container[minimum].name; }
117 ///Returns the minimum priority w.r.t. Compare.
120 It returns the minimum priority w.r.t. Compare.
121 \pre The heap must be nonempty.
123 PrioType prio() const { return container[minimum].prio; }
126 ///Returns the priority of \c item.
129 It returns the priority of \c item.
130 \pre \c item must be in the heap.
132 PrioType& operator[](const Item& it) { return container[iimap[it]].prio; }
134 ///Returns the priority of \c item.
137 It returns the priority of \c item.
138 \pre \c item must be in the heap.
140 const PrioType& operator[](const Item& it) const {
141 return container[iimap[it]].prio;
145 ///Deletes the item with minimum priority w.r.t. Compare.
148 This method deletes the item with minimum priority w.r.t.
149 Compare from the heap.
150 \pre The heap must be non-empty.
154 ///Deletes \c item from the heap.
157 This method deletes \c item from the heap, if \c item was already
158 stored in the heap. It is quite inefficient in Fibonacci heaps.
160 void erase (const Item& item); /*vigyazat: az implementacioban it van*/
162 ///Decreases the priority of \c item to \c value.
165 This method decreases the priority of \c item to \c value.
166 \pre \c item must be stored in the heap with priority at least \c
167 value w.r.t. Compare.
169 void decrease (Item item, PrioType const value); /*vigyazat: az implementacioban it van*/
172 ///Increases the priority of \c item to \c value.
175 This method sets the priority of \c item to \c value. Though
176 there is no precondition on the priority of \c item, this
177 method should be used only if one wants to \e increase
178 (w.r.t. Compare) the priority of \c item, because this
179 method is inefficient.
181 void increase (Item it, PrioType const value) {
187 ///Tells if \c item is in, was in, or has not been in the heap.
190 This method returns PRE_HEAP if \c item has never been in the
191 heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
192 otherwise. In the latter case it is possible that \c item will
193 get back to the heap again.
195 state_enum state(const Item &it); /*vigyazat: az implementacioban it van*/
199 // **********************************************************************
201 // **********************************************************************
204 void set (Item const it, PrioType const value) {
206 if ( i >= 0 && container[i].in ) {
207 if ( comp(value, container[i].prio) ) decrease(it, value);
208 if ( comp(container[i].prio, value) ) increase(it, value);
209 } else push(it, value);
213 void push (Item const it, PrioType const value) {
216 int s=container.size();
220 container.push_back(st);
223 container[i].parent=container[i].child=-1;
224 container[i].degree=0;
225 container[i].in=true;
226 container[i].marked=false;
230 container[container[minimum].right_neighbor].left_neighbor=i;
231 container[i].right_neighbor=container[minimum].right_neighbor;
232 container[minimum].right_neighbor=i;
233 container[i].left_neighbor=minimum;
234 if ( comp( value, container[minimum].prio) ) minimum=i;
236 container[i].right_neighbor=container[i].left_neighbor=i;
239 container[i].prio=value;
245 /*The first case is that there are only one root.*/
246 if ( container[minimum].left_neighbor==minimum ) {
247 container[minimum].in=false;
248 if ( container[minimum].degree!=0 ) {
249 makeroot(container[minimum].child);
250 minimum=container[minimum].child;
254 int right=container[minimum].right_neighbor;
256 container[minimum].in=false;
257 if ( container[minimum].degree > 0 ) {
258 int left=container[minimum].left_neighbor;
259 int child=container[minimum].child;
260 int last_child=container[child].left_neighbor;
264 container[left].right_neighbor=child;
265 container[child].left_neighbor=left;
266 container[right].left_neighbor=last_child;
267 container[last_child].right_neighbor=right;
271 } // the case where there are more roots
276 void erase (const Item& it) {
279 if ( i >= 0 && container[i].in ) {
280 if ( container[i].parent!=-1 ) {
281 int p=container[i].parent;
285 minimum=i; //As if its prio would be -infinity
291 void decrease (Item it, PrioType const value) {
293 container[i].prio=value;
294 int p=container[i].parent;
296 if ( p!=-1 && comp(value, container[p].prio) ) {
300 if ( comp(value, container[minimum].prio) ) minimum=i;
304 state_enum state(const Item &it) const {
307 if ( container[i].in ) i=0;
310 return state_enum(i);
318 int maxdeg=int( floor( 2.08*log(double(container.size()))))+1;
320 std::vector<int> A(maxdeg,-1);
323 *Recall that now minimum does not point to the minimum prio element.
324 *We set minimum to this during balance().
326 int anchor=container[minimum].left_neighbor;
332 if ( anchor==active ) end=true;
333 int d=container[active].degree;
334 next=container[active].right_neighbor;
337 if( comp(container[active].prio, container[A[d]].prio) ) {
350 while ( container[minimum].parent >=0 ) minimum=container[minimum].parent;
354 if ( comp(container[s].prio, container[minimum].prio) ) minimum=s;
355 s=container[s].right_neighbor;
360 void makeroot (int c) {
363 container[s].parent=-1;
364 s=container[s].right_neighbor;
369 void cut (int a, int b) {
371 *Replacing a from the children of b.
373 --container[b].degree;
375 if ( container[b].degree !=0 ) {
376 int child=container[b].child;
378 container[b].child=container[child].right_neighbor;
383 /*Lacing a to the roots.*/
384 int right=container[minimum].right_neighbor;
385 container[minimum].right_neighbor=a;
386 container[a].left_neighbor=minimum;
387 container[a].right_neighbor=right;
388 container[right].left_neighbor=a;
390 container[a].parent=-1;
391 container[a].marked=false;
397 if ( container[a].parent!=-1 ) {
398 int p=container[a].parent;
400 if ( container[a].marked==false ) container[a].marked=true;
409 void fuse (int a, int b) {
412 /*Lacing b under a.*/
413 container[b].parent=a;
415 if (container[a].degree==0) {
416 container[b].left_neighbor=b;
417 container[b].right_neighbor=b;
418 container[a].child=b;
420 int child=container[a].child;
421 int last_child=container[child].left_neighbor;
422 container[child].left_neighbor=b;
423 container[b].right_neighbor=child;
424 container[last_child].right_neighbor=b;
425 container[b].left_neighbor=last_child;
428 ++container[a].degree;
430 container[b].marked=false;
435 *It is invoked only if a has siblings.
437 void unlace (int a) {
438 int leftn=container[a].left_neighbor;
439 int rightn=container[a].right_neighbor;
440 container[leftn].right_neighbor=rightn;
441 container[rightn].left_neighbor=leftn;
446 friend class FibHeap;
458 store() : parent(-1), child(-1), degree(), marked(false), in(true) {}