fibheap.h

Go to the documentation of this file.
00001 
00002 
00003 
00014 
00015 // Copyright (C) 1997-2010 by Pawel Pilarczyk.
00016 //
00017 // This file is part of the Homology Library.  This library is free software;
00018 // you can redistribute it and/or modify it under the terms of the GNU
00019 // General Public License as published by the Free Software Foundation;
00020 // either version 2 of the License, or (at your option) any later version.
00021 //
00022 // This library is distributed in the hope that it will be useful,
00023 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00024 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025 // GNU General Public License for more details.
00026 //
00027 // You should have received a copy of the GNU General Public License along
00028 // with this software; see the file "license.txt".  If not, write to the
00029 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00030 // MA 02111-1307, USA.
00031 
00032 // Started on August 13, 2007. Last revision: January 23, 2010.
00033 
00034 
00035 #ifndef _CHOMP_STRUCT_FIBHEAP_H_
00036 #define _CHOMP_STRUCT_FIBHEAP_H_
00037 
00038 
00039 #include "chomp/struct/multitab.h"
00040 //#include "chomp/struct/pool.h"
00041 
00042 
00043 namespace chomp {
00044 namespace homology {
00045 
00046 
00047 // --------------------------------------------------
00048 // ----------------- FIBONACCI HEAP -----------------
00049 // --------------------------------------------------
00050 
00062 template <class element>
00063 class FibonacciHeap
00064 {
00065 public:
00067         typedef int_t NodePtr;
00068 
00070         static const int_t NullPtr;
00071 
00072 private:
00075         struct Node
00076         {
00079                 element key;
00080 
00084                 bool mark;
00085 
00089                 int_t degree;
00090 
00092                 int_t number;
00093 
00095                 NodePtr parent;
00096 
00098                 NodePtr child;
00099 
00101                 NodePtr left;
00102 
00104                 NodePtr right;
00105         };
00106 
00107 public:
00110         FibonacciHeap (int_t maxSize = 0);
00111 
00113         ~FibonacciHeap ();
00114 
00119         int_t Insert (const element &value);
00120 
00123         int_t Minimum () const;
00124 
00126         const element &Value (int_t number) const;
00127 
00128         // Adds another heap to this one. Destroys the other one.
00129         // WARNING: Because of the node memory allocation strategy used
00130         // in this implementation of Fibonacci heaps, the complexity
00131         // of computing the union is O(n) instead of O(1).
00132         // Even worse, this operation is not yet implemented... Sorry!
00133 //      void Union (FibonacciHeap<element> &h);
00134 
00137         element ExtractMinimum ();
00138 
00141         void DecreaseKey (int_t number, const element &value);
00142 
00144         void Delete (int_t number);
00145 
00146 private:
00148         FibonacciHeap (const FibonacciHeap<element> &);
00149 
00151         FibonacciHeap<element> &operator = (const FibonacciHeap<element> &);
00152 
00154         NodePtr minRoot;
00155 
00158         int_t nodeCount;
00159 
00165         multitable<Node> nodes;
00166 
00171         element minValue;
00172 
00173         // The pool of nodes used for the Fibonacci heap.
00174 //      static pool<typename FibonacciHeap<element>::Node> *p;
00175 
00176         // The number of Fibonacci heaps in use.
00177 //      static int_t heapsInUse;
00178 
00180         void Consolidate ();
00181 
00183         multitable<NodePtr> auxArray;
00184 
00186         int_t arrayPrepared;
00187 
00189         void Cut (const typename FibonacciHeap<element>::NodePtr &x,
00190                 const typename FibonacciHeap<element>::NodePtr &y);
00191 
00193         void CascadingCut (typename FibonacciHeap<element>::NodePtr y);
00194 
00196         void showGraph (std::ostream &out, int_t depth,
00197                 const typename FibonacciHeap<element>::NodePtr &x) const;
00198 
00199 public:
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         } /* operator << */
00216 
00217 }; /* class FibonacciHeap */
00218 
00219 template <class element>
00220 const int_t FibonacciHeap<element>::NullPtr (-1);
00221 
00222 //template <class element>
00223 //pool<typename FibonacciHeap<element>::Node> *FibonacciHeap<element>::p = 0;
00224 
00225 //template <class element>
00226 //int_t FibonacciHeap<element>::heapsInUse = 0;
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         // show this node
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         // show all the children trees
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 } /* FibonacciHeap::showGraph */
00259 
00260 template <class element>
00261 inline FibonacciHeap<element>::FibonacciHeap (int_t maxSize):
00262         minRoot (NullPtr), nodeCount (0), nodes (maxSize), arrayPrepared (0)
00263 {
00264         // allocate a new pool for elements if this is the first heap
00265 //      if (!heapsInUse)
00266 //              p = new pool<typename FibonacciHeap<element>::Node>;
00267 
00268         // increase the number of heaps in use
00269 //      ++ heapsInUse;
00270 
00271         return;
00272 } /* FibonacciHeap::FibonacciHeap */
00273 
00274 template <class element>
00275 inline FibonacciHeap<element>::~FibonacciHeap ()
00276 {
00277         // decrease the number of heaps in use
00278 //      -- heapsInUse;
00279 
00280         // delete the pool for elements if this was the last heap
00281 //      if (!heapsInUse)
00282 //              delete p;
00283 
00284         return;
00285 } /* FibonacciHeap::~FibonacciHeap */
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 } /* FibonacciHeap::FibonacciHeap */
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 } /* FibonacciHeap::operator = */
00301 
00302 template <class element>
00303 inline int_t FibonacciHeap<element>::Insert (const element &value)
00304 {
00305         // allocate memory for the new node
00306         NodePtr nodePtr = nodeCount;
00307 
00308         // update the minimal value
00309         if (!nodeCount)
00310                 minValue = value;
00311         else if (value < minValue)
00312                 minValue = value;
00313 
00314         // fill in the fields of the new node
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         // insert the node to the unordered bidirectional list of roots
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         // make a correction to the pointer to the minimal root if necessary
00338         if ((minRoot == NullPtr) || (value < nodes [minRoot]. key))
00339                 minRoot = nodePtr;
00340 
00341         // return the number of the new node and increase the number of nodes
00342         return nodeCount ++;
00343 } /* FibonacciHeap::Insert */
00344 
00345 template <class element>
00346 inline int_t FibonacciHeap<element>::Minimum () const
00347 {
00348         return minRoot;
00349 } /* FibonacciHeap::Minimum */
00350 
00351 template <class element>
00352 inline const element &FibonacciHeap<element>::Value (int_t number) const
00353 {
00354         return nodes [number]. key;
00355 } /* FibonacciHeap::Value */
00356 
00357 /*
00358 template <class element>
00359 inline void FibonacciHeap<element>::Union (FibonacciHeap<element> &h)
00360 {
00361         // if the other heap is empty, then do nothing
00362         if (h. minRoot == NullPtr)
00363                 return;
00364 
00365         // if this heap is empty, then just copy the data
00366         if (minRoot == NullPtr)
00367         {
00368                 minRoot = h. minRoot;
00369                 nodeCount = h. nodeCount;
00370                 minValue = h. minValue;
00371                 return;
00372         }
00373 
00374         // copy the nodes from the other heap to this one and update links
00375         // TODO
00376 
00377         // join the root lists
00378         // TODO
00379 
00380         // update the node count
00381         nodeCount += h. nodeCount;
00382 
00383         // update the minimal key value
00384         if (h. minValue < minValue)
00385                 minValue = h. minValue;
00386 
00387         // make the other heap empty
00388         h. minRoot = NullPtr;
00389         h. nodeCount = 0;
00390         throw "The union of Fibonacci heaps not implemented, yet.";
00391         return;
00392 }*/ /* FibonacciHeap::Union */
00393 
00394 template <class element>
00395 inline void FibonacciHeap<element>::Consolidate ()
00396 {
00397         // do nothing if the heap is empty
00398         if (minRoot == NullPtr)
00399                 return;
00400 
00401         // for each node in the root list of the heap...
00402         NodePtr node = minRoot;
00403         int_t maxDegree = 0;
00404         do
00405         {
00406                 // take the node for the loop and get its degree
00407                 NodePtr x = node;
00408                 int_t d = nodes [x]. degree;
00409 
00410                 // prepare the next node from the root list for the next time
00411                 node = nodes [node]. right;
00412 
00413                 // expand the auxiliary array if necessary
00414                 while (arrayPrepared <= d)
00415                         auxArray [arrayPrepared ++] = NullPtr;
00416 
00417                 // update the strict upper limit on the degree used
00418                 if (maxDegree <= d)
00419                         maxDegree = d + 1;
00420 
00421                 // join this tree with another one of the same degree if any
00422                 while (auxArray [d] != NullPtr)
00423                 {
00424                         // take the node of the same degree as x
00425                         NodePtr y = auxArray [d];
00426 
00427                         // swap the node pointers if necessary
00428                         if (nodes [y]. key < nodes [x]. key)
00429                         {
00430                                 NodePtr tmp = x;
00431                                 x = y;
00432                                 y = tmp;
00433                         }
00434 
00435                         // clear the mark of the node y
00436                         nodes [y]. mark = false;
00437 
00438                         // make the node y a child of the node x
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                         // clear the entry which stored the node of degree d
00457                         auxArray [d] = NullPtr;
00458 
00459                         // increase the degree to the degree of x
00460                         ++ d;
00461 
00462                         // expand the auxiliary array if necessary
00463                         if (arrayPrepared <= d)
00464                                 auxArray [arrayPrepared ++] = NullPtr;
00465 
00466                         // update the strict upper limit on the degree used
00467                         if (maxDegree <= d)
00468                                 maxDegree = d + 1;
00469                 }
00470 
00471                 // put this node in the array
00472                 auxArray [d] = x;
00473 
00474         } while (node != minRoot);
00475 
00476         // reconstruct the root list from the auxiliary array
00477         minRoot = NullPtr;
00478         for (int_t d = 0; d < maxDegree; ++ d)
00479         {
00480                 // skip entries of the array which don't point to nodes
00481                 if (auxArray [d] == NullPtr)
00482                         continue;
00483 
00484                 // take the node pointer of the array
00485                 NodePtr nodePtr = auxArray [d];
00486                 auxArray [d] = NullPtr;
00487                 Node &node = nodes [nodePtr];
00488 
00489                 // link this node to the root list
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                 // update the pointer to the minimal root node if necessary
00504                 if ((minRoot == NullPtr) ||
00505                         (node. key < nodes [minRoot]. key))
00506                 {
00507                         minRoot = nodePtr;
00508                 }
00509         }
00510         return;
00511 } /* FibonacciHeap::Consolidate */
00512 
00513 template <class element>
00514 inline element FibonacciHeap<element>::ExtractMinimum ()
00515 {
00516         // determine the node with the minimum to extract
00517         NodePtr nodePtr = minRoot;
00518         Node &node = nodes [minRoot];
00519 
00520         // make the children of the node become root nodes
00521         // and attach them to the root list
00522         NodePtr child = node. child;
00523         if (child != NullPtr)
00524         {
00525                 // clear the child pointer in the parent
00526                 node. child = NullPtr;
00527 
00528                 // clear the parent pointers in the children
00529                 while (nodes [child]. parent != NullPtr)
00530                 {
00531                         nodes [child]. parent = NullPtr;
00532                         child = nodes [child]. right;
00533                 }
00534 
00535                 // attach the children to the root list
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         // make the min root pointer point at any other node
00547         // and remove the node from the root list
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         // reset the fields in the node to avoid any confusion in the future
00558         node. left = NullPtr;
00559         node. right = NullPtr;
00560         node. parent = NullPtr;
00561         node. child = NullPtr;
00562         node. degree = -1;
00563 
00564         // consolidate the heap
00565         Consolidate ();
00566 
00567         return node. key;
00568 } /* FibonacciHeap::ExtractMinimum */
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         // remove x from the children of y:
00576         // case 1: if x is the only child of y
00577         nodes [x]. parent = NullPtr;
00578         if (nodes [x]. right == x)
00579         {
00580                 nodes [y]. child = NullPtr;
00581         }
00582         //case 2: if there are also other children of y
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         // update the degree of y
00593         -- nodes [y]. degree;
00594 
00595         // add x to the root list of the heap
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         // clear the marking of the node x if any
00604         nodes [x]. mark = false;
00605 
00606         return;
00607 } /* FibonacciHeap::Cut */
00608 
00609 template <class element>
00610 inline void FibonacciHeap<element>::CascadingCut
00611         (typename FibonacciHeap<element>::NodePtr y)
00612 {
00613         // do the cascading cut while the node has a parent
00614         while (!(nodes [y]. parent == NullPtr))
00615         {
00616                 // if this is the first time the node lost its child,
00617                 // then just mark the node and exit the cascading cut
00618                 if (!nodes [y]. mark)
00619                 {
00620                         nodes [y]. mark = true;
00621                         return;
00622                 }
00623 
00624                 // cut the node and continue the cascading cut
00625                 // with its parent
00626                 NodePtr z = nodes [y]. parent;
00627                 Cut (y, z);
00628                 y = z;
00629         }
00630         return;
00631 } /* FibonacciHeap::CascadingCut */
00632 
00633 template <class element>
00634 inline void FibonacciHeap<element>::DecreaseKey (int_t number,
00635         const element &value)
00636 {
00637         // translate the number to a node pointer
00638         NodePtr x (number);
00639 
00640         // ignore this action if the node is no longer in the heap
00641         if (nodes [x]. degree == -1)
00642                 return;
00643 
00644         // update the minimal value in the heap
00645         if (value < minValue)
00646                 minValue = value;
00647 
00648         // update the value of the node
00649         nodes [x]. key = value;
00650 
00651         // cut the tree so that the node x is in the root list
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         // update the pointer to the minimal node in the root list
00660         if (value < nodes [minRoot]. key)
00661                 minRoot = x;
00662 
00663         return;
00664 } /* FibonacciHeap::DecreaseKey */
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 } /* FibonacciHeap::Delete */
00675 
00676 
00677 } // namespace homology
00678 } // namespace chomp
00679 
00680 #endif // _CHOMP_STRUCT_FIBHEAP_H_
00681 
00683