13 namespace hugo { | 
    13 namespace hugo { | 
    14     | 
    14     | 
    15   /// An implementation of the Fibonacci Heap.  | 
    15   /// An implementation of the Fibonacci Heap.  | 
    16   | 
    16   | 
    17   /**  | 
    17   /**  | 
    18      This class implements the \e Fibonacci \e heap data structure. A \e  | 
    18      This class implements the \e Fibonacci \e heap data structure. A \e heap  | 
    19      heap is a data structure for storing items with specified priorities,  | 
    19      is a data structure for storing items with specified values called \e  | 
    20      such that finding the item with minimum priority is efficient. In a  | 
    20      priorities, such that finding the item with minimum priority with respect  | 
    21      heap one can change the priority of an item, and to add or erase an  | 
    21      to \e Compare is efficient. In a heap one can change the priority of an  | 
    22      item.  | 
    22      item, add or erase an item, etc.  | 
    23   | 
    23   | 
    24      The methods \ref increase and \ref erase are not efficient, in  | 
    24      The methods \ref increase and \ref erase are not efficient in a Fibonacci  | 
    25      case of many calls to these operations, it is better to use  | 
    25      heap. In case of many calls to these operations, it is better to use a  | 
    26      a binary heap.  | 
    26      \e binary \e heap.  | 
    27        | 
    27        | 
    28      /param Item The type of the items to be stored.    | 
    28      \param Item The type of the items to be stored.    | 
    29      /param Prio The type of the priority of the items.  | 
    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  | 
    30      \param ItemIntMap A read and writable Item int map, for the usage of  | 
    31      the heap.  | 
    31      the heap.  | 
    32      /param Compare A class for the comparison of the priorities. The  | 
    32      \param Compare A class for the comparison of the priorities. The  | 
    33      default is \c std::less<Prio>.  | 
    33      default is \c std::less<Prio>.  | 
    34   | 
    34   | 
    35   */  | 
    35   */  | 
    36   | 
    36   | 
    37 #ifdef DOXYGEN  | 
    37 #ifdef DOXYGEN  | 
    65       IN_HEAP = 0,  | 
    65       IN_HEAP = 0,  | 
    66       PRE_HEAP = -1,  | 
    66       PRE_HEAP = -1,  | 
    67       POST_HEAP = -2  | 
    67       POST_HEAP = -2  | 
    68     };  | 
    68     };  | 
    69       | 
    69       | 
    70   public :  | 
         | 
    71       | 
         | 
    72     FibHeap(ItemIntMap &_iimap) : minimum(0), iimap(_iimap), num_items() {}  | 
    70     FibHeap(ItemIntMap &_iimap) : minimum(0), iimap(_iimap), num_items() {}  | 
    73     FibHeap(ItemIntMap &_iimap, const Compare &_comp) : minimum(0),   | 
    71     FibHeap(ItemIntMap &_iimap, const Compare &_comp) : minimum(0),   | 
    74       iimap(_iimap), comp(_comp), num_items() {} | 
    72       iimap(_iimap), comp(_comp), num_items() {} | 
    75       | 
    73       | 
    76     ///The number of items stored in the heap.  | 
    74     ///The number of items stored in the heap.  | 
    77   | 
    75   | 
    78     /**  | 
    76     /**  | 
    79     Returns the number of items stored in the heap.  | 
    77        Returns the number of items stored in the heap.  | 
    80     */  | 
    78     */  | 
    81     int size() const { return num_items; } | 
    79     int size() const { return num_items; } | 
    82   | 
    80   | 
    83     ///Checks if the heap stores no items.  | 
    81     ///Checks if the heap stores no items.  | 
    84       | 
    82       | 
    85     /**  | 
    83     /**  | 
    86        Returns true iff the heap stores no items.  | 
    84        Returns \c true iff the heap stores no items.  | 
    87     */  | 
    85     */  | 
    88     bool empty() const { return num_items==0; } | 
    86     bool empty() const { return num_items==0; } | 
    89   | 
    87   | 
    90     ///Item \c item gets to the heap with priority \c value independently if \c item was already there.  | 
    88     ///\c item gets to the heap with priority \c value independently if \c item was already there.  | 
    91   | 
    89   | 
    92     /**  | 
    90     /**  | 
    93        This method calls \ref push(item, value) if \c item is not  | 
    91        This method calls \ref push(\c item, \c value) if \c item is not  | 
    94        stored in the heap, and it calls \ref decrease(it, \c value) or  | 
    92        stored in the heap and it calls \ref decrease(\c item, \c value) or  | 
    95        \ref increase(it, \c value) otherwise.  | 
    93        \ref increase(\c item, \c value) otherwise.  | 
    96     */  | 
    94     */  | 
    97     void set (Item const item, PrioType const value); //vigyazat: az implementacioban it van  | 
    95     void set (Item const item, PrioType const value);   | 
    98       | 
    96       | 
    99     ///Adds \c item to the heap with priority \c value.   | 
    97     ///Adds \c item to the heap with priority \c value.   | 
   100       | 
    98       | 
   101     /**  | 
    99     /**  | 
   102        Adds \c item to the heap with priority \c value.   | 
   100        Adds \c item to the heap with priority \c value.   | 
   103        \pre \c item must not be stored in the heap.   | 
   101        \pre \c item must not be stored in the heap.   | 
   104     */  | 
   102     */  | 
   105     void push (Item const it, PrioType const value); /*vigyazat: az implementacioban it van*/  | 
   103     void push (Item const item, PrioType const value);  | 
   106       | 
   104       | 
   107       | 
   105       | 
   108     ///Returns the item having the minimum priority w.r.t.  Compare.  | 
   106     ///Returns the item having the minimum priority w.r.t.  Compare.  | 
   109       | 
   107       | 
   110     /**  | 
   108     /**  | 
   155   | 
   155   | 
   156     /**  | 
   156     /**  | 
   157        This method deletes \c item from the heap, if \c item was already  | 
   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.  | 
   158        stored in the heap. It is quite inefficient in Fibonacci heaps.  | 
   159     */  | 
   159     */  | 
   160     void erase (const Item& item); /*vigyazat: az implementacioban it van*/  | 
   160     void erase (const Item& item);   | 
   161   | 
   161   | 
   162     ///Decreases the priority of \c item to \c value.  | 
   162     ///Decreases the priority of \c item to \c value.  | 
   163   | 
   163   | 
   164     /**  | 
   164     /**  | 
   165        This method 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  | 
   166        \pre \c item must be stored in the heap with priority at least \c  | 
   167        value w.r.t.  Compare.  | 
   167        value w.r.t.  Compare.  | 
   168     */  | 
   168     */  | 
   169     void decrease (Item item, PrioType const value); /*vigyazat: az implementacioban it van*/  | 
   169     void decrease (Item item, PrioType const value);   | 
   170   | 
   170   | 
   171   | 
   171   | 
   172     ///Increases the priority of \c item to \c value.  | 
   172     ///Increases the priority of \c item to \c value.  | 
   173   | 
   173   | 
   174     /**  | 
   174     /**  | 
   175        This method sets the priority of \c item to \c value. Though  | 
   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  | 
   176        there is no precondition on the priority of \c item, this  | 
   177        method should be used only if one wants to \e increase  | 
   177        method should be used only if there is a need to really \e increase  | 
   178        (w.r.t.  Compare) the priority of \c item, because this  | 
   178        (w.r.t.  Compare) the priority of \c item, because this  | 
   179        method is inefficient.  | 
   179        method is inefficient.  | 
   180     */  | 
   180     */  | 
   181     void increase (Item it, PrioType const value) { | 
   181     void increase (Item item, PrioType const value) { | 
   182       erase(it);  | 
   182       erase(item);  | 
   183       push(it, value);  | 
   183       push(item, value);  | 
   184     }  | 
   184     }  | 
   185   | 
   185   | 
   186   | 
   186   | 
   187     ///Tells if \c item is in, was in, or has not been in the heap.  | 
   187     ///Tells if \c item is in, was already in, or has never been in the heap.  | 
   188   | 
   188   | 
   189     /**  | 
   189     /**  | 
   190        This method returns PRE_HEAP if \c item has never been in the  | 
   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  | 
   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  | 
   192        otherwise. In the latter case it is possible that \c item will  | 
   193        get back to the heap again.  | 
   193        get back to the heap again.  | 
   194     */  | 
   194     */  | 
   195     state_enum state(const Item &it);  /*vigyazat: az implementacioban it van*/  | 
   195     state_enum state(const Item &item) const { | 
   196   | 
   196       int i=iimap[item];  | 
         | 
   197       if( i>=0 ) { | 
         | 
   198 	if ( container[i].in ) i=0;  | 
         | 
   199 	else i=-2;   | 
         | 
   200       }  | 
         | 
   201       return state_enum(i);  | 
         | 
   202     }      | 
         | 
   203       | 
         | 
   204   private:  | 
         | 
   205       | 
         | 
   206     void balance();  | 
         | 
   207     void makeroot(int c);  | 
         | 
   208     void cut(int a, int b);  | 
         | 
   209     void cascade(int a);  | 
         | 
   210     void fuse(int a, int b);  | 
         | 
   211     void unlace(int a);  | 
         | 
   212   | 
         | 
   213   | 
         | 
   214     class store { | 
         | 
   215       friend class FibHeap;  | 
         | 
   216         | 
         | 
   217       Item name;  | 
         | 
   218       int parent;  | 
         | 
   219       int left_neighbor;  | 
         | 
   220       int right_neighbor;  | 
         | 
   221       int child;  | 
         | 
   222       int degree;    | 
         | 
   223       bool marked;  | 
         | 
   224       bool in;  | 
         | 
   225       PrioType prio;  | 
         | 
   226         | 
         | 
   227       store() : parent(-1), child(-1), degree(), marked(false), in(true) {}  | 
         | 
   228     };  | 
         | 
   229   };      | 
         | 
   230    | 
   197   | 
   231   | 
   198   | 
   232   | 
   199     // **********************************************************************  | 
   233     // **********************************************************************  | 
   200     //  IMPLEMENTATIONS  | 
   234     //  IMPLEMENTATIONS  | 
   201     // **********************************************************************  | 
   235     // **********************************************************************  | 
   202       | 
   236       | 
   203   | 
   237   template <typename Item, typename Prio, typename ItemIntMap,   | 
   204     void set (Item const it, PrioType const value) { | 
   238     typename Compare>  | 
   205       int i=iimap[it];  | 
   239   void FibHeap<Item, Prio, ItemIntMap, Compare>::set   | 
   206       if ( i >= 0 && container[i].in ) { | 
   240   (Item const item, PrioType const value)   | 
   207 	if ( comp(value, container[i].prio) ) decrease(it, value);   | 
   241   { | 
   208 	if ( comp(container[i].prio, value) ) increase(it, value);   | 
   242     int i=iimap[item];  | 
   209       } else push(it, value);  | 
   243     if ( i >= 0 && container[i].in ) { | 
   210     }  | 
   244       if ( comp(value, container[i].prio) ) decrease(item, value);   | 
   211       | 
   245       if ( comp(container[i].prio, value) ) increase(item, value);   | 
   212   | 
   246     } else push(item, value);  | 
   213     void push (Item const it, PrioType const value) { | 
   247   }  | 
   214       int i=iimap[it];        | 
   248       | 
         | 
   249   template <typename Item, typename Prio, typename ItemIntMap,   | 
         | 
   250     typename Compare>  | 
         | 
   251   void FibHeap<Item, Prio, ItemIntMap, Compare>::push   | 
         | 
   252   (Item const item, PrioType const value) { | 
         | 
   253       int i=iimap[item];        | 
   215       if ( i < 0 ) { | 
   254       if ( i < 0 ) { | 
   216 	int s=container.size();  | 
   255 	int s=container.size();  | 
   217 	iimap.set( it, s );	  | 
   256 	iimap.set( item, s );	  | 
   218 	store st;  | 
   257 	store st;  | 
   219 	st.name=it;  | 
   258 	st.name=item;  | 
   220 	container.push_back(st);  | 
   259 	container.push_back(st);  | 
   221 	i=s;  | 
   260 	i=s;  | 
   222       } else { | 
   261       } else { | 
   223 	container[i].parent=container[i].child=-1;  | 
   262 	container[i].parent=container[i].child=-1;  | 
   224 	container[i].degree=0;  | 
   263 	container[i].degree=0;  | 
   270 	balance();  | 
   310 	balance();  | 
   271       } // the case where there are more roots  | 
   311       } // the case where there are more roots  | 
   272       --num_items;     | 
   312       --num_items;     | 
   273     }  | 
   313     }  | 
   274   | 
   314   | 
   275       | 
   315   | 
   276     void erase (const Item& it) { | 
   316   template <typename Item, typename Prio, typename ItemIntMap,   | 
   277       int i=iimap[it];  | 
   317     typename Compare>  | 
         | 
   318   void FibHeap<Item, Prio, ItemIntMap, Compare>::erase   | 
         | 
   319   (const Item& item) { | 
         | 
   320       int i=iimap[item];  | 
   278         | 
   321         | 
   279       if ( i >= 0 && container[i].in ) { 	 | 
   322       if ( i >= 0 && container[i].in ) { 	 | 
   280 	if ( container[i].parent!=-1 ) { | 
   323 	if ( container[i].parent!=-1 ) { | 
   281 	  int p=container[i].parent;  | 
   324 	  int p=container[i].parent;  | 
   282 	  cut(i,p);	      | 
   325 	  cut(i,p);	      | 
   283 	  cascade(p);  | 
   326 	  cascade(p);  | 
   284 	}  | 
   327 	}  | 
   285 	minimum=i;     //As if its prio would be -infinity  | 
   328 	minimum=i;     //As if its prio would be -infinity  | 
   286 	pop();  | 
   329 	pop();  | 
   287       }  | 
   330       }  | 
   288     }  | 
   331   }  | 
   289       | 
   332       | 
   290   | 
   333   template <typename Item, typename Prio, typename ItemIntMap,   | 
   291     void decrease (Item it, PrioType const value) { | 
   334     typename Compare>  | 
   292       int i=iimap[it];  | 
   335   void FibHeap<Item, Prio, ItemIntMap, Compare>::decrease   | 
         | 
   336   (Item item, PrioType const value) { | 
         | 
   337       int i=iimap[item];  | 
   293       container[i].prio=value;  | 
   338       container[i].prio=value;  | 
   294       int p=container[i].parent;  | 
   339       int p=container[i].parent;  | 
   295         | 
   340         | 
   296       if ( p!=-1 && comp(value, container[p].prio) ) { | 
   341       if ( p!=-1 && comp(value, container[p].prio) ) { | 
   297 	cut(i,p);	      | 
   342 	cut(i,p);	      | 
   298 	cascade(p);  | 
   343 	cascade(p);  | 
   299       }        | 
   344       }        | 
   300       if ( comp(value, container[minimum].prio) ) minimum=i;   | 
   345       if ( comp(value, container[minimum].prio) ) minimum=i;   | 
   301     }  | 
   346   }  | 
   302      | 
   347    | 
   303   | 
   348   | 
   304     state_enum state(const Item &it) const { | 
   349   template <typename Item, typename Prio, typename ItemIntMap,   | 
   305       int i=iimap[it];  | 
   350     typename Compare>  | 
   306       if( i>=0 ) { | 
   351   void FibHeap<Item, Prio, ItemIntMap, Compare>::balance() {       | 
   307 	if ( container[i].in ) i=0;  | 
         | 
   308 	else i=-2;   | 
         | 
   309       }  | 
         | 
   310       return state_enum(i);  | 
         | 
   311     }  | 
         | 
   312   | 
         | 
   313   | 
         | 
   314   private:  | 
         | 
   315       | 
         | 
   316     void balance() {       | 
         | 
   317   | 
   352   | 
   318     int maxdeg=int( floor( 2.08*log(double(container.size()))))+1;  | 
   353     int maxdeg=int( floor( 2.08*log(double(container.size()))))+1;  | 
   319     | 
   354     | 
   320     std::vector<int> A(maxdeg,-1);   | 
   355     std::vector<int> A(maxdeg,-1);   | 
   321       | 
   356       | 
   354 	 if ( comp(container[s].prio, container[minimum].prio) ) minimum=s;  | 
   389 	 if ( comp(container[s].prio, container[minimum].prio) ) minimum=s;  | 
   355 	 s=container[s].right_neighbor;  | 
   390 	 s=container[s].right_neighbor;  | 
   356        } while ( s != m );  | 
   391        } while ( s != m );  | 
   357     }  | 
   392     }  | 
   358   | 
   393   | 
   359   | 
   394   template <typename Item, typename Prio, typename ItemIntMap,   | 
   360     void makeroot (int c) { | 
   395     typename Compare>  | 
         | 
   396   void FibHeap<Item, Prio, ItemIntMap, Compare>::makeroot   | 
         | 
   397   (int c) { | 
   361       int s=c;  | 
   398       int s=c;  | 
   362       do {   | 
   399       do {   | 
   363 	container[s].parent=-1;  | 
   400 	container[s].parent=-1;  | 
   364 	s=container[s].right_neighbor;  | 
   401 	s=container[s].right_neighbor;  | 
   365       } while ( s != c );  | 
   402       } while ( s != c );  | 
   366     }  | 
   403     }  | 
   367       | 
   404     | 
   368   | 
   405     | 
   369     void cut (int a, int b) {     | 
   406   template <typename Item, typename Prio, typename ItemIntMap,   | 
   370       /*  | 
   407     typename Compare>  | 
   371        *Replacing a from the children of b.  | 
   408   void FibHeap<Item, Prio, ItemIntMap, Compare>::cut   | 
   372        */  | 
   409   (int a, int b) {     | 
   373       --container[b].degree;  | 
   410     /*  | 
   374         | 
   411      *Replacing a from the children of b.  | 
   375       if ( container[b].degree !=0 ) { | 
   412      */  | 
   376 	int child=container[b].child;  | 
   413     --container[b].degree;  | 
   377 	if ( child==a )   | 
   414       | 
   378 	  container[b].child=container[child].right_neighbor;  | 
   415     if ( container[b].degree !=0 ) { | 
   379 	unlace(a);  | 
   416       int child=container[b].child;  | 
   380       }  | 
   417       if ( child==a )   | 
   381         | 
   418 	container[b].child=container[child].right_neighbor;  | 
   382         | 
   419       unlace(a);  | 
   383       /*Lacing a to the roots.*/  | 
   420     }  | 
   384       int right=container[minimum].right_neighbor;  | 
   421       | 
   385       container[minimum].right_neighbor=a;  | 
   422       | 
   386       container[a].left_neighbor=minimum;  | 
   423     /*Lacing a to the roots.*/  | 
   387       container[a].right_neighbor=right;  | 
   424     int right=container[minimum].right_neighbor;  | 
   388       container[right].left_neighbor=a;  | 
   425     container[minimum].right_neighbor=a;  | 
   389   | 
   426     container[a].left_neighbor=minimum;  | 
   390       container[a].parent=-1;  | 
   427     container[a].right_neighbor=right;  | 
   391       container[a].marked=false;  | 
   428     container[right].left_neighbor=a;  | 
   392     }  | 
   429       | 
   393   | 
   430     container[a].parent=-1;  | 
   394   | 
   431     container[a].marked=false;  | 
   395     void cascade (int a)   | 
   432   }  | 
         | 
   433     | 
         | 
   434   | 
         | 
   435   template <typename Item, typename Prio, typename ItemIntMap,   | 
         | 
   436     typename Compare>  | 
         | 
   437   void FibHeap<Item, Prio, ItemIntMap, Compare>::cascade   | 
         | 
   438   (int a)   | 
   396     { | 
   439     { | 
   397       if ( container[a].parent!=-1 ) { | 
   440       if ( container[a].parent!=-1 ) { | 
   398 	int p=container[a].parent;  | 
   441 	int p=container[a].parent;  | 
   399 	  | 
   442 	  | 
   400 	if ( container[a].marked==false ) container[a].marked=true;  | 
   443 	if ( container[a].marked==false ) container[a].marked=true;  | 
   428       ++container[a].degree;  | 
   474       ++container[a].degree;  | 
   429         | 
   475         | 
   430       container[b].marked=false;  | 
   476       container[b].marked=false;  | 
   431     }  | 
   477     }  | 
   432   | 
   478   | 
   433   | 
   479     | 
   434     /*  | 
   480   /*  | 
   435      *It is invoked only if a has siblings.  | 
   481    *It is invoked only if a has siblings.  | 
   436      */  | 
   482    */  | 
   437     void unlace (int a) {       | 
   483   template <typename Item, typename Prio, typename ItemIntMap,   | 
         | 
   484     typename Compare>  | 
         | 
   485   void FibHeap<Item, Prio, ItemIntMap, Compare>::unlace   | 
         | 
   486   (int a) {       | 
   438       int leftn=container[a].left_neighbor;  | 
   487       int leftn=container[a].left_neighbor;  | 
   439       int rightn=container[a].right_neighbor;  | 
   488       int rightn=container[a].right_neighbor;  | 
   440       container[leftn].right_neighbor=rightn;  | 
   489       container[leftn].right_neighbor=rightn;  | 
   441       container[rightn].left_neighbor=leftn;  | 
   490       container[rightn].left_neighbor=leftn;  | 
   442     }  | 
   491   }  | 
   443   | 
         | 
   444   | 
         | 
   445     class store { | 
         | 
   446       friend class FibHeap;  | 
         | 
   447         | 
         | 
   448       Item name;  | 
         | 
   449       int parent;  | 
         | 
   450       int left_neighbor;  | 
         | 
   451       int right_neighbor;  | 
         | 
   452       int child;  | 
         | 
   453       int degree;    | 
         | 
   454       bool marked;  | 
         | 
   455       bool in;  | 
         | 
   456       PrioType prio;  | 
         | 
   457   | 
         | 
   458       store() : parent(-1), child(-1), degree(), marked(false), in(true) {}  | 
         | 
   459     };  | 
         | 
   460       | 
         | 
   461   };  | 
         | 
   462     | 
   492     | 
   463 } //namespace hugo  | 
   493 } //namespace hugo  | 
   464 #endif   | 
   494 #endif   |