00001 #ifndef TI_FIBHEAP_
00002 #define TI_FIBHEAP_
00003
00021 #include <cstddef>
00022 #include <fstream>
00023
00024
00025
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
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
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
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
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
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
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
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 ) 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
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
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
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
00490
00491 if (l->son != NULL) remove_son(l);
00492 if (l->left != f) remove_left(l);
00493
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