fibheap.H

Go to the documentation of this file.
00001 #ifndef TI_FIBHEAP_
00002 #define TI_FIBHEAP_
00003 
00021 #include <cstddef>
00022 #include <fstream>
00023 
00024 //#define PEDANDIC_FIBHEAP
00025 //#define FIBNODE_POOL
00026 
00027 typedef size_t size_type;
00028 
00029 
00030 #if defined(ASM_CMOV) && (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 3)
00031  #warning "using asm_ifaeqbsetac(a,b,c)"
00032  #define asm_ifaeqbsetac(a,b,c) \
00033    asm ( \
00034     "cmpl %[B],%[A]\n\t" \
00035     "cmovel %[C],%[A]\n\t" \
00036     : [A] "+r" (a) : [B] "g" (b), [C] "g" (c) : "cc");
00037 #endif
00038 
00039 
00040 template <class Data> class FibNode
00041 {
00042   //  friend class FibHeap<Data>;
00043 public:
00044   FibNode<Data> *father, *son, *left, *right;
00045   size_type rank;
00046   Data data;
00047   bool mark;
00048 };
00049 
00050 
00051 #ifdef FIBNODE_POOL
00052 // fibnodes have their own pool
00053 template <class T> class CPool
00054 {
00055 private:
00056   T** pool;
00057   unsigned int poolsize;
00058   unsigned int poolpos;
00059 
00060 public:
00061   inline explicit CPool(int _poolsize = 1024) : poolsize(_poolsize) 
00062    {
00063      pool = new T*[poolsize];
00064      for (unsigned int i=0; i<poolsize; ++i) pool[i] = new T;
00065      poolpos=poolsize;
00066    }
00067 
00068   inline ~CPool()
00069    {
00070      cout << "CPool destructor called " << poolpos << "/" << poolsize << endl;
00071      for (unsigned int i=0; i<poolpos; ++i) delete pool[i];
00072      delete [] pool;
00073    }
00074 
00075   inline T* const new_node(void)
00076    {
00077      if (poolpos) return pool[--poolpos];
00078      else
00079       {
00080         const unsigned int oldsize = poolsize;
00081         poolsize = (oldsize<<1) - (oldsize>>1);
00082         cout << "Pool empty, increasing Poolsize to "<< poolsize << endl;
00083         delete [] pool;
00084         pool = new T*[poolsize];
00085         poolpos=poolsize-oldsize;
00086         for (unsigned int i=0; i<poolpos; ++i) pool[i] = new T;
00087         return pool[--poolpos];
00088       }
00089    }
00090 
00091   inline void release_node(T* node)
00092    {
00093      if (poolpos<poolsize) pool[poolpos++]=node;
00094      else
00095       {
00096         cout << "Pool full, this should not happen!" << endl;
00097         delete node;
00098       }
00099    }
00100 };
00101 
00102 #else
00103 // fibnodes handled by normal memory management
00104 template <class T> class CPool
00105 {
00106 public:
00107   inline T* new_node(void) const
00108    {
00109      return new T;
00110    }
00111 
00112   inline void release_node(T* node) const
00113    {
00114      delete node;
00115    }
00116 };
00117 #endif
00118 
00119 
00120 template <class Data> class FibHeap : protected CPool<FibNode<Data> >
00121 {
00122 private:
00123   FibNode<Data> *min;
00124   size_type heapsize;
00125 
00126   const FibNode<Data> * next(const FibNode<Data> *act, const bool down = true) const;
00127   const FibNode<Data> * search(const Data &d) const;
00128   void remove_son(FibNode<Data> * const n);
00129   void remove_left(FibNode<Data> * const n);
00130   void remove_all(void);
00131   void move_up(FibNode<Data> * const n);
00132 
00133 public:
00134   inline FibHeap(void) : min(NULL), heapsize(0) { }
00135   ~FibHeap(void);
00136   void clear(void);
00137   void init(void);
00138   void insert(const Data &d);
00139   inline void push(const Data &d) { insert(d); }
00140   inline const Data& get_min(void) const { return min->data; }
00141   inline const Data& top(void) const { return min->data; }
00142   void delete_min(void);
00143   inline void pop(void) { delete_min(); }
00144   inline size_type size(void) const { return heapsize; }
00145   inline bool empty(void) const { return heapsize==0; }
00146   void change(const Data &old_data, const Data &new_data);
00147   void remove(const Data &d);
00148   void dump(std::ofstream &f);
00149   void dump_tree(std::ofstream &f);
00150 };
00151 
00152 
00153 template <class Data>
00154 void FibHeap<Data>::init(void)
00155 {
00156   remove_all();
00157 }
00158 
00159 template <class Data>
00160 FibHeap<Data>::~FibHeap(void)
00161 {
00162   init();
00163 }
00164 
00165 template <class Data>
00166 void FibHeap<Data>::clear(void)
00167 {
00168   init();
00169 }
00170 
00171 template <class Data>
00172 void FibHeap<Data>::insert(const Data &d)
00173 {
00174   FibNode<Data> * const tmp = this->new_node();
00175   ++heapsize;
00176   tmp->data = d;
00177   tmp->rank = 0;
00178   tmp->mark = false;
00179   tmp->father = tmp->son = NULL;
00180   if (min == NULL) {
00181     tmp->left = tmp->right = tmp;
00182     min = tmp;
00183   } else {
00184     tmp->left = min->left;
00185     min->left = tmp;
00186     tmp->left->right = tmp;
00187     tmp->right = min;
00188     if (tmp->data < min->data) min = tmp;
00189   }
00190 }
00191 
00192 
00193 template <class Data>
00194 void FibHeap<Data>::delete_min(void)
00195 {
00196   if (heapsize == 0) return;
00197   heapsize--;
00198   if (heapsize == 0) {
00199     release_node(min);
00200     min = NULL;
00201     return;
00202   }
00203 
00204   FibNode<Data> *tmp;
00205 
00206   if (min->son == NULL) {
00207     min->left->right = min->right;
00208     min->right->left = min->left;
00209     tmp = min->left;
00210     release_node(min);
00211   } else {
00212     tmp = min->son;
00213     if (min->left == min) {
00214       release_node(min);
00215     } else {
00216       tmp->left->right = min->right;
00217       min->right->left = tmp->left;
00218       min->left->right = tmp;
00219       tmp->left = min->left;
00220       release_node(min);
00221     }
00222   }
00223   min = tmp;
00224 
00225 #ifdef PEDANDIC_FIBHEAP
00226   size_type s, logsize;
00227   logsize=1;
00228   s=heapsize;
00229   while(s>0) { ++logsize; s>>=1; }
00230   // logsize is log2(heapsize) and rank <= 1.44 * logsize
00231   FibNode<Data> **rank_array = new FibNode<Data>*[2*logsize];
00232   for (s=0; s<2*logsize; s+=1) rank_array[s] = NULL;
00233 #else
00234   FibNode<Data>* rank_array[48] = { NULL };
00235   // should be sufficiently large for any "standard" 32-bit-computer!
00236 #endif
00237 
00238   FibNode<Data> *next = tmp;
00239   FibNode<Data> *tmp2;
00240 
00241   do
00242   {
00243     tmp = next;
00244     next = next->left;
00245     tmp->father = NULL;
00246     if (tmp->data < min->data) min = tmp;
00247     while (((tmp2=rank_array[tmp->rank])!=NULL) && (tmp2!=tmp))
00248      {
00249        // join tmp2 and tmp to rank+1 tree
00250        rank_array[tmp->rank]=NULL;
00251        if (tmp2->data < tmp->data)
00252         {
00253           register FibNode<Data>* const tmp3 = tmp2;
00254           tmp2 = tmp;
00255           tmp  = tmp3;
00256         }
00257 
00258       tmp2->left->right = tmp2->right;
00259       tmp2->right->left = tmp2->left;
00260 #if defined(asm_ifaeqbsetac)
00261       asm_ifaeqbsetac(next,tmp2,tmp2->left);
00262       asm_ifaeqbsetac(min,tmp2,tmp);
00263 #else
00264       if (next == tmp2) next = tmp2->left;
00265       if (min  == tmp2) min = tmp;
00266 #endif
00267       tmp2->father = tmp;
00268       tmp->rank+=1;
00269       tmp->mark = false;
00270 
00271       // insert tmp2 in tmp->son list
00272       if (tmp->son == NULL)
00273        {
00274          tmp->son = tmp2;
00275          tmp2->left = tmp2->right = tmp2;
00276        }
00277       else
00278        {
00279          tmp->son->left->right = tmp2;
00280          tmp2->right = tmp->son;
00281          tmp2->left = tmp->son->left;
00282          tmp->son->left = tmp2;
00283        }
00284      }
00285     rank_array[tmp->rank]=tmp;
00286   } while (tmp2!=tmp);
00287 
00288 #ifdef PEDANTIC_FIBHEAP
00289   delete [] rank_array;
00290 #endif
00291 }
00292 
00293 
00294 template <class Data>
00295 void FibHeap<Data>::change(const Data &old_data, const Data &new_data)
00296 {
00297   FibNode<Data> * const tmp = search(old_data);
00298   if (tmp == NULL) return;
00299 
00300   if (old_data<new_data) {
00301     remove(old_data);
00302     insert(new_data);
00303     return;
00304   }
00305 
00306   tmp->data = new_data;
00307   if (old_data == new_data) return;
00308   if (tmp->father) {
00309     move_up(tmp);
00310   }
00311   if (new_data < min->data) min = tmp;
00312 
00313 }
00314 
00315 template <class Data>
00316 void FibHeap<Data>::remove(const Data &d)
00317 {
00318   FibNode<Data> * const tmp = search(d);
00319   if (tmp==NULL) return;
00320   if (tmp->father) {
00321     move_up(tmp);
00322   }
00323   min = tmp;
00324   delete_min();
00325 }
00326 
00327 template <class Data>
00328 const FibNode<Data>* FibHeap<Data>::search(const Data &d) const
00329 {
00330   const FibNode<Data>* tmp = min;
00331   if (tmp == NULL) return NULL;
00332   do {
00333     if (tmp->data == d) return tmp;
00334     tmp = next(tmp, !(d < tmp->data));
00335   } while (tmp != NULL);
00336   return NULL;
00337 }
00338 
00339 template <class Data>
00340 void FibHeap<Data>::move_up(FibNode<Data> * const n)
00341 {
00342   if (n == NULL) return;
00343   FibNode<Data> * const f = n->father;
00344   if (f == NULL) return;
00345 
00346   n->father = NULL;
00347   f->rank-=1;
00348   if (n->left == n) {
00349     f->son = NULL;
00350   } else {
00351     if (f->son == n) f->son = n->left;
00352     n->left->right = n->right;
00353     n->right->left = n->left;
00354   }
00355   n->left = min;
00356   n->right = min->right;
00357   n->right->left = n;
00358   min->right = n;
00359   if (f->mark) {
00360     move_up(f);
00361   } else {
00362     f->mark = true;
00363   }
00364 }
00365 
00366 template <class Data>
00367 const FibNode<Data> * FibHeap<Data>::next(const FibNode<Data> *act, const bool down /* =true */) const
00368 {
00369   if (down && (act->son != NULL)) return act->son;
00370   if ((act->father != NULL) 
00371       && (act->father->son != act->left))
00372     return act->left;
00373   if (act->father == NULL) {
00374     if (act->left == min) return NULL;
00375     else return act->left;
00376   }
00377   while ((act->father != NULL) && (act->father->son == act->left)) {
00378     act = act->father;
00379   }
00380   if ((act->father == NULL) && (act->left == min)) return NULL;
00381   return act->left;
00382 }
00383 
00384 template <class Data>
00385 void FibHeap<Data>::dump(std::ofstream &f)
00386 {
00387   using std::endl;
00388   FibNode<Data> *tmp;
00389   size_type nr;
00390 
00391   f << "graph [" << endl << "directed 1" <<endl;
00392   
00393   tmp = min;
00394   nr = 0;
00395   while (tmp != NULL) {
00396     f << "node [" << endl;
00397     f << "id " << static_cast<unsigned long>(tmp) << endl;
00398     f << "label \"" << tmp->data << "\""<< endl;
00399     f << "]" << endl;
00400     if (tmp->son != NULL) {
00401       f << "edge [" << endl;
00402       f << "label \"s\"" << endl;
00403       f << "source " << static_cast<unsigned long>(tmp) << endl;
00404       f << "target " << static_cast<unsigned long>(tmp->son) << endl;
00405       f << "]" << endl;
00406     }
00407     if (tmp->father != NULL) {
00408       f << "edge [" << endl;
00409       f << "label \"f\"" << endl;
00410       f << "source " << static_cast<unsigned long>(tmp) << endl;
00411       f << "target " << static_cast<unsigned long>(tmp->father) << endl;
00412       f << "]" << endl;
00413     }
00414     if (tmp->left != NULL) {
00415       f << "edge [" << endl;
00416       f << "label \"l\"" << endl;
00417       f << "source " << static_cast<unsigned long>(tmp) << endl;
00418       f << "target " << static_cast<unsigned long>(tmp->left) << endl;
00419       f << "]" << endl;
00420     }
00421     if (tmp->right != NULL) {
00422       f << "edge [" << endl;
00423       f << "label \"r\"" << endl;
00424       f << "source " << static_cast<unsigned long>(tmp) << endl;
00425       f << "target " << static_cast<unsigned long>(tmp->right) << endl;
00426       f << "]" << endl;
00427     }
00428     
00429     nr +=1;
00430     tmp = next(tmp);
00431   }
00432   f << "]" << endl;
00433 }
00434 
00435 template <class Data>
00436 void FibHeap<Data>::dump_tree(std::ofstream &f)
00437 {
00438   using std::endl;
00439   FibNode<Data> *tmp;
00440   size_type nr;
00441 
00442   f << "graph [" << endl << "directed 1" << endl;
00443   f << "node [" << endl;
00444   f << "id 0" << endl;
00445   f << "label \"Wood\"" << endl;
00446   f << "]" << endl;
00447   
00448   tmp = min;
00449   nr = 0;
00450   while (tmp != NULL) {
00451     f << "node [" << endl;
00452     f << "id " << static_cast<unsigned long>(tmp) << endl;
00453     f << "label \"" << tmp->data << "\""<< endl;
00454     f << "]" << endl;
00455     f << "edge [" << endl;
00456     f << "source " << static_cast<unsigned long>(tmp->father) << endl;
00457     f << "target " << static_cast<unsigned long>(tmp) << endl;
00458     f << "]" << endl;
00459     nr +=1;
00460     tmp = next(tmp);
00461   }
00462   f << "]" << endl;
00463 }
00464 
00465 template <class Data>
00466 void FibHeap<Data>::remove_son(FibNode<Data> * const n)
00467 {
00468   // remove sons of *n
00469   FibNode<Data> * const s = n->son;
00470 
00471   if (s == NULL) return;
00472   if (s->son != NULL) remove_son(s);
00473   if (s->left != s) remove_left(s);
00474   // s is only son of n
00475   release_node(s);
00476   n->son=NULL;
00477   heapsize--;
00478 }
00479 
00480 template <class Data>
00481 void FibHeap<Data>::remove_left(FibNode<Data> * const n)
00482 {
00483   // remove siblings of *n
00484   FibNode<Data> * const l=n->left;
00485   const FibNode<Data> *f=n->father;
00486 
00487   if (f == NULL) f=min;
00488   else f=f->son;
00489   // f is the first of the siblings
00490 
00491   if (l->son != NULL) remove_son(l);
00492   if (l->left != f) remove_left(l);
00493   // l is last sibling of n and without sons
00494   n->left=l->left;
00495   l->left->right=n;
00496   release_node(l);
00497   heapsize--;
00498 }
00499 
00500 template <class Data>
00501 void FibHeap<Data>::remove_all(void)
00502 {
00503   if (heapsize == 0) return;
00504   remove_son(min);
00505   remove_left(min);
00506   release_node(min);
00507   min = NULL;
00508   heapsize--;
00509 }
00510 
00511 #endif

Generated on Wed Nov 7 23:29:25 2007 for Qsieve by  doxygen 1.5.4