fib_heap.h

Go to the documentation of this file.
00001 /* -*- C++ -*- 00002 * src/lemon/fib_heap.h - Part of LEMON, a generic C++ optimization library 00003 * 00004 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport 00005 * (Egervary Combinatorial Optimization Research Group, 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 <math.h> 00027 00028 namespace lemon { 00029 00032 00034 00053 00054 #ifdef DOXYGEN 00055 template <typename Item, 00056 typename Prio, 00057 typename ItemIntMap, 00058 typename Compare> 00059 #else 00060 template <typename Item, 00061 typename Prio, 00062 typename ItemIntMap, 00063 typename Compare = std::less<Prio> > 00064 #endif 00065 class FibHeap { 00066 public: 00067 typedef Prio PrioType; 00068 00069 private: 00070 class store; 00071 00072 std::vector<store> container; 00073 int minimum; 00074 ItemIntMap &iimap; 00075 Compare comp; 00076 int num_items; 00077 00078 public: 00079 enum state_enum { 00080 IN_HEAP = 0, 00081 PRE_HEAP = -1, 00082 POST_HEAP = -2 00083 }; 00084 00085 FibHeap(ItemIntMap &_iimap) : minimum(0), iimap(_iimap), num_items() {} 00086 FibHeap(ItemIntMap &_iimap, const Compare &_comp) : minimum(0), 00087 iimap(_iimap), comp(_comp), num_items() {} 00088 00090 00094 int size() const { return num_items; } 00095 00097 00101 bool empty() const { return num_items==0; } 00102 00104 00110 void set (Item const item, PrioType const value); 00111 00113 00118 void push (Item const item, PrioType const value); 00119 00121 00127 Item top() const { return container[minimum].name; } 00128 00130 00135 PrioType prio() const { return container[minimum].prio; } 00136 00138 00143 PrioType& operator[](const Item& item) { 00144 return container[iimap[item]].prio; 00145 } 00146 00148 00153 const PrioType& operator[](const Item& item) const { 00154 return container[iimap[item]].prio; 00155 } 00156 00157 00159 00165 void pop(); 00166 00168 00173 void erase (const Item& item); 00174 00176 00182 void decrease (Item item, PrioType const value); 00183 00185 00193 void increase (Item item, PrioType const value) { 00194 erase(item); 00195 push(item, value); 00196 } 00197 00198 00200 00207 state_enum state(const Item &item) const { 00208 int i=iimap[item]; 00209 if( i>=0 ) { 00210 if ( container[i].in ) i=0; 00211 else i=-2; 00212 } 00213 return state_enum(i); 00214 } 00215 00216 private: 00217 00218 void balance(); 00219 void makeroot(int c); 00220 void cut(int a, int b); 00221 void cascade(int a); 00222 void fuse(int a, int b); 00223 void unlace(int a); 00224 00225 00226 class store { 00227 friend class FibHeap; 00228 00229 Item name; 00230 int parent; 00231 int left_neighbor; 00232 int right_neighbor; 00233 int child; 00234 int degree; 00235 bool marked; 00236 bool in; 00237 PrioType prio; 00238 00239 store() : parent(-1), child(-1), degree(), marked(false), in(true) {} 00240 }; 00241 }; 00242 00243 00244 00245 // ********************************************************************** 00246 // IMPLEMENTATIONS 00247 // ********************************************************************** 00248 00249 template <typename Item, typename Prio, typename ItemIntMap, 00250 typename Compare> 00251 void FibHeap<Item, Prio, ItemIntMap, Compare>::set 00252 (Item const item, PrioType const value) 00253 { 00254 int i=iimap[item]; 00255 if ( i >= 0 && container[i].in ) { 00256 if ( comp(value, container[i].prio) ) decrease(item, value); 00257 if ( comp(container[i].prio, value) ) increase(item, value); 00258 } else push(item, value); 00259 } 00260 00261 template <typename Item, typename Prio, typename ItemIntMap, 00262 typename Compare> 00263 void FibHeap<Item, Prio, ItemIntMap, Compare>::push 00264 (Item const item, PrioType const value) { 00265 int i=iimap[item]; 00266 if ( i < 0 ) { 00267 int s=container.size(); 00268 iimap.set( item, s ); 00269 store st; 00270 st.name=item; 00271 container.push_back(st); 00272 i=s; 00273 } else { 00274 container[i].parent=container[i].child=-1; 00275 container[i].degree=0; 00276 container[i].in=true; 00277 container[i].marked=false; 00278 } 00279 00280 if ( num_items ) { 00281 container[container[minimum].right_neighbor].left_neighbor=i; 00282 container[i].right_neighbor=container[minimum].right_neighbor; 00283 container[minimum].right_neighbor=i; 00284 container[i].left_neighbor=minimum; 00285 if ( comp( value, container[minimum].prio) ) minimum=i; 00286 } else { 00287 container[i].right_neighbor=container[i].left_neighbor=i; 00288 minimum=i; 00289 } 00290 container[i].prio=value; 00291 ++num_items; 00292 } 00293 00294 template <typename Item, typename Prio, typename ItemIntMap, 00295 typename Compare> 00296 void FibHeap<Item, Prio, ItemIntMap, Compare>::pop() { 00297 /*The first case is that there are only one root.*/ 00298 if ( container[minimum].left_neighbor==minimum ) { 00299 container[minimum].in=false; 00300 if ( container[minimum].degree!=0 ) { 00301 makeroot(container[minimum].child); 00302 minimum=container[minimum].child; 00303 balance(); 00304 } 00305 } else { 00306 int right=container[minimum].right_neighbor; 00307 unlace(minimum); 00308 container[minimum].in=false; 00309 if ( container[minimum].degree > 0 ) { 00310 int left=container[minimum].left_neighbor; 00311 int child=container[minimum].child; 00312 int last_child=container[child].left_neighbor; 00313 00314 makeroot(child); 00315 00316 container[left].right_neighbor=child; 00317 container[child].left_neighbor=left; 00318 container[right].left_neighbor=last_child; 00319 container[last_child].right_neighbor=right; 00320 } 00321 minimum=right; 00322 balance(); 00323 } // the case where there are more roots 00324 --num_items; 00325 } 00326 00327 00328 template <typename Item, typename Prio, typename ItemIntMap, 00329 typename Compare> 00330 void FibHeap<Item, Prio, ItemIntMap, Compare>::erase 00331 (const Item& item) { 00332 int i=iimap[item]; 00333 00334 if ( i >= 0 && container[i].in ) { 00335 if ( container[i].parent!=-1 ) { 00336 int p=container[i].parent; 00337 cut(i,p); 00338 cascade(p); 00339 } 00340 minimum=i; //As if its prio would be -infinity 00341 pop(); 00342 } 00343 } 00344 00345 template <typename Item, typename Prio, typename ItemIntMap, 00346 typename Compare> 00347 void FibHeap<Item, Prio, ItemIntMap, Compare>::decrease 00348 (Item item, PrioType const value) { 00349 int i=iimap[item]; 00350 container[i].prio=value; 00351 int p=container[i].parent; 00352 00353 if ( p!=-1 && comp(value, container[p].prio) ) { 00354 cut(i,p); 00355 cascade(p); 00356 } 00357 if ( comp(value, container[minimum].prio) ) minimum=i; 00358 } 00359 00360 00361 template <typename Item, typename Prio, typename ItemIntMap, 00362 typename Compare> 00363 void FibHeap<Item, Prio, ItemIntMap, Compare>::balance() { 00364 00365 int maxdeg=int( floor( 2.08*log(double(container.size()))))+1; 00366 00367 std::vector<int> A(maxdeg,-1); 00368 00369 /* 00370 *Recall that now minimum does not point to the minimum prio element. 00371 *We set minimum to this during balance(). 00372 */ 00373 int anchor=container[minimum].left_neighbor; 00374 int next=minimum; 00375 bool end=false; 00376 00377 do { 00378 int active=next; 00379 if ( anchor==active ) end=true; 00380 int d=container[active].degree; 00381 next=container[active].right_neighbor; 00382 00383 while (A[d]!=-1) { 00384 if( comp(container[active].prio, container[A[d]].prio) ) { 00385 fuse(active,A[d]); 00386 } else { 00387 fuse(A[d],active); 00388 active=A[d]; 00389 } 00390 A[d]=-1; 00391 ++d; 00392 } 00393 A[d]=active; 00394 } while ( !end ); 00395 00396 00397 while ( container[minimum].parent >=0 ) minimum=container[minimum].parent; 00398 int s=minimum; 00399 int m=minimum; 00400 do { 00401 if ( comp(container[s].prio, container[minimum].prio) ) minimum=s; 00402 s=container[s].right_neighbor; 00403 } while ( s != m ); 00404 } 00405 00406 template <typename Item, typename Prio, typename ItemIntMap, 00407 typename Compare> 00408 void FibHeap<Item, Prio, ItemIntMap, Compare>::makeroot 00409 (int c) { 00410 int s=c; 00411 do { 00412 container[s].parent=-1; 00413 s=container[s].right_neighbor; 00414 } while ( s != c ); 00415 } 00416 00417 00418 template <typename Item, typename Prio, typename ItemIntMap, 00419 typename Compare> 00420 void FibHeap<Item, Prio, ItemIntMap, Compare>::cut 00421 (int a, int b) { 00422 /* 00423 *Replacing a from the children of b. 00424 */ 00425 --container[b].degree; 00426 00427 if ( container[b].degree !=0 ) { 00428 int child=container[b].child; 00429 if ( child==a ) 00430 container[b].child=container[child].right_neighbor; 00431 unlace(a); 00432 } 00433 00434 00435 /*Lacing a to the roots.*/ 00436 int right=container[minimum].right_neighbor; 00437 container[minimum].right_neighbor=a; 00438 container[a].left_neighbor=minimum; 00439 container[a].right_neighbor=right; 00440 container[right].left_neighbor=a; 00441 00442 container[a].parent=-1; 00443 container[a].marked=false; 00444 } 00445 00446 00447 template <typename Item, typename Prio, typename ItemIntMap, 00448 typename Compare> 00449 void FibHeap<Item, Prio, ItemIntMap, Compare>::cascade 00450 (int a) 00451 { 00452 if ( container[a].parent!=-1 ) { 00453 int p=container[a].parent; 00454 00455 if ( container[a].marked==false ) container[a].marked=true; 00456 else { 00457 cut(a,p); 00458 cascade(p); 00459 } 00460 } 00461 } 00462 00463 00464 template <typename Item, typename Prio, typename ItemIntMap, 00465 typename Compare> 00466 void FibHeap<Item, Prio, ItemIntMap, Compare>::fuse 00467 (int a, int b) { 00468 unlace(b); 00469 00470 /*Lacing b under a.*/ 00471 container[b].parent=a; 00472 00473 if (container[a].degree==0) { 00474 container[b].left_neighbor=b; 00475 container[b].right_neighbor=b; 00476 container[a].child=b; 00477 } else { 00478 int child=container[a].child; 00479 int last_child=container[child].left_neighbor; 00480 container[child].left_neighbor=b; 00481 container[b].right_neighbor=child; 00482 container[last_child].right_neighbor=b; 00483 container[b].left_neighbor=last_child; 00484 } 00485 00486 ++container[a].degree; 00487 00488 container[b].marked=false; 00489 } 00490 00491 00492 /* 00493 *It is invoked only if a has siblings. 00494 */ 00495 template <typename Item, typename Prio, typename ItemIntMap, 00496 typename Compare> 00497 void FibHeap<Item, Prio, ItemIntMap, Compare>::unlace 00498 (int a) { 00499 int leftn=container[a].left_neighbor; 00500 int rightn=container[a].right_neighbor; 00501 container[leftn].right_neighbor=rightn; 00502 container[rightn].left_neighbor=leftn; 00503 } 00504 00506 00507 } //namespace lemon 00508 00509 #endif //LEMON_FIB_HEAP_H 00510

Generated on Thu Sep 30 12:18:33 2004 for LEMON by doxygen 1.3.8