Virtual Belgium  2.0
A micro-simulation platform for the Belgian population
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
FiboHeap.hpp
Go to the documentation of this file.
1 /****************************************************************
2  * DATA.HPP
3  *
4  * This file contains the implementation of a Fibonacci Heap
5  * data structure, necessary for an efficient Dijkstra algorithm
6  * implementation.
7  *
8  * Authors: Erel Segal - modified by J. Barthelemy
9  * Date : 15 august 2013
10  ****************************************************************/
11 
16 #include <iostream>
17 #include <algorithm>
18 #include <vector>
19 
20 using namespace std;
21 
22 typedef unsigned int uint;
23 
24 
26 
30 template <typename Data, typename Key> class FibonacciHeapNode {
31 
32  Key myKey;
34 
36  bool mark;
37 
38  // pointers in a circular doubly linked list
43 
46  myKey(-1),
47  myData(NULL),
48  degree(0),
49  mark(false),
50  child(NULL),
51  parent(NULL) {
52  previous = next = this; // doubly linked circular list
53  }
54 
56 
61  myKey(k),
62  myData(d),
63  degree(0),
64  mark(false),
65  child(NULL),
66  parent(NULL) {
67  previous = next = this; // doubly linked circular list
68  }
69 
71 
74  bool isSingle() const {
75  return (this == this->next);
76  }
77 
79 
84 
85  if (!other) return;
86 
87  this->next->previous = other->previous;
88  other->previous->next = this->next;
89 
90  this->next = other;
91  other->previous = this;
92 
93  }
94 
96  void remove() {
97  this->previous->next = this->next;
98  this->next->previous = this->previous;
99  this->next = this->previous = this;
100  }
101 
103 
109  if (!child)
110  child = other;
111  else
112  child->insert(other);
113  other->parent = this;
114  other->mark = false;
115  degree++;
116  //count += other->count;
117  }
118 
120 
124  if (other->parent!=this)
125  throw string ("Trying to remove a child from a non-parent");
126  if (other->isSingle()) {
127  if (child != other)
128  throw string ("Trying to remove a non-child");
129  child = NULL;
130  } else {
131  if (child == other)
132  child = other->next;
133  other->remove(); // from list of children
134  }
135  other->parent=NULL;
136  other->mark = false;
137  degree--;
138  //count -= other->count;
139  }
140 
141 
143 
149  friend ostream& operator<< (ostream& out, const FibonacciHeapNode& n) {
150  return (out << n.myData << ":" << n.myKey);
151  }
152 
154 
157  void printTree(ostream& out) const {
158  out << myData << ":" << myKey << ":" << degree << ":" << mark;
159  if (child) {
160  out << "(";
161  const FibonacciHeapNode<Data,Key>* n=child;
162  do {
163  if (n==this)
164  throw string("Illegal pointer - node is child of itself");
165  n->printTree(out);
166  out << " ";
167  n = n->next;
168  } while (n!=child);
169  out << ")";
170  }
171  }
172 
174 
177  void printAll(ostream& out) const {
178  const FibonacciHeapNode<Data,Key>* n=this;
179  do {
180  n->printTree(out);
181  out << " ";
182  n = n->next;
183  } while (n!=this);
184  out << endl;
185  }
186 
187 public:
188 
190 
193  Key key() const { return myKey; }
194 
196 
199  Data data() const { return myData; }
200 
201  template <typename D, typename K> friend class FibonacciHeap;
202 };
203 
204 
206 
214 template <typename Data, typename Key> class FibonacciHeap {
215 
217 
221 
222 protected:
223 
225 
230  PNode insertNode(PNode newNode) {
231 
232  if (!rootWithMinKey) { // insert the first myKey to the heap:
233  rootWithMinKey = newNode;
234  } else {
235  rootWithMinKey->insert(newNode); // insert the root of new tree to the list of roots
236  if (newNode->key() < rootWithMinKey->key()) rootWithMinKey = newNode;
237  }
238 
239  return newNode;
240 
241  }
242 
243 public:
244 
247  rootWithMinKey(NULL), count(0), maxDegree(0) {}
248 
251 
252  while(this->empty() == false ) {
253  deletemin();
254  }
255 
256  }
257 
259 
262  bool empty() const {return count==0;}
263 
265 
268  PNode minimum() const {
269  if (!rootWithMinKey)
270  throw string("no minimum element");
271  return rootWithMinKey;
272  }
273 
275 
278  void printRoots(ostream& out) const {
279  out << "maxDegree=" << maxDegree << " count=" << count << " roots=";
280  if (rootWithMinKey)
281  rootWithMinKey->printAll(out);
282  else
283  out << endl;
284  }
285 
287 
292  void merge (const FibonacciHeap& other) {
293  rootWithMinKey->insert(other.rootWithMinKey);
294  if (!rootWithMinKey || (other.rootWithMinKey && other.rootWithMinKey->key() < rootWithMinKey->key()))
295  this->rootWithMinKey = other.rootWithMinKey;
296  count += other.count;
297  }
298 
300 
306  PNode insert (Data d, Key k) {
307  count++;
308  // create a new tree with a single myKey:
309  return insertNode(new FibonacciHeapNode<Data,Key>(d,k));
310  }
311 
313  void deletemin() {
314  if (!rootWithMinKey) throw string("trying to remove from an empty heap");
315  count--;
316 
318  // Make all children of root new roots:
319  if (rootWithMinKey->child) {
320 
321  PNode c = rootWithMinKey->child;
322 
323  do {
324 
325  c->parent = NULL;
326  c = c->next;
327 
328  } while (c!=rootWithMinKey->child);
329 
330  rootWithMinKey->child = NULL; // removed all children
331  rootWithMinKey->insert(c);
332 
333  }
334 
336  if (rootWithMinKey->next == rootWithMinKey) {
337 
338  if (count!=0) throw string ("Internal error: should have 0 keys");
339  rootWithMinKey = NULL;
340  return;
341 
342  }
343 
345  vector<PNode> degreeRoots ((maxDegree+250)); // make room for a new degree
346  fill (degreeRoots.begin(), degreeRoots.end(), (PNode)NULL);
347  maxDegree = 0;
348  PNode currentPointer = rootWithMinKey->next;
349  uint currentDegree;
350  do {
351 
352  currentDegree = currentPointer->degree;
353 
354  PNode current = currentPointer;
355  currentPointer = currentPointer->next;
356  while (degreeRoots[currentDegree] != NULL) { // merge the two roots with the same degree:
357  PNode other = degreeRoots[currentDegree]; // another root with the same degree
358  if (current->key() > other->key())
359  swap(other,current);
360  // now current->key() <= other->key() - make other a child of current:
361  other->remove(); // remove from list of roots
362  current->addChild(other);
363 
364  degreeRoots[currentDegree]=NULL;
365  currentDegree++;
366  if (currentDegree >= degreeRoots.size())
367  degreeRoots.push_back((PNode)NULL);
368  }
369  // keep the current root as the first of its degree in the degrees array:
370  degreeRoots[currentDegree] = current;
371 
372  } while (currentPointer != rootWithMinKey);
373 
375  delete rootWithMinKey;
376  rootWithMinKey = NULL;
377 
378  unsigned int newMaxDegree=0;
379  for (unsigned int d=0; d<degreeRoots.size(); ++d) {
380  if (degreeRoots[d]) {
381  degreeRoots[d]->next = degreeRoots[d]->previous = degreeRoots[d];
382  insertNode(degreeRoots[d]);
383  if (d>newMaxDegree)
384  newMaxDegree = d;
385  }
386  }
387  maxDegree=newMaxDegree;
388 
389  }
390 
392 
396  void decreaseKey(PNode node, Key newKey) {
397 
398  if (newKey >= node->myKey)
399  throw string("Trying to decrease key to a greater key");
400 
401  // Update the key and possibly the min key:
402  node->myKey = newKey;
403 
404  // Check if the new key violates the heap invariant:
405  PNode parent = node->parent;
406 
407  if (parent == NULL ) { // root node - just make sure the minimum is correct
408  if (newKey < rootWithMinKey->key())
409  rootWithMinKey = node;
410  return; // heap invariant not violated - nothing more to do
411  } else if (parent->key() <= newKey) {
412  return; // heap invariant not violated - nothing more to do
413  }
414 
415  for(;;) {
416  parent->removeChild(node);
417  insertNode(node);
418 
419  if (!parent->parent) { // parent is a root - nothing more to do
420  break;
421  } else if (!parent->mark) { // parent is not a root and is not marked - just mark it
422  parent->mark = true;
423  break;
424  } else {
425  node = parent;
426  parent = parent->parent;
427  continue;
428  }
429  };
430  }
431 
433 
437  void remove(PNode node, Key minusInfinity) {
438  if (minusInfinity >= minimum()->key())
439  throw string("2nd argument to remove must be a key that is smaller than all other keys");
440  decreaseKey(node, minusInfinity);
441  deletemin();
442  }
443 
444 };
void printAll(ostream &out) const
Print every tree of nodes on the same level as the current one.
Definition: FiboHeap.hpp:177
void merge(const FibonacciHeap &other)
Fibonacci-Heap union procedure.
Definition: FiboHeap.hpp:292
FibonacciHeapNode< Data, Key > * parent
pointer to the parent
Definition: FiboHeap.hpp:42
FibonacciHeapNode()
Default constructor.
Definition: FiboHeap.hpp:45
FibonacciHeap()
Constructor.
Definition: FiboHeap.hpp:246
unsigned int uint
Definition: FiboHeap.hpp:22
bool mark
mark used in the decreaseKey algorithm.
Definition: FiboHeap.hpp:36
A template Fibonacci heap node class.
Definition: FiboHeap.hpp:30
bool empty() const
Check if the heap is empty.
Definition: FiboHeap.hpp:262
PNode rootWithMinKey
a circular d-list of nodes
Definition: FiboHeap.hpp:218
void addChild(FibonacciHeapNode< Data, Key > *other)
Add a child to the node.
Definition: FiboHeap.hpp:108
void decreaseKey(PNode node, Key newKey)
Decrease the key of a node to a given value.
Definition: FiboHeap.hpp:396
FibonacciHeapNode< Data, Key > * child
pointer to the first child in the list of children
Definition: FiboHeap.hpp:41
Key myKey
key associated to the node
Definition: FiboHeap.hpp:32
FibonacciHeapNode< Data, Key > * next
pointer to the next node
Definition: FiboHeap.hpp:40
PNode insert(Data d, Key k)
Insert a node to the heap.
Definition: FiboHeap.hpp:306
Data data() const
Return node's data.
Definition: FiboHeap.hpp:199
FibonacciHeapNode< Data, Key > * PNode
Definition: FiboHeap.hpp:216
~FibonacciHeap()
Destructor.
Definition: FiboHeap.hpp:250
void removeChild(FibonacciHeapNode< Data, Key > *other)
Remove a child node.
Definition: FiboHeap.hpp:123
Data myData
data stored in the node
Definition: FiboHeap.hpp:33
void printTree(ostream &out) const
Print the tree of nodes starting from the current one acting as the root.
Definition: FiboHeap.hpp:157
void deletemin()
Remove the minimum node of the heap, i.e. the Fibonacci Heap Extract Min procedure.
Definition: FiboHeap.hpp:313
FibonacciHeapNode< Data, Key > * previous
pointer to the previous node
Definition: FiboHeap.hpp:39
bool isSingle() const
Check if the node is single.
Definition: FiboHeap.hpp:74
Key key() const
Return node's key.
Definition: FiboHeap.hpp:193
PNode minimum() const
Return the node associated with the minimum key.
Definition: FiboHeap.hpp:268
uint count
total number of elements in heap
Definition: FiboHeap.hpp:219
void remove()
Removes the node from the list.
Definition: FiboHeap.hpp:96
uint degree
number of children. used in the deletemin algorithm.
Definition: FiboHeap.hpp:35
Template class for a Fibonacci Heap data structure.
Definition: FiboHeap.hpp:214
void insert(FibonacciHeapNode< Data, Key > *other)
Inserts a new node after this node.
Definition: FiboHeap.hpp:83
A data class.
Definition: Data.hpp:100
uint maxDegree
maximum degree (=child count) of a root in the circular d-list
Definition: FiboHeap.hpp:220
void printRoots(ostream &out) const
Print the roots in an output stream.
Definition: FiboHeap.hpp:278
FibonacciHeapNode(Data d, Key k)
Constructor.
Definition: FiboHeap.hpp:60
PNode insertNode(PNode newNode)
Insert a node to the heap.
Definition: FiboHeap.hpp:230