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 <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
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
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 }
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;
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
00371
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
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
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
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
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 }
00508
00509
#endif //LEMON_FIB_HEAP_H
00510