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;
 
    65     ///\todo It is use nowhere
 
    66     ///\todo It doesn't conform to the naming conventions.
 
    74     FibHeap(ItemIntMap &_iimap) : minimum(0), iimap(_iimap), num_items() {} 
 
    75     FibHeap(ItemIntMap &_iimap, const Compare &_comp) : minimum(0), 
 
    76       iimap(_iimap), comp(_comp), num_items() {}
 
    78     ///The number of items stored in the heap.
 
    81        Returns the number of items stored in the heap.
 
    83     int size() const { return num_items; }
 
    85     ///Checks if the heap stores no items.
 
    88        Returns \c true iff the heap stores no items.
 
    90     bool empty() const { return num_items==0; }
 
    92     ///\c item gets to the heap with priority \c value independently if \c item was already there.
 
    95        This method calls \ref push(\c item, \c value) if \c item is not
 
    96        stored in the heap and it calls \ref decrease(\c item, \c value) or
 
    97        \ref increase(\c item, \c value) otherwise.
 
    99     void set (Item const item, PrioType const value); 
 
   101     ///Adds \c item to the heap with priority \c value. 
 
   104        Adds \c item to the heap with priority \c value. 
 
   105        \pre \c item must not be stored in the heap. 
 
   107     void push (Item const item, PrioType const value);
 
   110     ///Returns the item having the minimum priority w.r.t.  Compare.
 
   113        This method returns the item having the minimum priority w.r.t.  Compare. 
 
   114        \pre The heap must be nonempty.
 
   116     Item top() const { return container[minimum].name; }
 
   119     ///Returns the minimum priority w.r.t.  Compare.
 
   122        It returns the minimum priority w.r.t.  Compare.
 
   123        \pre The heap must be nonempty.
 
   125     PrioType prio() const { return container[minimum].prio; }
 
   128     ///Returns the priority of \c item.
 
   131        It returns the priority of \c item.
 
   132        \pre \c item must be in the heap.
 
   134     PrioType& operator[](const Item& item) { 
 
   135       return container[iimap[item]].prio; 
 
   138     ///Returns the priority of \c item.
 
   141        It returns the priority of \c item.
 
   142        \pre \c item must be in the heap.
 
   144     const PrioType& operator[](const Item& item) const { 
 
   145       return container[iimap[item]].prio; 
 
   149     ///Deletes the item with minimum priority w.r.t.  Compare.
 
   152     This method deletes the item with minimum priority w.r.t. 
 
   153     Compare from the heap.
 
   154     \pre The heap must be non-empty.
 
   158     ///Deletes \c item from the heap.
 
   161        This method deletes \c item from the heap, if \c item was already
 
   162        stored in the heap. It is quite inefficient in Fibonacci heaps.
 
   164     void erase (const Item& item); 
 
   166     ///Decreases the priority of \c item to \c value.
 
   169        This method decreases the priority of \c item to \c value.
 
   170        \pre \c item must be stored in the heap with priority at least \c
 
   171        value w.r.t.  Compare.
 
   173     void decrease (Item item, PrioType const value); 
 
   176     ///Increases the priority of \c item to \c value.
 
   179        This method sets the priority of \c item to \c value. Though
 
   180        there is no precondition on the priority of \c item, this
 
   181        method should be used only if there is a need to really \e increase
 
   182        (w.r.t.  Compare) the priority of \c item, because this
 
   183        method is inefficient.
 
   185     void increase (Item item, PrioType const value) {
 
   191     ///Tells if \c item is in, was already in, or has never been in the heap.
 
   194        This method returns PRE_HEAP if \c item has never been in the
 
   195        heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
 
   196        otherwise. In the latter case it is possible that \c item will
 
   197        get back to the heap again.
 
   199     state_enum state(const Item &item) const {
 
   202 	if ( container[i].in ) i=0;
 
   205       return state_enum(i);
 
   211     void makeroot(int c);
 
   212     void cut(int a, int b);
 
   214     void fuse(int a, int b);
 
   219       friend class FibHeap;
 
   231       store() : parent(-1), child(-1), degree(), marked(false), in(true) {} 
 
   237     // **********************************************************************
 
   239     // **********************************************************************
 
   241   template <typename Item, typename Prio, typename ItemIntMap, 
 
   243   void FibHeap<Item, Prio, ItemIntMap, Compare>::set 
 
   244   (Item const item, PrioType const value) 
 
   247     if ( i >= 0 && container[i].in ) {
 
   248       if ( comp(value, container[i].prio) ) decrease(item, value); 
 
   249       if ( comp(container[i].prio, value) ) increase(item, value); 
 
   250     } else push(item, value);
 
   253   template <typename Item, typename Prio, typename ItemIntMap, 
 
   255   void FibHeap<Item, Prio, ItemIntMap, Compare>::push 
 
   256   (Item const item, PrioType const value) {
 
   259 	int s=container.size();
 
   260 	iimap.set( item, s );	
 
   263 	container.push_back(st);
 
   266 	container[i].parent=container[i].child=-1;
 
   267 	container[i].degree=0;
 
   268 	container[i].in=true;
 
   269 	container[i].marked=false;
 
   273 	container[container[minimum].right_neighbor].left_neighbor=i;
 
   274 	container[i].right_neighbor=container[minimum].right_neighbor;
 
   275 	container[minimum].right_neighbor=i;
 
   276 	container[i].left_neighbor=minimum;
 
   277 	if ( comp( value, container[minimum].prio) ) minimum=i; 
 
   279 	container[i].right_neighbor=container[i].left_neighbor=i;
 
   282       container[i].prio=value;
 
   286   template <typename Item, typename Prio, typename ItemIntMap, 
 
   288   void FibHeap<Item, Prio, ItemIntMap, Compare>::pop() {
 
   289       /*The first case is that there are only one root.*/
 
   290       if ( container[minimum].left_neighbor==minimum ) {
 
   291 	container[minimum].in=false;
 
   292 	if ( container[minimum].degree!=0 ) { 
 
   293 	  makeroot(container[minimum].child);
 
   294 	  minimum=container[minimum].child;
 
   298 	int right=container[minimum].right_neighbor;
 
   300 	container[minimum].in=false;
 
   301 	if ( container[minimum].degree > 0 ) {
 
   302 	  int left=container[minimum].left_neighbor;
 
   303 	  int child=container[minimum].child;
 
   304 	  int last_child=container[child].left_neighbor;
 
   308 	  container[left].right_neighbor=child;
 
   309 	  container[child].left_neighbor=left;
 
   310 	  container[right].left_neighbor=last_child;
 
   311 	  container[last_child].right_neighbor=right;
 
   315       } // the case where there are more roots
 
   320   template <typename Item, typename Prio, typename ItemIntMap, 
 
   322   void FibHeap<Item, Prio, ItemIntMap, Compare>::erase 
 
   326       if ( i >= 0 && container[i].in ) { 	
 
   327 	if ( container[i].parent!=-1 ) {
 
   328 	  int p=container[i].parent;
 
   332 	minimum=i;     //As if its prio would be -infinity
 
   337   template <typename Item, typename Prio, typename ItemIntMap, 
 
   339   void FibHeap<Item, Prio, ItemIntMap, Compare>::decrease 
 
   340   (Item item, PrioType const value) {
 
   342       container[i].prio=value;
 
   343       int p=container[i].parent;
 
   345       if ( p!=-1 && comp(value, container[p].prio) ) {
 
   349       if ( comp(value, container[minimum].prio) ) minimum=i; 
 
   353   template <typename Item, typename Prio, typename ItemIntMap, 
 
   355   void FibHeap<Item, Prio, ItemIntMap, Compare>::balance() {      
 
   357     int maxdeg=int( floor( 2.08*log(double(container.size()))))+1;
 
   359     std::vector<int> A(maxdeg,-1); 
 
   362      *Recall that now minimum does not point to the minimum prio element.
 
   363      *We set minimum to this during balance().
 
   365     int anchor=container[minimum].left_neighbor; 
 
   371 	if ( anchor==active ) end=true;
 
   372 	int d=container[active].degree;
 
   373 	next=container[active].right_neighbor;
 
   376 	  if( comp(container[active].prio, container[A[d]].prio) ) {
 
   389        while ( container[minimum].parent >=0 ) minimum=container[minimum].parent;
 
   393 	 if ( comp(container[s].prio, container[minimum].prio) ) minimum=s;
 
   394 	 s=container[s].right_neighbor;
 
   398   template <typename Item, typename Prio, typename ItemIntMap, 
 
   400   void FibHeap<Item, Prio, ItemIntMap, Compare>::makeroot 
 
   404 	container[s].parent=-1;
 
   405 	s=container[s].right_neighbor;
 
   410   template <typename Item, typename Prio, typename ItemIntMap, 
 
   412   void FibHeap<Item, Prio, ItemIntMap, Compare>::cut 
 
   415      *Replacing a from the children of b.
 
   417     --container[b].degree;
 
   419     if ( container[b].degree !=0 ) {
 
   420       int child=container[b].child;
 
   422 	container[b].child=container[child].right_neighbor;
 
   427     /*Lacing a to the roots.*/
 
   428     int right=container[minimum].right_neighbor;
 
   429     container[minimum].right_neighbor=a;
 
   430     container[a].left_neighbor=minimum;
 
   431     container[a].right_neighbor=right;
 
   432     container[right].left_neighbor=a;
 
   434     container[a].parent=-1;
 
   435     container[a].marked=false;
 
   439   template <typename Item, typename Prio, typename ItemIntMap, 
 
   441   void FibHeap<Item, Prio, ItemIntMap, Compare>::cascade 
 
   444       if ( container[a].parent!=-1 ) {
 
   445 	int p=container[a].parent;
 
   447 	if ( container[a].marked==false ) container[a].marked=true;
 
   456   template <typename Item, typename Prio, typename ItemIntMap, 
 
   458   void FibHeap<Item, Prio, ItemIntMap, Compare>::fuse 
 
   462       /*Lacing b under a.*/
 
   463       container[b].parent=a;
 
   465       if (container[a].degree==0) {
 
   466 	container[b].left_neighbor=b;
 
   467 	container[b].right_neighbor=b;
 
   468 	container[a].child=b;	
 
   470 	int child=container[a].child;
 
   471 	int last_child=container[child].left_neighbor;
 
   472 	container[child].left_neighbor=b;
 
   473 	container[b].right_neighbor=child;
 
   474 	container[last_child].right_neighbor=b;
 
   475 	container[b].left_neighbor=last_child;
 
   478       ++container[a].degree;
 
   480       container[b].marked=false;
 
   485    *It is invoked only if a has siblings.
 
   487   template <typename Item, typename Prio, typename ItemIntMap, 
 
   489   void FibHeap<Item, Prio, ItemIntMap, Compare>::unlace 
 
   491       int leftn=container[a].left_neighbor;
 
   492       int rightn=container[a].right_neighbor;
 
   493       container[leftn].right_neighbor=rightn;
 
   494       container[rightn].left_neighbor=leftn;