00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
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
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
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 }
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;
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
00392
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
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
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
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
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 }
00529
00530 #endif //LEMON_FIB_HEAP_H
00531