Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef _CHOMP_STRUCT_FIBHEAP_H_
00036 #define _CHOMP_STRUCT_FIBHEAP_H_
00037
00038
00039 #include "chomp/struct/multitab.h"
00040
00041
00042
00043 namespace chomp {
00044 namespace homology {
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 template <class element>
00063 class FibonacciHeap
00064 {
00065 public:
00066
00067 typedef int_t NodePtr;
00068
00069
00070 static const int_t NullPtr;
00071
00072 private:
00073
00074
00075 struct Node
00076 {
00077
00078
00079 element key;
00080
00081
00082
00083
00084 bool mark;
00085
00086
00087
00088
00089 int_t degree;
00090
00091
00092 int_t number;
00093
00094
00095 NodePtr parent;
00096
00097
00098 NodePtr child;
00099
00100
00101 NodePtr left;
00102
00103
00104 NodePtr right;
00105 };
00106
00107 public:
00108
00109
00110 FibonacciHeap (int_t maxSize = 0);
00111
00112
00113 ~FibonacciHeap ();
00114
00115
00116
00117
00118
00119 int_t Insert (const element &value);
00120
00121
00122
00123 int_t Minimum () const;
00124
00125
00126 const element &Value (int_t number) const;
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 element ExtractMinimum ();
00138
00139
00140
00141 void DecreaseKey (int_t number, const element &value);
00142
00143
00144 void Delete (int_t number);
00145
00146 private:
00147
00148 FibonacciHeap (const FibonacciHeap<element> &);
00149
00150
00151 FibonacciHeap<element> &operator = (const FibonacciHeap<element> &);
00152
00153
00154 NodePtr minRoot;
00155
00156
00157
00158 int_t nodeCount;
00159
00160
00161
00162
00163
00164
00165 multitable<Node> nodes;
00166
00167
00168
00169
00170
00171 element minValue;
00172
00173
00174
00175
00176
00177
00178
00179
00180 void Consolidate ();
00181
00182
00183 multitable<NodePtr> auxArray;
00184
00185
00186 int_t arrayPrepared;
00187
00188
00189 void Cut (const typename FibonacciHeap<element>::NodePtr &x,
00190 const typename FibonacciHeap<element>::NodePtr &y);
00191
00192
00193 void CascadingCut (typename FibonacciHeap<element>::NodePtr y);
00194
00195
00196 void showGraph (std::ostream &out, int_t depth,
00197 const typename FibonacciHeap<element>::NodePtr &x) const;
00198
00199 public:
00200
00201
00202 friend inline std::ostream &operator << (std::ostream &out,
00203 const FibonacciHeap<element> &h)
00204 {
00205 out << "Fibonacci heap (min root = " << h. minRoot << "):\n";
00206 NodePtr rootPtr = h. minRoot;
00207 if (rootPtr == NullPtr)
00208 return out;
00209 do
00210 {
00211 h. showGraph (out, 0, rootPtr);
00212 rootPtr = h. nodes [rootPtr]. right;
00213 } while (rootPtr != h. minRoot);
00214 return out;
00215 }
00216
00217 };
00218
00219 template <class element>
00220 const int_t FibonacciHeap<element>::NullPtr (-1);
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 template <class element>
00231 void FibonacciHeap<element>::showGraph (std::ostream &out, int_t depth,
00232 const typename FibonacciHeap<element>::NodePtr &x) const
00233 {
00234
00235 for (int_t i = 0; i < depth; ++ i)
00236 out << "| ";
00237 out << "+-- [" << nodes [x]. number << ": " << nodes [x]. key << "]";
00238 if (nodes [x]. left != NullPtr)
00239 out << " left=" << nodes [x]. left;
00240 if (nodes [x]. right != NullPtr)
00241 out << " right=" << nodes [x]. right;
00242 if (nodes [x]. parent != NullPtr)
00243 out << " parent=" << nodes [x]. parent;
00244 if (nodes [x]. child != NullPtr)
00245 out << " child=" << nodes [x]. child;
00246 out << " deg=" << nodes [x]. degree << "\n";
00247
00248
00249 NodePtr child = nodes [x]. child;
00250 if (child == NullPtr)
00251 return;
00252 do
00253 {
00254 showGraph (out, depth + 1, child);
00255 child = nodes [child]. right;
00256 } while (child != nodes [x]. child);
00257 return;
00258 }
00259
00260 template <class element>
00261 inline FibonacciHeap<element>::FibonacciHeap (int_t maxSize):
00262 minRoot (NullPtr), nodeCount (0), nodes (maxSize), arrayPrepared (0)
00263 {
00264
00265
00266
00267
00268
00269
00270
00271 return;
00272 }
00273
00274 template <class element>
00275 inline FibonacciHeap<element>::~FibonacciHeap ()
00276 {
00277
00278
00279
00280
00281
00282
00283
00284 return;
00285 }
00286
00287 template <class element>
00288 inline FibonacciHeap<element>::FibonacciHeap (const FibonacciHeap<element> &)
00289 {
00290 throw "Copy constructor for a Fibonacci heap not implemented.";
00291 return;
00292 }
00293
00294 template <class element>
00295 inline FibonacciHeap<element> &FibonacciHeap<element>::operator =
00296 (const FibonacciHeap<element> &)
00297 {
00298 throw "Assignment operator for a Fibonacci heap not implemented.";
00299 return *this;
00300 }
00301
00302 template <class element>
00303 inline int_t FibonacciHeap<element>::Insert (const element &value)
00304 {
00305
00306 NodePtr nodePtr = nodeCount;
00307
00308
00309 if (!nodeCount)
00310 minValue = value;
00311 else if (value < minValue)
00312 minValue = value;
00313
00314
00315 Node &node = nodes [nodePtr];
00316 node. key = value;
00317 node. mark = false;
00318 node. degree = 0;
00319 node. number = nodeCount;
00320 node. parent = NullPtr;
00321 node. child = NullPtr;
00322
00323
00324 if (minRoot == NullPtr)
00325 {
00326 node. left = nodePtr;
00327 node. right = nodePtr;
00328 }
00329 else
00330 {
00331 node. left = nodes [minRoot]. left;
00332 node. right = minRoot;
00333 nodes [node. left]. right = nodePtr;
00334 nodes [node. right]. left = nodePtr;
00335 }
00336
00337
00338 if ((minRoot == NullPtr) || (value < nodes [minRoot]. key))
00339 minRoot = nodePtr;
00340
00341
00342 return nodeCount ++;
00343 }
00344
00345 template <class element>
00346 inline int_t FibonacciHeap<element>::Minimum () const
00347 {
00348 return minRoot;
00349 }
00350
00351 template <class element>
00352 inline const element &FibonacciHeap<element>::Value (int_t number) const
00353 {
00354 return nodes [number]. key;
00355 }
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 template <class element>
00395 inline void FibonacciHeap<element>::Consolidate ()
00396 {
00397
00398 if (minRoot == NullPtr)
00399 return;
00400
00401
00402 NodePtr node = minRoot;
00403 int_t maxDegree = 0;
00404 do
00405 {
00406
00407 NodePtr x = node;
00408 int_t d = nodes [x]. degree;
00409
00410
00411 node = nodes [node]. right;
00412
00413
00414 while (arrayPrepared <= d)
00415 auxArray [arrayPrepared ++] = NullPtr;
00416
00417
00418 if (maxDegree <= d)
00419 maxDegree = d + 1;
00420
00421
00422 while (auxArray [d] != NullPtr)
00423 {
00424
00425 NodePtr y = auxArray [d];
00426
00427
00428 if (nodes [y]. key < nodes [x]. key)
00429 {
00430 NodePtr tmp = x;
00431 x = y;
00432 y = tmp;
00433 }
00434
00435
00436 nodes [y]. mark = false;
00437
00438
00439 nodes [y]. parent = x;
00440 NodePtr child = nodes [x]. child;
00441 if (child == NullPtr)
00442 {
00443 nodes [x]. child = y;
00444 nodes [y]. left = y;
00445 nodes [y]. right = y;
00446 }
00447 else
00448 {
00449 nodes [y]. left = child;
00450 nodes [y]. right = nodes [child]. right;
00451 nodes [child]. right = y;
00452 nodes [nodes [y]. right]. left = y;
00453 }
00454 ++ nodes [x]. degree;
00455
00456
00457 auxArray [d] = NullPtr;
00458
00459
00460 ++ d;
00461
00462
00463 if (arrayPrepared <= d)
00464 auxArray [arrayPrepared ++] = NullPtr;
00465
00466
00467 if (maxDegree <= d)
00468 maxDegree = d + 1;
00469 }
00470
00471
00472 auxArray [d] = x;
00473
00474 } while (node != minRoot);
00475
00476
00477 minRoot = NullPtr;
00478 for (int_t d = 0; d < maxDegree; ++ d)
00479 {
00480
00481 if (auxArray [d] == NullPtr)
00482 continue;
00483
00484
00485 NodePtr nodePtr = auxArray [d];
00486 auxArray [d] = NullPtr;
00487 Node &node = nodes [nodePtr];
00488
00489
00490 if (minRoot == NullPtr)
00491 {
00492 node. left = nodePtr;
00493 node. right = nodePtr;
00494 }
00495 else
00496 {
00497 node. left = minRoot;
00498 node. right = nodes [minRoot]. right;
00499 nodes [node. left]. right = nodePtr;
00500 nodes [node. right]. left = nodePtr;
00501 }
00502
00503
00504 if ((minRoot == NullPtr) ||
00505 (node. key < nodes [minRoot]. key))
00506 {
00507 minRoot = nodePtr;
00508 }
00509 }
00510 return;
00511 }
00512
00513 template <class element>
00514 inline element FibonacciHeap<element>::ExtractMinimum ()
00515 {
00516
00517 NodePtr nodePtr = minRoot;
00518 Node &node = nodes [minRoot];
00519
00520
00521
00522 NodePtr child = node. child;
00523 if (child != NullPtr)
00524 {
00525
00526 node. child = NullPtr;
00527
00528
00529 while (nodes [child]. parent != NullPtr)
00530 {
00531 nodes [child]. parent = NullPtr;
00532 child = nodes [child]. right;
00533 }
00534
00535
00536 NodePtr leftChild = child;
00537 NodePtr rightChild = nodes [child]. right;
00538 NodePtr leftRoot = nodePtr;
00539 NodePtr rightRoot = node. right;
00540 nodes [leftRoot]. right = rightChild;
00541 nodes [rightRoot]. left = leftChild;
00542 nodes [leftChild]. right = rightRoot;
00543 nodes [rightChild]. left = leftRoot;
00544 }
00545
00546
00547
00548 if (node. right != nodePtr)
00549 {
00550 minRoot = node. right;
00551 nodes [minRoot]. left = node. left;
00552 nodes [node. left]. right = minRoot;
00553 }
00554 else
00555 minRoot = NullPtr;
00556
00557
00558 node. left = NullPtr;
00559 node. right = NullPtr;
00560 node. parent = NullPtr;
00561 node. child = NullPtr;
00562 node. degree = -1;
00563
00564
00565 Consolidate ();
00566
00567 return node. key;
00568 }
00569
00570 template <class element>
00571 inline void FibonacciHeap<element>::Cut
00572 (const typename FibonacciHeap<element>::NodePtr &x,
00573 const typename FibonacciHeap<element>::NodePtr &y)
00574 {
00575
00576
00577 nodes [x]. parent = NullPtr;
00578 if (nodes [x]. right == x)
00579 {
00580 nodes [y]. child = NullPtr;
00581 }
00582
00583 else
00584 {
00585 NodePtr leftChild = nodes [x]. left;
00586 NodePtr rightChild = nodes [x]. right;
00587 nodes [y]. child = rightChild;
00588 nodes [leftChild]. right = rightChild;
00589 nodes [rightChild]. left = leftChild;
00590 }
00591
00592
00593 -- nodes [y]. degree;
00594
00595
00596 NodePtr leftRoot = minRoot;
00597 NodePtr rightRoot = nodes [minRoot]. right;
00598 nodes [x]. left = leftRoot;
00599 nodes [x]. right = rightRoot;
00600 nodes [leftRoot]. right = x;
00601 nodes [rightRoot]. left = x;
00602
00603
00604 nodes [x]. mark = false;
00605
00606 return;
00607 }
00608
00609 template <class element>
00610 inline void FibonacciHeap<element>::CascadingCut
00611 (typename FibonacciHeap<element>::NodePtr y)
00612 {
00613
00614 while (!(nodes [y]. parent == NullPtr))
00615 {
00616
00617
00618 if (!nodes [y]. mark)
00619 {
00620 nodes [y]. mark = true;
00621 return;
00622 }
00623
00624
00625
00626 NodePtr z = nodes [y]. parent;
00627 Cut (y, z);
00628 y = z;
00629 }
00630 return;
00631 }
00632
00633 template <class element>
00634 inline void FibonacciHeap<element>::DecreaseKey (int_t number,
00635 const element &value)
00636 {
00637
00638 NodePtr x (number);
00639
00640
00641 if (nodes [x]. degree == -1)
00642 return;
00643
00644
00645 if (value < minValue)
00646 minValue = value;
00647
00648
00649 nodes [x]. key = value;
00650
00651
00652 NodePtr y = nodes [x]. parent;
00653 if ((y != NullPtr) && (value < nodes [y]. key))
00654 {
00655 Cut (x, y);
00656 CascadingCut (y);
00657 }
00658
00659
00660 if (value < nodes [minRoot]. key)
00661 minRoot = x;
00662
00663 return;
00664 }
00665
00666 template <class element>
00667 inline void FibonacciHeap<element>::Delete (int_t number)
00668 {
00669 element value = minValue;
00670 DecreaseKey (number, value - 1);
00671 ExtractMinimum ();
00672 minValue = value;
00673 return;
00674 }
00675
00676
00677 }
00678 }
00679
00680 #endif // _CHOMP_STRUCT_FIBHEAP_H_
00681
00682
00683