Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

fib_heap.h

Go to the documentation of this file.
00001 /* -*- C++ -*-
00002  * lemon/fib_heap.h - Part of LEMON, a generic C++ optimization library
00003  *
00004  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
00005  * (Egervary Research Group on Combinatorial Optimization, EGRES).
00006  *
00007  * Permission to use, modify and distribute this software is granted
00008  * provided that this copyright notice appears in all copies. For
00009  * precise terms see the accompanying LICENSE file.
00010  *
00011  * This software is provided "AS IS" with no warranty of any kind,
00012  * express or implied, and with no claim as to its suitability for any
00013  * purpose.
00014  *
00015  */
00016 
00017 #ifndef LEMON_FIB_HEAP_H
00018 #define LEMON_FIB_HEAP_H
00019 
00023 
00024 #include <vector>
00025 #include <functional>
00026 #include <cmath>
00027 
00028 namespace lemon {
00029   
00032 
00034 
00055  
00056 #ifdef DOXYGEN
00057   template <typename Item, 
00058             typename Prio, 
00059             typename ItemIntMap, 
00060             typename Compare>
00061 #else
00062   template <typename Item, 
00063             typename Prio, 
00064             typename ItemIntMap, 
00065             typename Compare = std::less<Prio> >
00066 #endif
00067   class FibHeap {
00068   public:     
00069     typedef Prio PrioType;
00070     
00071   private:
00072     class store;
00073     
00074     std::vector<store> container;
00075     int minimum;
00076     ItemIntMap &iimap;
00077     Compare comp;
00078     int num_items;
00079     
00080   public:
00082     enum state_enum {
00084       IN_HEAP = 0,
00086       PRE_HEAP = -1,
00088       POST_HEAP = -2
00089     };
00090     
00092 
00097     explicit FibHeap(ItemIntMap &_iimap) 
00098       : minimum(0), iimap(_iimap), num_items() {} 
00099  
00101 
00107     FibHeap(ItemIntMap &_iimap, const Compare &_comp) : minimum(0), 
00108                   iimap(_iimap), comp(_comp), num_items() {}
00109     
00111 
00115     int size() const { return num_items; }
00116 
00118     
00122     bool empty() const { return num_items==0; }
00123 
00125 
00131     void set (Item const item, PrioType const value); 
00132     
00134     
00139     void push (Item const item, PrioType const value);
00140     
00142     
00148     Item top() const { return container[minimum].name; }
00149 
00151 
00156     PrioType prio() const { return container[minimum].prio; }
00157     
00159 
00164     PrioType& operator[](const Item& item) { 
00165       return container[iimap[item]].prio; 
00166     }
00167     
00169     
00174     const PrioType& operator[](const Item& item) const { 
00175       return container[iimap[item]].prio; 
00176     }
00177 
00178 
00180 
00186     void pop();
00187 
00189 
00194     void erase (const Item& item); 
00195 
00197 
00203     void decrease (Item item, PrioType const value); 
00204 
00206 
00214     void increase (Item item, PrioType const value) {
00215       erase(item);
00216       push(item, value);
00217     }
00218 
00219 
00221 
00228     state_enum state(const Item &item) const {
00229       int i=iimap[item];
00230       if( i>=0 ) {
00231         if ( container[i].in ) i=0;
00232         else i=-2; 
00233       }
00234       return state_enum(i);
00235     }    
00236     
00237   private:
00238     
00239     void balance();
00240     void makeroot(int c);
00241     void cut(int a, int b);
00242     void cascade(int a);
00243     void fuse(int a, int b);
00244     void unlace(int a);
00245 
00246 
00247     class store {
00248       friend class FibHeap;
00249       
00250       Item name;
00251       int parent;
00252       int left_neighbor;
00253       int right_neighbor;
00254       int child;
00255       int degree;  
00256       bool marked;
00257       bool in;
00258       PrioType prio;
00259       
00260       store() : parent(-1), child(-1), degree(), marked(false), in(true) {} 
00261     };
00262   };    
00263  
00264 
00265 
00266     // **********************************************************************
00267     //  IMPLEMENTATIONS
00268     // **********************************************************************
00269     
00270   template <typename Item, typename Prio, typename ItemIntMap, 
00271     typename Compare>
00272   void FibHeap<Item, Prio, ItemIntMap, Compare>::set 
00273   (Item const item, PrioType const value) 
00274   {
00275     int i=iimap[item];
00276     if ( i >= 0 && container[i].in ) {
00277       if ( comp(value, container[i].prio) ) decrease(item, value); 
00278       if ( comp(container[i].prio, value) ) increase(item, value); 
00279     } else push(item, value);
00280   }
00281     
00282   template <typename Item, typename Prio, typename ItemIntMap, 
00283     typename Compare>
00284   void FibHeap<Item, Prio, ItemIntMap, Compare>::push 
00285   (Item const item, PrioType const value) {
00286       int i=iimap[item];      
00287       if ( i < 0 ) {
00288         int s=container.size();
00289         iimap.set( item, s );   
00290         store st;
00291         st.name=item;
00292         container.push_back(st);
00293         i=s;
00294       } else {
00295         container[i].parent=container[i].child=-1;
00296         container[i].degree=0;
00297         container[i].in=true;
00298         container[i].marked=false;
00299       }
00300 
00301       if ( num_items ) {
00302         container[container[minimum].right_neighbor].left_neighbor=i;
00303         container[i].right_neighbor=container[minimum].right_neighbor;
00304         container[minimum].right_neighbor=i;
00305         container[i].left_neighbor=minimum;
00306         if ( comp( value, container[minimum].prio) ) minimum=i; 
00307       } else {
00308         container[i].right_neighbor=container[i].left_neighbor=i;
00309         minimum=i;      
00310       }
00311       container[i].prio=value;
00312       ++num_items;
00313     }
00314     
00315   template <typename Item, typename Prio, typename ItemIntMap, 
00316     typename Compare>
00317   void FibHeap<Item, Prio, ItemIntMap, Compare>::pop() {
00318       /*The first case is that there are only one root.*/
00319       if ( container[minimum].left_neighbor==minimum ) {
00320         container[minimum].in=false;
00321         if ( container[minimum].degree!=0 ) { 
00322           makeroot(container[minimum].child);
00323           minimum=container[minimum].child;
00324           balance();
00325         }
00326       } else {
00327         int right=container[minimum].right_neighbor;
00328         unlace(minimum);
00329         container[minimum].in=false;
00330         if ( container[minimum].degree > 0 ) {
00331           int left=container[minimum].left_neighbor;
00332           int child=container[minimum].child;
00333           int last_child=container[child].left_neighbor;
00334         
00335           makeroot(child);
00336           
00337           container[left].right_neighbor=child;
00338           container[child].left_neighbor=left;
00339           container[right].left_neighbor=last_child;
00340           container[last_child].right_neighbor=right;
00341         }
00342         minimum=right;
00343         balance();
00344       } // the case where there are more roots
00345       --num_items;   
00346     }
00347 
00348 
00349   template <typename Item, typename Prio, typename ItemIntMap, 
00350     typename Compare>
00351   void FibHeap<Item, Prio, ItemIntMap, Compare>::erase 
00352   (const Item& item) {
00353       int i=iimap[item];
00354       
00355       if ( i >= 0 && container[i].in ) {        
00356         if ( container[i].parent!=-1 ) {
00357           int p=container[i].parent;
00358           cut(i,p);         
00359           cascade(p);
00360         }
00361         minimum=i;     //As if its prio would be -infinity
00362         pop();
00363       }
00364   }
00365     
00366   template <typename Item, typename Prio, typename ItemIntMap, 
00367     typename Compare>
00368   void FibHeap<Item, Prio, ItemIntMap, Compare>::decrease 
00369   (Item item, PrioType const value) {
00370       int i=iimap[item];
00371       container[i].prio=value;
00372       int p=container[i].parent;
00373       
00374       if ( p!=-1 && comp(value, container[p].prio) ) {
00375         cut(i,p);           
00376         cascade(p);
00377       }      
00378       if ( comp(value, container[minimum].prio) ) minimum=i; 
00379   }
00380  
00381 
00382   template <typename Item, typename Prio, typename ItemIntMap, 
00383     typename Compare>
00384   void FibHeap<Item, Prio, ItemIntMap, Compare>::balance() {      
00385 
00386     int maxdeg=int( std::floor( 2.08*log(double(container.size()))))+1;
00387   
00388     std::vector<int> A(maxdeg,-1); 
00389     
00390     /*
00391      *Recall that now minimum does not point to the minimum prio element.
00392      *We set minimum to this during balance().
00393      */
00394     int anchor=container[minimum].left_neighbor; 
00395     int next=minimum; 
00396     bool end=false; 
00397         
00398        do {
00399         int active=next;
00400         if ( anchor==active ) end=true;
00401         int d=container[active].degree;
00402         next=container[active].right_neighbor;
00403 
00404         while (A[d]!=-1) {        
00405           if( comp(container[active].prio, container[A[d]].prio) ) {
00406             fuse(active,A[d]); 
00407           } else { 
00408             fuse(A[d],active);
00409             active=A[d];
00410           } 
00411           A[d]=-1;
00412           ++d;
00413         }       
00414         A[d]=active;
00415        } while ( !end );
00416 
00417 
00418        while ( container[minimum].parent >=0 ) minimum=container[minimum].parent;
00419        int s=minimum;
00420        int m=minimum;
00421        do {  
00422          if ( comp(container[s].prio, container[minimum].prio) ) minimum=s;
00423          s=container[s].right_neighbor;
00424        } while ( s != m );
00425     }
00426 
00427   template <typename Item, typename Prio, typename ItemIntMap, 
00428     typename Compare>
00429   void FibHeap<Item, Prio, ItemIntMap, Compare>::makeroot 
00430   (int c) {
00431       int s=c;
00432       do {  
00433         container[s].parent=-1;
00434         s=container[s].right_neighbor;
00435       } while ( s != c );
00436     }
00437   
00438   
00439   template <typename Item, typename Prio, typename ItemIntMap, 
00440     typename Compare>
00441   void FibHeap<Item, Prio, ItemIntMap, Compare>::cut 
00442   (int a, int b) {    
00443     /*
00444      *Replacing a from the children of b.
00445      */
00446     --container[b].degree;
00447     
00448     if ( container[b].degree !=0 ) {
00449       int child=container[b].child;
00450       if ( child==a ) 
00451         container[b].child=container[child].right_neighbor;
00452       unlace(a);
00453     }
00454     
00455     
00456     /*Lacing a to the roots.*/
00457     int right=container[minimum].right_neighbor;
00458     container[minimum].right_neighbor=a;
00459     container[a].left_neighbor=minimum;
00460     container[a].right_neighbor=right;
00461     container[right].left_neighbor=a;
00462     
00463     container[a].parent=-1;
00464     container[a].marked=false;
00465   }
00466   
00467 
00468   template <typename Item, typename Prio, typename ItemIntMap, 
00469     typename Compare>
00470   void FibHeap<Item, Prio, ItemIntMap, Compare>::cascade 
00471   (int a) 
00472     {
00473       if ( container[a].parent!=-1 ) {
00474         int p=container[a].parent;
00475         
00476         if ( container[a].marked==false ) container[a].marked=true;
00477         else {
00478           cut(a,p);
00479           cascade(p);
00480         }
00481       }
00482     }
00483 
00484 
00485   template <typename Item, typename Prio, typename ItemIntMap, 
00486     typename Compare>
00487   void FibHeap<Item, Prio, ItemIntMap, Compare>::fuse 
00488   (int a, int b) {
00489       unlace(b);
00490       
00491       /*Lacing b under a.*/
00492       container[b].parent=a;
00493 
00494       if (container[a].degree==0) {
00495         container[b].left_neighbor=b;
00496         container[b].right_neighbor=b;
00497         container[a].child=b;   
00498       } else {
00499         int child=container[a].child;
00500         int last_child=container[child].left_neighbor;
00501         container[child].left_neighbor=b;
00502         container[b].right_neighbor=child;
00503         container[last_child].right_neighbor=b;
00504         container[b].left_neighbor=last_child;
00505       }
00506 
00507       ++container[a].degree;
00508       
00509       container[b].marked=false;
00510     }
00511 
00512   
00513   /*
00514    *It is invoked only if a has siblings.
00515    */
00516   template <typename Item, typename Prio, typename ItemIntMap, 
00517     typename Compare>
00518   void FibHeap<Item, Prio, ItemIntMap, Compare>::unlace 
00519   (int a) {      
00520       int leftn=container[a].left_neighbor;
00521       int rightn=container[a].right_neighbor;
00522       container[leftn].right_neighbor=rightn;
00523       container[rightn].left_neighbor=leftn;
00524   }
00525   
00527 
00528 } //namespace lemon
00529 
00530 #endif //LEMON_FIB_HEAP_H
00531 

Generated on Sat Aug 27 14:14:51 2005 for LEMON by  doxygen 1.4.4