The Original CHomP Software
fibheap.h
Go to the documentation of this file.
1
3
14
15// Copyright (C) 1997-2020 by Pawel Pilarczyk.
16//
17// This file is part of my research software package. This is free software:
18// you can redistribute it and/or modify it under the terms of the GNU
19// General Public License as published by the Free Software Foundation,
20// either version 3 of the License, or (at your option) any later version.
21//
22// This software is distributed in the hope that it will be useful,
23// but WITHOUT ANY WARRANTY; without even the implied warranty of
24// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25// GNU General Public License for more details.
26//
27// You should have received a copy of the GNU General Public License
28// along with this software; see the file "license.txt". If not,
29// please, see <https://www.gnu.org/licenses/>.
30
31// Started on August 13, 2007. Last revision: January 23, 2010.
32
33
34#ifndef _CHOMP_STRUCT_FIBHEAP_H_
35#define _CHOMP_STRUCT_FIBHEAP_H_
36
37
39//#include "chomp/struct/pool.h"
40
41
42namespace chomp {
43namespace homology {
44
45
46// --------------------------------------------------
47// ----------------- FIBONACCI HEAP -----------------
48// --------------------------------------------------
49
61template <class element>
63{
64public:
66 typedef int_t NodePtr;
67
69 static const int_t NullPtr;
70
71private:
74 struct Node
75 {
78 element key;
79
83 bool mark;
84
89
92
95
98
101
104 };
105
106public:
109 FibonacciHeap (int_t maxSize = 0);
110
113
118 int_t Insert (const element &value);
119
122 int_t Minimum () const;
123
125 const element &Value (int_t number) const;
126
127 // Adds another heap to this one. Destroys the other one.
128 // WARNING: Because of the node memory allocation strategy used
129 // in this implementation of Fibonacci heaps, the complexity
130 // of computing the union is O(n) instead of O(1).
131 // Even worse, this operation is not yet implemented... Sorry!
132// void Union (FibonacciHeap<element> &h);
133
136 element ExtractMinimum ();
137
140 void DecreaseKey (int_t number, const element &value);
141
143 void Delete (int_t number);
144
145private:
148
151
154
158
165
170 element minValue;
171
172 // The pool of nodes used for the Fibonacci heap.
173// static pool<typename FibonacciHeap<element>::Node> *p;
174
175 // The number of Fibonacci heaps in use.
176// static int_t heapsInUse;
177
179 void Consolidate ();
180
183
186
188 void Cut (const typename FibonacciHeap<element>::NodePtr &x,
189 const typename FibonacciHeap<element>::NodePtr &y);
190
193
195 void showGraph (std::ostream &out, int_t depth,
196 const typename FibonacciHeap<element>::NodePtr &x) const;
197
198public:
201 friend inline std::ostream &operator << (std::ostream &out,
202 const FibonacciHeap<element> &h)
203 {
204 out << "Fibonacci heap (min root = " << h. minRoot << "):\n";
205 NodePtr rootPtr = h. minRoot;
206 if (rootPtr == NullPtr)
207 return out;
208 do
209 {
210 h. showGraph (out, 0, rootPtr);
211 rootPtr = h. nodes [rootPtr]. right;
212 } while (rootPtr != h. minRoot);
213 return out;
214 } /* operator << */
215
216}; /* class FibonacciHeap */
217
218template <class element>
220
221//template <class element>
222//pool<typename FibonacciHeap<element>::Node> *FibonacciHeap<element>::p = 0;
223
224//template <class element>
225//int_t FibonacciHeap<element>::heapsInUse = 0;
226
227// --------------------------------------------------
228
229template <class element>
230void FibonacciHeap<element>::showGraph (std::ostream &out, int_t depth,
231 const typename FibonacciHeap<element>::NodePtr &x) const
232{
233 // show this node
234 for (int_t i = 0; i < depth; ++ i)
235 out << "| ";
236 out << "+-- [" << nodes [x]. number << ": " << nodes [x]. key << "]";
237 if (nodes [x]. left != NullPtr)
238 out << " left=" << nodes [x]. left;
239 if (nodes [x]. right != NullPtr)
240 out << " right=" << nodes [x]. right;
241 if (nodes [x]. parent != NullPtr)
242 out << " parent=" << nodes [x]. parent;
243 if (nodes [x]. child != NullPtr)
244 out << " child=" << nodes [x]. child;
245 out << " deg=" << nodes [x]. degree << "\n";
246
247 // show all the children trees
248 NodePtr child = nodes [x]. child;
249 if (child == NullPtr)
250 return;
251 do
252 {
253 showGraph (out, depth + 1, child);
254 child = nodes [child]. right;
255 } while (child != nodes [x]. child);
256 return;
257} /* FibonacciHeap::showGraph */
258
259template <class element>
261 minRoot (NullPtr), nodeCount (0), nodes (maxSize), arrayPrepared (0)
262{
263 // allocate a new pool for elements if this is the first heap
264// if (!heapsInUse)
265// p = new pool<typename FibonacciHeap<element>::Node>;
266
267 // increase the number of heaps in use
268// ++ heapsInUse;
269
270 return;
271} /* FibonacciHeap::FibonacciHeap */
272
273template <class element>
275{
276 // decrease the number of heaps in use
277// -- heapsInUse;
278
279 // delete the pool for elements if this was the last heap
280// if (!heapsInUse)
281// delete p;
282
283 return;
284} /* FibonacciHeap::~FibonacciHeap */
285
286template <class element>
288{
289 throw "Copy constructor for a Fibonacci heap not implemented.";
290 return;
291} /* FibonacciHeap::FibonacciHeap */
292
293template <class element>
295 (const FibonacciHeap<element> &)
296{
297 throw "Assignment operator for a Fibonacci heap not implemented.";
298 return *this;
299} /* FibonacciHeap::operator = */
300
301template <class element>
302inline int_t FibonacciHeap<element>::Insert (const element &value)
303{
304 // allocate memory for the new node
305 NodePtr nodePtr = nodeCount;
306
307 // update the minimal value
308 if (!nodeCount)
309 minValue = value;
310 else if (value < minValue)
311 minValue = value;
312
313 // fill in the fields of the new node
314 Node &node = nodes [nodePtr];
315 node. key = value;
316 node. mark = false;
317 node. degree = 0;
318 node. number = nodeCount;
319 node. parent = NullPtr;
320 node. child = NullPtr;
321
322 // insert the node to the unordered bidirectional list of roots
323 if (minRoot == NullPtr)
324 {
325 node. left = nodePtr;
326 node. right = nodePtr;
327 }
328 else
329 {
330 node. left = nodes [minRoot]. left;
331 node. right = minRoot;
332 nodes [node. left]. right = nodePtr;
333 nodes [node. right]. left = nodePtr;
334 }
335
336 // make a correction to the pointer to the minimal root if necessary
337 if ((minRoot == NullPtr) || (value < nodes [minRoot]. key))
338 minRoot = nodePtr;
339
340 // return the number of the new node and increase the number of nodes
341 return nodeCount ++;
342} /* FibonacciHeap::Insert */
343
344template <class element>
346{
347 return minRoot;
348} /* FibonacciHeap::Minimum */
349
350template <class element>
351inline const element &FibonacciHeap<element>::Value (int_t number) const
352{
353 return nodes [number]. key;
354} /* FibonacciHeap::Value */
355
356/*
357template <class element>
358inline void FibonacciHeap<element>::Union (FibonacciHeap<element> &h)
359{
360 // if the other heap is empty, then do nothing
361 if (h. minRoot == NullPtr)
362 return;
363
364 // if this heap is empty, then just copy the data
365 if (minRoot == NullPtr)
366 {
367 minRoot = h. minRoot;
368 nodeCount = h. nodeCount;
369 minValue = h. minValue;
370 return;
371 }
372
373 // copy the nodes from the other heap to this one and update links
374 // TODO
375
376 // join the root lists
377 // TODO
378
379 // update the node count
380 nodeCount += h. nodeCount;
381
382 // update the minimal key value
383 if (h. minValue < minValue)
384 minValue = h. minValue;
385
386 // make the other heap empty
387 h. minRoot = NullPtr;
388 h. nodeCount = 0;
389 throw "The union of Fibonacci heaps not implemented, yet.";
390 return;
391}*/ /* FibonacciHeap::Union */
392
393template <class element>
395{
396 // do nothing if the heap is empty
397 if (minRoot == NullPtr)
398 return;
399
400 // for each node in the root list of the heap...
401 NodePtr node = minRoot;
402 int_t maxDegree = 0;
403 do
404 {
405 // take the node for the loop and get its degree
406 NodePtr x = node;
407 int_t d = nodes [x]. degree;
408
409 // prepare the next node from the root list for the next time
410 node = nodes [node]. right;
411
412 // expand the auxiliary array if necessary
413 while (arrayPrepared <= d)
414 auxArray [arrayPrepared ++] = NullPtr;
415
416 // update the strict upper limit on the degree used
417 if (maxDegree <= d)
418 maxDegree = d + 1;
419
420 // join this tree with another one of the same degree if any
421 while (auxArray [d] != NullPtr)
422 {
423 // take the node of the same degree as x
424 NodePtr y = auxArray [d];
425
426 // swap the node pointers if necessary
427 if (nodes [y]. key < nodes [x]. key)
428 {
429 NodePtr tmp = x;
430 x = y;
431 y = tmp;
432 }
433
434 // clear the mark of the node y
435 nodes [y]. mark = false;
436
437 // make the node y a child of the node x
438 nodes [y]. parent = x;
439 NodePtr child = nodes [x]. child;
440 if (child == NullPtr)
441 {
442 nodes [x]. child = y;
443 nodes [y]. left = y;
444 nodes [y]. right = y;
445 }
446 else
447 {
448 nodes [y]. left = child;
449 nodes [y]. right = nodes [child]. right;
450 nodes [child]. right = y;
451 nodes [nodes [y]. right]. left = y;
452 }
453 ++ nodes [x]. degree;
454
455 // clear the entry which stored the node of degree d
456 auxArray [d] = NullPtr;
457
458 // increase the degree to the degree of x
459 ++ d;
460
461 // expand the auxiliary array if necessary
462 if (arrayPrepared <= d)
463 auxArray [arrayPrepared ++] = NullPtr;
464
465 // update the strict upper limit on the degree used
466 if (maxDegree <= d)
467 maxDegree = d + 1;
468 }
469
470 // put this node in the array
471 auxArray [d] = x;
472
473 } while (node != minRoot);
474
475 // reconstruct the root list from the auxiliary array
476 minRoot = NullPtr;
477 for (int_t d = 0; d < maxDegree; ++ d)
478 {
479 // skip entries of the array which don't point to nodes
480 if (auxArray [d] == NullPtr)
481 continue;
482
483 // take the node pointer of the array
484 NodePtr nodePtr = auxArray [d];
485 auxArray [d] = NullPtr;
486 Node &node = nodes [nodePtr];
487
488 // link this node to the root list
489 if (minRoot == NullPtr)
490 {
491 node. left = nodePtr;
492 node. right = nodePtr;
493 }
494 else
495 {
496 node. left = minRoot;
497 node. right = nodes [minRoot]. right;
498 nodes [node. left]. right = nodePtr;
499 nodes [node. right]. left = nodePtr;
500 }
501
502 // update the pointer to the minimal root node if necessary
503 if ((minRoot == NullPtr) ||
504 (node. key < nodes [minRoot]. key))
505 {
506 minRoot = nodePtr;
507 }
508 }
509 return;
510} /* FibonacciHeap::Consolidate */
511
512template <class element>
514{
515 // determine the node with the minimum to extract
516 NodePtr nodePtr = minRoot;
517 Node &node = nodes [minRoot];
518
519 // make the children of the node become root nodes
520 // and attach them to the root list
521 NodePtr child = node. child;
522 if (child != NullPtr)
523 {
524 // clear the child pointer in the parent
525 node. child = NullPtr;
526
527 // clear the parent pointers in the children
528 while (nodes [child]. parent != NullPtr)
529 {
530 nodes [child]. parent = NullPtr;
531 child = nodes [child]. right;
532 }
533
534 // attach the children to the root list
535 NodePtr leftChild = child;
536 NodePtr rightChild = nodes [child]. right;
537 NodePtr leftRoot = nodePtr;
538 NodePtr rightRoot = node. right;
539 nodes [leftRoot]. right = rightChild;
540 nodes [rightRoot]. left = leftChild;
541 nodes [leftChild]. right = rightRoot;
542 nodes [rightChild]. left = leftRoot;
543 }
544
545 // make the min root pointer point at any other node
546 // and remove the node from the root list
547 if (node. right != nodePtr)
548 {
549 minRoot = node. right;
550 nodes [minRoot]. left = node. left;
551 nodes [node. left]. right = minRoot;
552 }
553 else
554 minRoot = NullPtr;
555
556 // reset the fields in the node to avoid any confusion in the future
557 node. left = NullPtr;
558 node. right = NullPtr;
559 node. parent = NullPtr;
560 node. child = NullPtr;
561 node. degree = -1;
562
563 // consolidate the heap
564 Consolidate ();
565
566 return node. key;
567} /* FibonacciHeap::ExtractMinimum */
568
569template <class element>
571 (const typename FibonacciHeap<element>::NodePtr &x,
572 const typename FibonacciHeap<element>::NodePtr &y)
573{
574 // remove x from the children of y:
575 // case 1: if x is the only child of y
576 nodes [x]. parent = NullPtr;
577 if (nodes [x]. right == x)
578 {
579 nodes [y]. child = NullPtr;
580 }
581 //case 2: if there are also other children of y
582 else
583 {
584 NodePtr leftChild = nodes [x]. left;
585 NodePtr rightChild = nodes [x]. right;
586 nodes [y]. child = rightChild;
587 nodes [leftChild]. right = rightChild;
588 nodes [rightChild]. left = leftChild;
589 }
590
591 // update the degree of y
592 -- nodes [y]. degree;
593
594 // add x to the root list of the heap
595 NodePtr leftRoot = minRoot;
596 NodePtr rightRoot = nodes [minRoot]. right;
597 nodes [x]. left = leftRoot;
598 nodes [x]. right = rightRoot;
599 nodes [leftRoot]. right = x;
600 nodes [rightRoot]. left = x;
601
602 // clear the marking of the node x if any
603 nodes [x]. mark = false;
604
605 return;
606} /* FibonacciHeap::Cut */
607
608template <class element>
611{
612 // do the cascading cut while the node has a parent
613 while (!(nodes [y]. parent == NullPtr))
614 {
615 // if this is the first time the node lost its child,
616 // then just mark the node and exit the cascading cut
617 if (!nodes [y]. mark)
618 {
619 nodes [y]. mark = true;
620 return;
621 }
622
623 // cut the node and continue the cascading cut
624 // with its parent
625 NodePtr z = nodes [y]. parent;
626 Cut (y, z);
627 y = z;
628 }
629 return;
630} /* FibonacciHeap::CascadingCut */
631
632template <class element>
634 const element &value)
635{
636 // translate the number to a node pointer
637 NodePtr x (number);
638
639 // ignore this action if the node is no longer in the heap
640 if (nodes [x]. degree == -1)
641 return;
642
643 // update the minimal value in the heap
644 if (value < minValue)
645 minValue = value;
646
647 // update the value of the node
648 nodes [x]. key = value;
649
650 // cut the tree so that the node x is in the root list
651 NodePtr y = nodes [x]. parent;
652 if ((y != NullPtr) && (value < nodes [y]. key))
653 {
654 Cut (x, y);
655 CascadingCut (y);
656 }
657
658 // update the pointer to the minimal node in the root list
659 if (value < nodes [minRoot]. key)
660 minRoot = x;
661
662 return;
663} /* FibonacciHeap::DecreaseKey */
664
665template <class element>
667{
668 element value = minValue;
669 DecreaseKey (number, value - 1);
670 ExtractMinimum ();
671 minValue = value;
672 return;
673} /* FibonacciHeap::Delete */
674
675
676} // namespace homology
677} // namespace chomp
678
679#endif // _CHOMP_STRUCT_FIBHEAP_H_
680
682
This template contains the definition of a Fibonacci heap that can be used as an efficient priority q...
Definition: fibheap.h:63
int_t arrayPrepared
The size of the prepared data in the array.
Definition: fibheap.h:185
FibonacciHeap< element > & operator=(const FibonacciHeap< element > &)
The assignment operator is not allowed.
Definition: fibheap.h:295
int_t NodePtr
The type of a pointer to a node in the Fibonacci heap.
Definition: fibheap.h:66
int_t Minimum() const
Returns the number of the node that contains the minimum.
Definition: fibheap.h:345
void CascadingCut(typename FibonacciHeap< element >::NodePtr y)
Does a cascading cut of the tree.
Definition: fibheap.h:610
void Cut(const typename FibonacciHeap< element >::NodePtr &x, const typename FibonacciHeap< element >::NodePtr &y)
Cuts the tree.
Definition: fibheap.h:571
~FibonacciHeap()
The destructor of a Fibonacci heap.
Definition: fibheap.h:274
FibonacciHeap(int_t maxSize=0)
The constructor of an empty Fibonacci heap.
Definition: fibheap.h:260
element minValue
The minimal value that ever appeared in the heap.
Definition: fibheap.h:170
void showGraph(std::ostream &out, int_t depth, const typename FibonacciHeap< element >::NodePtr &x) const
Shows a graph starting at the given node using DFS.
Definition: fibheap.h:230
int_t Insert(const element &value)
Inserts an element into the heap.
Definition: fibheap.h:302
multitable< Node > nodes
The array of nodes which hold the elements inserted to the heap in this order.
Definition: fibheap.h:164
void Consolidate()
Consolidates the Fibonacci heap by joining roots of equal degree.
Definition: fibheap.h:394
void Delete(int_t number)
Removes the element identified by the given number from the heap.
Definition: fibheap.h:666
NodePtr minRoot
A pointer to the minimal element in the list of roots.
Definition: fibheap.h:153
int_t nodeCount
The total number of nodes inserted to the heap and allocated in the multitable "nodes".
Definition: fibheap.h:157
element ExtractMinimum()
Extracts the minimum from the heap.
Definition: fibheap.h:513
const element & Value(int_t number) const
Returns the value of the node with the given number.
Definition: fibheap.h:351
void DecreaseKey(int_t number, const element &value)
Decreases the key of the element identified by the given number to the new value.
Definition: fibheap.h:633
static const int_t NullPtr
The value used for a NULL pointer.
Definition: fibheap.h:69
multitable< NodePtr > auxArray
An auto-expandable array used by the "Consolidate" procedure.
Definition: fibheap.h:182
friend std::ostream & operator<<(std::ostream &out, const FibonacciHeap< element > &h)
Operator << shows the heap to the output stream.
Definition: fibheap.h:201
A container for elements placed in a table (like a vector) that is actually built of many smaller tab...
Definition: multitab.h:65
int int_t
Index type for indexing arrays, counting cubes, etc.
Definition: config.h:115
This file contains the definition of the container "multitable" which is essentially an automatically...
This namespace contains the entire CHomP library interface.
Definition: bitmaps.h:51
The structure that holds a graph node for the graph representation of a Fibonacci heap.
Definition: fibheap.h:75
NodePtr right
A pointer to the right sibling node.
Definition: fibheap.h:103
NodePtr left
A pointer to the left sibling node.
Definition: fibheap.h:100
NodePtr child
A pointer to one of the children nodes.
Definition: fibheap.h:97
int_t number
The number of this node.
Definition: fibheap.h:91
element key
The value of the element that is used to compare the elements.
Definition: fibheap.h:78
NodePtr parent
A pointer to the parent node.
Definition: fibheap.h:94
int_t degree
The degree of the node, i.e., the number of its children.
Definition: fibheap.h:88
bool mark
A mark bit which indicates whether the node has lost a child since the last time it was made a child ...
Definition: fibheap.h:83