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 heap
 
    19      is a data structure for storing items with specified values called \e
 
    20      priorities, such that finding the item with minimum priority with respect
 
    21      to \e Compare is efficient. In a heap one can change the priority of an
 
    22      item, add or erase an item, etc.
 
    24      The methods \ref increase and \ref erase are not efficient in a Fibonacci
 
    25      heap. In case of many calls to these operations, it is better to use a
 
    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.
 
    70     FibHeap(ItemIntMap &_iimap) : minimum(0), iimap(_iimap), num_items() {} 
 
    71     FibHeap(ItemIntMap &_iimap, const Compare &_comp) : minimum(0), 
 
    72       iimap(_iimap), comp(_comp), num_items() {}
 
    74     ///The number of items stored in the heap.
 
    77        Returns the number of items stored in the heap.
 
    79     int size() const { return num_items; }
 
    81     ///Checks if the heap stores no items.
 
    84        Returns \c true iff the heap stores no items.
 
    86     bool empty() const { return num_items==0; }
 
    88     ///\c item gets to the heap with priority \c value independently if \c item was already there.
 
    91        This method calls \ref push(\c item, \c value) if \c item is not
 
    92        stored in the heap and it calls \ref decrease(\c item, \c value) or
 
    93        \ref increase(\c item, \c value) otherwise.
 
    95     void set (Item const item, PrioType const value); 
 
    97     ///Adds \c item to the heap with priority \c value. 
 
   100        Adds \c item to the heap with priority \c value. 
 
   101        \pre \c item must not be stored in the heap. 
 
   103     void push (Item const item, PrioType const value);
 
   106     ///Returns the item having the minimum priority w.r.t.  Compare.
 
   109        This method returns the item having the minimum priority w.r.t.  Compare. 
 
   110        \pre The heap must be nonempty.
 
   112     Item top() const { return container[minimum].name; }
 
   115     ///Returns the minimum priority w.r.t.  Compare.
 
   118        It returns the minimum priority w.r.t.  Compare.
 
   119        \pre The heap must be nonempty.
 
   121     PrioType prio() const { return container[minimum].prio; }
 
   124     ///Returns the priority of \c item.
 
   127        It returns the priority of \c item.
 
   128        \pre \c item must be in the heap.
 
   130     PrioType& operator[](const Item& item) { 
 
   131       return container[iimap[item]].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& item) const { 
 
   141       return container[iimap[item]].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); 
 
   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); 
 
   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 there is a need to really \e increase
 
   178        (w.r.t.  Compare) the priority of \c item, because this
 
   179        method is inefficient.
 
   181     void increase (Item item, PrioType const value) {
 
   187     ///Tells if \c item is in, was already in, or has never 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 &item) const {
 
   198 	if ( container[i].in ) i=0;
 
   201       return state_enum(i);
 
   207     void makeroot(int c);
 
   208     void cut(int a, int b);
 
   210     void fuse(int a, int b);
 
   215       friend class FibHeap;
 
   227       store() : parent(-1), child(-1), degree(), marked(false), in(true) {} 
 
   233     // **********************************************************************
 
   235     // **********************************************************************
 
   237   template <typename Item, typename Prio, typename ItemIntMap, 
 
   239   void FibHeap<Item, Prio, ItemIntMap, Compare>::set 
 
   240   (Item const item, PrioType const value) 
 
   243     if ( i >= 0 && container[i].in ) {
 
   244       if ( comp(value, container[i].prio) ) decrease(item, value); 
 
   245       if ( comp(container[i].prio, value) ) increase(item, value); 
 
   246     } else push(item, value);
 
   249   template <typename Item, typename Prio, typename ItemIntMap, 
 
   251   void FibHeap<Item, Prio, ItemIntMap, Compare>::push 
 
   252   (Item const item, PrioType const value) {
 
   255 	int s=container.size();
 
   256 	iimap.set( item, s );	
 
   259 	container.push_back(st);
 
   262 	container[i].parent=container[i].child=-1;
 
   263 	container[i].degree=0;
 
   264 	container[i].in=true;
 
   265 	container[i].marked=false;
 
   269 	container[container[minimum].right_neighbor].left_neighbor=i;
 
   270 	container[i].right_neighbor=container[minimum].right_neighbor;
 
   271 	container[minimum].right_neighbor=i;
 
   272 	container[i].left_neighbor=minimum;
 
   273 	if ( comp( value, container[minimum].prio) ) minimum=i; 
 
   275 	container[i].right_neighbor=container[i].left_neighbor=i;
 
   278       container[i].prio=value;
 
   282   template <typename Item, typename Prio, typename ItemIntMap, 
 
   284   void FibHeap<Item, Prio, ItemIntMap, Compare>::pop() {
 
   285       /*The first case is that there are only one root.*/
 
   286       if ( container[minimum].left_neighbor==minimum ) {
 
   287 	container[minimum].in=false;
 
   288 	if ( container[minimum].degree!=0 ) { 
 
   289 	  makeroot(container[minimum].child);
 
   290 	  minimum=container[minimum].child;
 
   294 	int right=container[minimum].right_neighbor;
 
   296 	container[minimum].in=false;
 
   297 	if ( container[minimum].degree > 0 ) {
 
   298 	  int left=container[minimum].left_neighbor;
 
   299 	  int child=container[minimum].child;
 
   300 	  int last_child=container[child].left_neighbor;
 
   304 	  container[left].right_neighbor=child;
 
   305 	  container[child].left_neighbor=left;
 
   306 	  container[right].left_neighbor=last_child;
 
   307 	  container[last_child].right_neighbor=right;
 
   311       } // the case where there are more roots
 
   316   template <typename Item, typename Prio, typename ItemIntMap, 
 
   318   void FibHeap<Item, Prio, ItemIntMap, Compare>::erase 
 
   322       if ( i >= 0 && container[i].in ) { 	
 
   323 	if ( container[i].parent!=-1 ) {
 
   324 	  int p=container[i].parent;
 
   328 	minimum=i;     //As if its prio would be -infinity
 
   333   template <typename Item, typename Prio, typename ItemIntMap, 
 
   335   void FibHeap<Item, Prio, ItemIntMap, Compare>::decrease 
 
   336   (Item item, PrioType const value) {
 
   338       container[i].prio=value;
 
   339       int p=container[i].parent;
 
   341       if ( p!=-1 && comp(value, container[p].prio) ) {
 
   345       if ( comp(value, container[minimum].prio) ) minimum=i; 
 
   349   template <typename Item, typename Prio, typename ItemIntMap, 
 
   351   void FibHeap<Item, Prio, ItemIntMap, Compare>::balance() {      
 
   353     int maxdeg=int( floor( 2.08*log(double(container.size()))))+1;
 
   355     std::vector<int> A(maxdeg,-1); 
 
   358      *Recall that now minimum does not point to the minimum prio element.
 
   359      *We set minimum to this during balance().
 
   361     int anchor=container[minimum].left_neighbor; 
 
   367 	if ( anchor==active ) end=true;
 
   368 	int d=container[active].degree;
 
   369 	next=container[active].right_neighbor;
 
   372 	  if( comp(container[active].prio, container[A[d]].prio) ) {
 
   385        while ( container[minimum].parent >=0 ) minimum=container[minimum].parent;
 
   389 	 if ( comp(container[s].prio, container[minimum].prio) ) minimum=s;
 
   390 	 s=container[s].right_neighbor;
 
   394   template <typename Item, typename Prio, typename ItemIntMap, 
 
   396   void FibHeap<Item, Prio, ItemIntMap, Compare>::makeroot 
 
   400 	container[s].parent=-1;
 
   401 	s=container[s].right_neighbor;
 
   406   template <typename Item, typename Prio, typename ItemIntMap, 
 
   408   void FibHeap<Item, Prio, ItemIntMap, Compare>::cut 
 
   411      *Replacing a from the children of b.
 
   413     --container[b].degree;
 
   415     if ( container[b].degree !=0 ) {
 
   416       int child=container[b].child;
 
   418 	container[b].child=container[child].right_neighbor;
 
   423     /*Lacing a to the roots.*/
 
   424     int right=container[minimum].right_neighbor;
 
   425     container[minimum].right_neighbor=a;
 
   426     container[a].left_neighbor=minimum;
 
   427     container[a].right_neighbor=right;
 
   428     container[right].left_neighbor=a;
 
   430     container[a].parent=-1;
 
   431     container[a].marked=false;
 
   435   template <typename Item, typename Prio, typename ItemIntMap, 
 
   437   void FibHeap<Item, Prio, ItemIntMap, Compare>::cascade 
 
   440       if ( container[a].parent!=-1 ) {
 
   441 	int p=container[a].parent;
 
   443 	if ( container[a].marked==false ) container[a].marked=true;
 
   452   template <typename Item, typename Prio, typename ItemIntMap, 
 
   454   void FibHeap<Item, Prio, ItemIntMap, Compare>::fuse 
 
   458       /*Lacing b under a.*/
 
   459       container[b].parent=a;
 
   461       if (container[a].degree==0) {
 
   462 	container[b].left_neighbor=b;
 
   463 	container[b].right_neighbor=b;
 
   464 	container[a].child=b;	
 
   466 	int child=container[a].child;
 
   467 	int last_child=container[child].left_neighbor;
 
   468 	container[child].left_neighbor=b;
 
   469 	container[b].right_neighbor=child;
 
   470 	container[last_child].right_neighbor=b;
 
   471 	container[b].left_neighbor=last_child;
 
   474       ++container[a].degree;
 
   476       container[b].marked=false;
 
   481    *It is invoked only if a has siblings.
 
   483   template <typename Item, typename Prio, typename ItemIntMap, 
 
   485   void FibHeap<Item, Prio, ItemIntMap, Compare>::unlace 
 
   487       int leftn=container[a].left_neighbor;
 
   488       int rightn=container[a].right_neighbor;
 
   489       container[leftn].right_neighbor=rightn;
 
   490       container[rightn].left_neighbor=leftn;