3 #ifndef HUGO_FIB_HEAP_H
 
     4 #define HUGO_FIB_HEAP_H
 
     8 ///\brief Fibonacci Heap implementation.
 
    16   /// \addtogroup auxdat
 
    19   /// An implementation of the Fibonacci Heap.
 
    22      This class implements the \e Fibonacci \e heap data structure. A \e heap
 
    23      is a data structure for storing items with specified values called \e
 
    24      priorities, such that finding the item with minimum priority with respect
 
    25      to \e Compare is efficient. In a heap one can change the priority of an
 
    26      item, add or erase an item, etc.
 
    28      The methods \ref increase and \ref erase are not efficient in a Fibonacci
 
    29      heap. In case of many calls to these operations, it is better to use a
 
    32      \param Item The type of the items to be stored.  
 
    33      \param Prio The type of the priority of the items.
 
    34      \param ItemIntMap A read and writable Item int map, for the usage of
 
    36      \param Compare A class for the comparison of the priorities. The
 
    37      default is \c std::less<Prio>.
 
    42   template <typename Item, 
 
    47   template <typename Item, 
 
    50 	    typename Compare = std::less<Prio> >
 
    54     typedef Prio PrioType;
 
    59     std::vector<store> container;
 
    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 \c true iff the heap stores no items.
 
    88     bool empty() const { return num_items==0; }
 
    90     ///\c item gets to the heap with priority \c value independently if \c item was already there.
 
    93        This method calls \ref push(\c item, \c value) if \c item is not
 
    94        stored in the heap and it calls \ref decrease(\c item, \c value) or
 
    95        \ref increase(\c item, \c value) otherwise.
 
    97     void set (Item const item, PrioType const value); 
 
    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 item, PrioType const value);
 
   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& item) { 
 
   133       return container[iimap[item]].prio; 
 
   136     ///Returns the priority of \c item.
 
   139        It returns the priority of \c item.
 
   140        \pre \c item must be in the heap.
 
   142     const PrioType& operator[](const Item& item) const { 
 
   143       return container[iimap[item]].prio; 
 
   147     ///Deletes the item with minimum priority w.r.t.  Compare.
 
   150     This method deletes the item with minimum priority w.r.t. 
 
   151     Compare from the heap.
 
   152     \pre The heap must be non-empty.
 
   156     ///Deletes \c item from the heap.
 
   159        This method deletes \c item from the heap, if \c item was already
 
   160        stored in the heap. It is quite inefficient in Fibonacci heaps.
 
   162     void erase (const Item& item); 
 
   164     ///Decreases the priority of \c item to \c value.
 
   167        This method decreases the priority of \c item to \c value.
 
   168        \pre \c item must be stored in the heap with priority at least \c
 
   169        value w.r.t.  Compare.
 
   171     void decrease (Item item, PrioType const value); 
 
   174     ///Increases the priority of \c item to \c value.
 
   177        This method sets the priority of \c item to \c value. Though
 
   178        there is no precondition on the priority of \c item, this
 
   179        method should be used only if there is a need to really \e increase
 
   180        (w.r.t.  Compare) the priority of \c item, because this
 
   181        method is inefficient.
 
   183     void increase (Item item, PrioType const value) {
 
   189     ///Tells if \c item is in, was already in, or has never been in the heap.
 
   192        This method returns PRE_HEAP if \c item has never been in the
 
   193        heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
 
   194        otherwise. In the latter case it is possible that \c item will
 
   195        get back to the heap again.
 
   197     state_enum state(const Item &item) const {
 
   200 	if ( container[i].in ) i=0;
 
   203       return state_enum(i);
 
   209     void makeroot(int c);
 
   210     void cut(int a, int b);
 
   212     void fuse(int a, int b);
 
   217       friend class FibHeap;
 
   229       store() : parent(-1), child(-1), degree(), marked(false), in(true) {} 
 
   235     // **********************************************************************
 
   237     // **********************************************************************
 
   239   template <typename Item, typename Prio, typename ItemIntMap, 
 
   241   void FibHeap<Item, Prio, ItemIntMap, Compare>::set 
 
   242   (Item const item, PrioType const value) 
 
   245     if ( i >= 0 && container[i].in ) {
 
   246       if ( comp(value, container[i].prio) ) decrease(item, value); 
 
   247       if ( comp(container[i].prio, value) ) increase(item, value); 
 
   248     } else push(item, value);
 
   251   template <typename Item, typename Prio, typename ItemIntMap, 
 
   253   void FibHeap<Item, Prio, ItemIntMap, Compare>::push 
 
   254   (Item const item, PrioType const value) {
 
   257 	int s=container.size();
 
   258 	iimap.set( item, s );	
 
   261 	container.push_back(st);
 
   264 	container[i].parent=container[i].child=-1;
 
   265 	container[i].degree=0;
 
   266 	container[i].in=true;
 
   267 	container[i].marked=false;
 
   271 	container[container[minimum].right_neighbor].left_neighbor=i;
 
   272 	container[i].right_neighbor=container[minimum].right_neighbor;
 
   273 	container[minimum].right_neighbor=i;
 
   274 	container[i].left_neighbor=minimum;
 
   275 	if ( comp( value, container[minimum].prio) ) minimum=i; 
 
   277 	container[i].right_neighbor=container[i].left_neighbor=i;
 
   280       container[i].prio=value;
 
   284   template <typename Item, typename Prio, typename ItemIntMap, 
 
   286   void FibHeap<Item, Prio, ItemIntMap, Compare>::pop() {
 
   287       /*The first case is that there are only one root.*/
 
   288       if ( container[minimum].left_neighbor==minimum ) {
 
   289 	container[minimum].in=false;
 
   290 	if ( container[minimum].degree!=0 ) { 
 
   291 	  makeroot(container[minimum].child);
 
   292 	  minimum=container[minimum].child;
 
   296 	int right=container[minimum].right_neighbor;
 
   298 	container[minimum].in=false;
 
   299 	if ( container[minimum].degree > 0 ) {
 
   300 	  int left=container[minimum].left_neighbor;
 
   301 	  int child=container[minimum].child;
 
   302 	  int last_child=container[child].left_neighbor;
 
   306 	  container[left].right_neighbor=child;
 
   307 	  container[child].left_neighbor=left;
 
   308 	  container[right].left_neighbor=last_child;
 
   309 	  container[last_child].right_neighbor=right;
 
   313       } // the case where there are more roots
 
   318   template <typename Item, typename Prio, typename ItemIntMap, 
 
   320   void FibHeap<Item, Prio, ItemIntMap, Compare>::erase 
 
   324       if ( i >= 0 && container[i].in ) { 	
 
   325 	if ( container[i].parent!=-1 ) {
 
   326 	  int p=container[i].parent;
 
   330 	minimum=i;     //As if its prio would be -infinity
 
   335   template <typename Item, typename Prio, typename ItemIntMap, 
 
   337   void FibHeap<Item, Prio, ItemIntMap, Compare>::decrease 
 
   338   (Item item, PrioType const value) {
 
   340       container[i].prio=value;
 
   341       int p=container[i].parent;
 
   343       if ( p!=-1 && comp(value, container[p].prio) ) {
 
   347       if ( comp(value, container[minimum].prio) ) minimum=i; 
 
   351   template <typename Item, typename Prio, typename ItemIntMap, 
 
   353   void FibHeap<Item, Prio, ItemIntMap, Compare>::balance() {      
 
   355     int maxdeg=int( floor( 2.08*log(double(container.size()))))+1;
 
   357     std::vector<int> A(maxdeg,-1); 
 
   360      *Recall that now minimum does not point to the minimum prio element.
 
   361      *We set minimum to this during balance().
 
   363     int anchor=container[minimum].left_neighbor; 
 
   369 	if ( anchor==active ) end=true;
 
   370 	int d=container[active].degree;
 
   371 	next=container[active].right_neighbor;
 
   374 	  if( comp(container[active].prio, container[A[d]].prio) ) {
 
   387        while ( container[minimum].parent >=0 ) minimum=container[minimum].parent;
 
   391 	 if ( comp(container[s].prio, container[minimum].prio) ) minimum=s;
 
   392 	 s=container[s].right_neighbor;
 
   396   template <typename Item, typename Prio, typename ItemIntMap, 
 
   398   void FibHeap<Item, Prio, ItemIntMap, Compare>::makeroot 
 
   402 	container[s].parent=-1;
 
   403 	s=container[s].right_neighbor;
 
   408   template <typename Item, typename Prio, typename ItemIntMap, 
 
   410   void FibHeap<Item, Prio, ItemIntMap, Compare>::cut 
 
   413      *Replacing a from the children of b.
 
   415     --container[b].degree;
 
   417     if ( container[b].degree !=0 ) {
 
   418       int child=container[b].child;
 
   420 	container[b].child=container[child].right_neighbor;
 
   425     /*Lacing a to the roots.*/
 
   426     int right=container[minimum].right_neighbor;
 
   427     container[minimum].right_neighbor=a;
 
   428     container[a].left_neighbor=minimum;
 
   429     container[a].right_neighbor=right;
 
   430     container[right].left_neighbor=a;
 
   432     container[a].parent=-1;
 
   433     container[a].marked=false;
 
   437   template <typename Item, typename Prio, typename ItemIntMap, 
 
   439   void FibHeap<Item, Prio, ItemIntMap, Compare>::cascade 
 
   442       if ( container[a].parent!=-1 ) {
 
   443 	int p=container[a].parent;
 
   445 	if ( container[a].marked==false ) container[a].marked=true;
 
   454   template <typename Item, typename Prio, typename ItemIntMap, 
 
   456   void FibHeap<Item, Prio, ItemIntMap, Compare>::fuse 
 
   460       /*Lacing b under a.*/
 
   461       container[b].parent=a;
 
   463       if (container[a].degree==0) {
 
   464 	container[b].left_neighbor=b;
 
   465 	container[b].right_neighbor=b;
 
   466 	container[a].child=b;	
 
   468 	int child=container[a].child;
 
   469 	int last_child=container[child].left_neighbor;
 
   470 	container[child].left_neighbor=b;
 
   471 	container[b].right_neighbor=child;
 
   472 	container[last_child].right_neighbor=b;
 
   473 	container[b].left_neighbor=last_child;
 
   476       ++container[a].degree;
 
   478       container[b].marked=false;
 
   483    *It is invoked only if a has siblings.
 
   485   template <typename Item, typename Prio, typename ItemIntMap, 
 
   487   void FibHeap<Item, Prio, ItemIntMap, Compare>::unlace 
 
   489       int leftn=container[a].left_neighbor;
 
   490       int rightn=container[a].right_neighbor;
 
   491       container[leftn].right_neighbor=rightn;
 
   492       container[rightn].left_neighbor=leftn;
 
   499 #endif //HUGO_FIB_HEAP_H