$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
fibonacci_heap.hh
1 // Copyright (C) 2009, 2010 EPITA Research and Development Laboratory (LRDE)
2 //
3 // This file is part of Olena.
4 //
5 // Olena is free software: you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation, version 2 of the License.
8 //
9 // Olena is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // As a special exception, you may use this file as part of a free
18 // software project without restriction. Specifically, if other files
19 // instantiate templates or use macros or inline functions from this
20 // file, or you compile this file and link it with other files to produce
21 // an executable, this file does not by itself cause the resulting
22 // executable to be covered by the GNU General Public License. This
23 // exception does not however invalidate any other reasons why the
24 // executable file might be covered by the GNU General Public License.
25 
26 #ifndef MLN_UTIL_FIBONACCI_HEAP_HH
27 # define MLN_UTIL_FIBONACCI_HEAP_HH
28 
29 
30 # include <iostream>
31 # include <mln/core/concept/object.hh>
32 # include <mln/util/ord.hh>
33 
34 
35 
36 namespace mln
37 {
38 
39  namespace util
40  {
41 
42 
43  namespace internal
44  {
45 
46  /*---------------------------.
47  | Fibonacci Heap node Class. |
48  `---------------------------*/
49 
50  template <typename P, typename T>
52  {
53 
54  public:
57 
59  fibonacci_heap_node(const P& priority, const T& value);
60 
62 
64  const T& value() const;
65 
66  const P& priority() const;
67 
72 
73  short degree() const;
74 
75  short mark() const;
76 
77 
78  void set_value(const T&);
83  void set_degree(short degree);
84  void set_mark(short mark);
85 
88  bool operator<(fibonacci_heap_node<P,T>& rhs);
89 
90  void print_(std::ostream& ostr) const;
91 
92 
93  private:
94 
97  fibonacci_heap_node<P,T> *parent_;
99  short degree_;
100  short mark_;
101  P priority_;
102  T value_;
103  };
104 
105  } // end of namespace mln::util::internal
106 
107 
108 
109  /*----------------------.
110  | Fibonacci Heap Class. |
111  `----------------------*/
112 
116  template <typename P, typename T>
117  class fibonacci_heap : public Object< fibonacci_heap<P,T> >
118  {
119  public:
120 
121  typedef T element;
122 
124  fibonacci_heap();
125 
131 
132  ~fibonacci_heap();
133 
136  void push(const P& priority, const T& value);
137 
140  void push(fibonacci_heap<P,T>& other_heap);
141 
143  const T& front() const;
144 
146  T pop_front();
147 
149  bool is_empty() const;
150 
152  bool is_valid() const;
153 
155  unsigned nelements() const;
156 
158  void clear();
159 
167 
168 
169 
170  std::ostream& print_(std::ostream& ostr,
172  internal::fibonacci_heap_node<P,T> *parent = 0) const;
173 
174  private:
175 
176  // Internal functions that help to implement the Standard Operations
177 
178 
180  // FIXME: Cannot use that function efficiently except by passing the
181  // node pointer. Any idea why?
182  // FIXME: May be part of the public interface.
183  int decrease_key(internal::fibonacci_heap_node<P,T> *node,
185 
187  // FIXME: Cannot use that function efficiently except by passing the
188  // node pointer. Any idea why?
189  // FIXME: May be part of the public interface.
191 
194 
196  void exchange(internal::fibonacci_heap_node<P,T>*& lhs,
198 
214  void consolidate();
215 
218  void link(internal::fibonacci_heap_node<P,T> *lhs,
220 
221  void add_to_root_list(internal::fibonacci_heap_node<P,T> *);
222 
226 
234  void cascading_cut(internal::fibonacci_heap_node<P,T> *);
235 
237  void soft_clear_();
238 
241  mutable internal::fibonacci_heap_node<P,T> *min_root;
242  mutable long num_nodes;
243  mutable long num_trees;
244  mutable long num_marked_nodes;
245 
246  };
247 
248 
249  template <typename P, typename T>
250  std::ostream&
251  operator<<(std::ostream& ostr, const fibonacci_heap<P,T>& heap);
252 
253 
254 
255 # ifndef MLN_INCLUDE_ONLY
256 
257 
258  namespace internal
259  {
260 
261 
262  /*---------------------.
263  | fibonacci_heap_node. |
264  `---------------------*/
265 
266 
267  template <typename P, typename T>
268  inline
270  : left_(0), right_(0), parent_(0), child_(0),
271  degree_(0), mark_(0), priority_(0)
272  // FIXME: Don't we want to initialize priority with literal::zero?
273  {
274  }
275 
276 
277  template <typename P, typename T>
278  inline
279  fibonacci_heap_node<P,T>::fibonacci_heap_node(const P& priority,
280  const T& new_value)
281  : left_(0), right_(0), parent_(0), child_(0),
282  degree_(0), mark_(0), priority_(priority), value_(new_value)
283  {
284  }
285 
286 
287  template <typename P, typename T>
288  inline
289  fibonacci_heap_node<P,T>::~fibonacci_heap_node()
290  {
291  }
292 
293 
294  template <typename P, typename T>
295  inline
296  const T&
298  {
299  return value_;
300  }
301 
302 
303  template <typename P, typename T>
304  inline
305  const P&
306  fibonacci_heap_node<P,T>::priority() const
307  {
308  return priority_;
309  }
310 
311 
312  template <typename P, typename T>
313  inline
314  fibonacci_heap_node<P,T> *
316  {
317  return left_;
318  }
319 
320 
321  template <typename P, typename T>
322  inline
323  fibonacci_heap_node<P,T> *
325  {
326  return right_;
327  }
328 
329 
330  template <typename P, typename T>
331  inline
332  fibonacci_heap_node<P,T> *
333  fibonacci_heap_node<P,T>::parent() const
334  {
335  return parent_;
336  }
337 
338 
339  template <typename P, typename T>
340  inline
341  fibonacci_heap_node<P,T> *
342  fibonacci_heap_node<P,T>::child() const
343  {
344  return child_;
345  }
346 
347 
348  template <typename P, typename T>
349  inline
350  short
351  fibonacci_heap_node<P,T>::degree() const
352  {
353  return degree_;
354  }
355 
356 
357  template <typename P, typename T>
358  inline
359  short
360  fibonacci_heap_node<P,T>::mark() const
361  {
362  return mark_;
363  }
364 
365 
366  template <typename P, typename T>
367  inline
368  void
369  fibonacci_heap_node<P,T>::set_value(const T& value)
370  {
371  value_ = value;
372  }
373 
374 
375  template <typename P, typename T>
376  inline
377  void
378  fibonacci_heap_node<P,T>::set_left(fibonacci_heap_node<P,T> *node)
379  {
380  left_ = node;
381  }
382 
383 
384  template <typename P, typename T>
385  inline
386  void
387  fibonacci_heap_node<P,T>::set_right(fibonacci_heap_node<P,T> *node)
388  {
389  right_ = node;
390  }
391 
392 
393  template <typename P, typename T>
394  inline
395  void
396  fibonacci_heap_node<P,T>::set_parent(fibonacci_heap_node<P,T> *node)
397  {
398  parent_ = node;
399  }
400 
401 
402  template <typename P, typename T>
403  inline
404  void
405  fibonacci_heap_node<P,T>::set_child(fibonacci_heap_node<P,T> *node)
406  {
407  child_ = node;
408  }
409 
410 
411  template <typename P, typename T>
412  inline
413  void
414  fibonacci_heap_node<P,T>::set_degree(short degree)
415  {
416  degree_ = degree;
417  }
418 
419 
420  template <typename P, typename T>
421  inline
422  void
423  fibonacci_heap_node<P,T>::set_mark(short mark)
424  {
425  mark_ = mark;
426  }
427 
428 
429  template <typename P, typename T>
430  inline
431  void fibonacci_heap_node<P,T>::operator=(fibonacci_heap_node<P,T>& rhs)
432  {
433  priority_ = rhs.priority();
434  value_ = rhs.value();
435  }
436 
437 
438  template <typename P, typename T>
439  inline
440  bool
441  fibonacci_heap_node<P,T>::operator==(fibonacci_heap_node<P,T>& rhs)
442  {
443  return priority_ == rhs.priority() && value_ == rhs.value();
444  }
445 
446 
447  template <typename P, typename T>
448  inline
449  bool
450  fibonacci_heap_node<P,T>::operator<(fibonacci_heap_node<P,T>& rhs)
451  {
452  return util::ord_strict(priority_, rhs.priority())
453  || (priority_ == rhs.priority() && util::ord_strict(value_, rhs.value()));
454  }
455 
456 
457  template <typename P, typename T>
458  inline
459  void fibonacci_heap_node<P,T>::print_(std::ostream& ostr) const
460  {
461  ostr << value_ << " (" << priority_ << ")";
462  }
463 
464 
465  } // end of namespace mln::util::internal
466 
467 
468 
469  /*---------------\
470  | fibonacci_heap |
471  `---------------*/
472 
473  template <typename P, typename T>
474  inline
475  fibonacci_heap<P,T>::fibonacci_heap()
476  {
477  soft_clear_();
478  }
479 
480 
481  template <typename P, typename T>
482  inline
483  fibonacci_heap<P,T>::fibonacci_heap(const fibonacci_heap<P,T>& rhs)
484  : Object< fibonacci_heap<P,T> >()
485  {
486  min_root = rhs.min_root;
487  num_nodes = rhs.num_nodes;
488  num_trees = rhs.num_trees;
489  num_marked_nodes = rhs.num_marked_nodes;
490 
491 // rhs is const, we cannot call that method.
492 // rhs.soft_clear_();
493  rhs.min_root = 0;
494  rhs.num_nodes = 0;
495  rhs.num_trees = 0;
496  rhs.num_marked_nodes = 0;
497  }
498 
499 
500  template <typename P, typename T>
501  inline
503  {
504  clear();
505  }
506 
507 
508  template <typename P, typename T>
509  inline
510  void
511  fibonacci_heap<P,T>::push(const P& priority, const T& value)
512  {
513  typedef internal::fibonacci_heap_node<P,T> node_t;
514  node_t *new_node = new node_t(priority, value);
515 
516  insert(new_node);
517  }
518 
519 
520  template <typename P, typename T>
521  inline
522  void
523  fibonacci_heap<P,T>::push(fibonacci_heap<P,T>& other_heap)
524  {
525  if (other_heap.is_empty() || &other_heap == this)
526  return;
527 
528  if (min_root != 0)
529  {
530  internal::fibonacci_heap_node<P,T> *min1, *min2, *next1, *next2;
531 
532  // We join the two circular lists by cutting each list between its
533  // min node and the node after the min. This code just pulls those
534  // nodes into temporary variables so we don't get lost as changes
535  // are made.
536  min1 = min_root;
537  min2 = other_heap.min_root;
538  next1 = min1->right();
539  next2 = min2->right();
540 
541  // To join the two circles, we join the minimum nodes to the next
542  // nodes on the opposite chains. Conceptually, it looks like the way
543  // two bubbles join to form one larger bubble. They meet at one point
544  // of contact, then expand out to make the bigger circle.
545  min1->set_right(next2);
546  next2->set_left(min1);
547  min2->set_right(next1);
548  next1->set_left(min2);
549 
550  // Choose the new minimum for the heap.
551  if (*min2 < *min1)
552  min_root = min2;
553  }
554  else
555  min_root = other_heap.min_root;
556 
557  // Set the amortized analysis statistics and size of the new heap.
558  num_nodes += other_heap.num_nodes;
559  num_marked_nodes += other_heap.num_marked_nodes;
560  num_trees += other_heap.num_trees;
561 
562  // Complete the union by setting the other heap to emptiness.
563  other_heap.soft_clear_();
564 
565  mln_postcondition(other_heap.is_empty());
566  }
567 
568 
569  template <typename P, typename T>
570  inline
571  const T&
573  {
574  return min_root->value();
575  }
576 
577 
578  template <typename P, typename T>
579  inline
580  T
582  {
583  mln_precondition(is_valid());
584  mln_precondition(!is_empty());
585 
586  internal::fibonacci_heap_node<P,T> *result = min_root;
587  fibonacci_heap<P,T> *child_heap = 0;
588 
589  // Remove minimum node and set min_root to next node.
590  min_root = result->right();
591  result->right()->set_left(result->left());
592  result->left()->set_right(result->right());
593  result->set_left(0);
594  result->set_right(0);
595 
596  --num_nodes;
597  if (result->mark())
598  {
599  --num_marked_nodes;
600  result->set_mark(0);
601  }
602  result->set_degree(0);
603 
604  // Attach child list of minimum node to the root list of the heap
605  // If there is no child list, then do no work.
606  if (result->child() == 0)
607  {
608  if (min_root == result)
609  min_root = 0;
610  }
611 
612  // If min_root==result then there was only one root tree, so the
613  // root list is simply the child list of that node (which is
614  // 0 if this is the last node in the list).
615  else if (min_root == result)
616  min_root = result->child();
617 
618  // If min_root is different, then the child list is pushed into a
619  // new temporary heap, which is then merged by union() onto the
620  // root list of this heap.
621  else
622  {
623  child_heap = new fibonacci_heap<P,T>();
624  child_heap->min_root = result->child();
625  }
626 
627  // Complete the disassociation of the result node from the heap.
628  if (result->child() != 0)
629  result->child()->set_parent(0);
630  result->set_child(0);
631  result->set_parent(0);
632 
633  // If there was a child list, then we now merge it with the
634  // rest of the root list.
635  if (child_heap)
636  {
637  push(*child_heap);
638  delete child_heap;
639  }
640 
641  // Consolidate heap to find new minimum and do reorganize work.
642  if (min_root != 0)
643  consolidate();
644 
645  // Return the minimum node, which is now disassociated with the heap
646  // It has left, right, parent, child, mark and degree cleared.
647  T val = result->value();
648  delete result;
649 
650  return val;
651  }
652 
653 
654  template <typename P, typename T>
655  inline
656  int
657  fibonacci_heap<P,T>::decrease_key(internal::fibonacci_heap_node<P,T> *node,
658  internal::fibonacci_heap_node<P,T>& key)
659  {
660  internal::fibonacci_heap_node<P,T> *parent;
661 
662  if (node == 0 || *node < key)
663  return -1;
664 
665  *node = key;
666 
667  parent = node->parent();
668  if (parent != 0 && *node < *parent)
669  {
670  cut(node, parent);
671  cascading_cut(parent);
672  }
673 
674  if (*node < *min_root)
675  min_root = node;
676 
677  return 0;
678  }
679 
680 
681  template <typename P, typename T>
682  inline
683  int
684  fibonacci_heap<P,T>::remove(internal::fibonacci_heap_node<P,T> *node)
685  {
686  internal::fibonacci_heap_node<P,T> temp;
687  int result;
688 
689  if (node == 0)
690  return -1;
691 
692  result = decrease_key(node, temp);
693 
694  if (result == 0)
695  if (pop_front() == 0)
696  result = -1;
697 
698  if (result == 0)
699  delete node;
700 
701  return result;
702  }
703 
704 
705  template <typename P, typename T>
706  inline
707  bool
709  {
710  return min_root == 0;
711  }
712 
713 
714  template <typename P, typename T>
715  inline
716  bool
718  {
719  return min_root != 0;
720  }
721 
722 
723  template <typename P, typename T>
724  inline
725  void
727  {
728  while (min_root != 0)
729  pop_front();
730  }
731 
732 
733  template <typename P, typename T>
734  inline
735  void
736  fibonacci_heap<P,T>::soft_clear_()
737  {
738  min_root = 0;
739  num_nodes = 0;
740  num_trees = 0;
741  num_marked_nodes = 0;
742  }
743 
744 
745  template <typename P, typename T>
746  inline
747  unsigned
749  {
750  return num_nodes;
751  };
752 
753 
754  template <typename P, typename T>
755  inline
756  fibonacci_heap<P,T>&
757  fibonacci_heap<P,T>::operator=(fibonacci_heap<P,T>& rhs)
758  {
759  if (&rhs != this)
760  {
761  min_root = rhs.min_root;
762  num_nodes = rhs.num_nodes;
763  num_trees = rhs.num_trees;
764  num_marked_nodes = rhs.num_marked_nodes;
765  rhs.soft_clear_();
766  }
767  return *this;
768  }
769 
770 
771  template <typename P, typename T>
772  std::ostream&
773  fibonacci_heap<P,T>::print_(std::ostream& ostr,
774  internal::fibonacci_heap_node<P,T> *tree,
775  internal::fibonacci_heap_node<P,T> *parent) const
776  {
777  internal::fibonacci_heap_node<P,T>* temp = 0;
778 
779  if (tree == 0)
780  tree = min_root;
781 
782  temp = tree;
783  if (temp != 0)
784  {
785  do {
786  if (temp->left() == 0)
787  ostr << "(left is 0)";
788  temp->print_();
789  if (temp->parent() != parent)
790  ostr << "(parent is incorrect)";
791  if (temp->right() == 0)
792  ostr << "(right is 0)";
793  else if (temp->right()->left() != temp)
794  ostr << "(Error in left link left) ->";
795  else
796  ostr << " <-> ";
797 
798  temp = temp->right();
799 
800  } while (temp != 0 && temp != tree);
801  }
802  else
803  ostr << " <empty>" << std::endl;
804  ostr << std::endl;
805 
806  temp = tree;
807  if (temp != 0)
808  {
809  do {
810  ostr << "children of " << temp->value() << ": ";
811  if (temp->child() == 0)
812  ostr << "NONE" << std::endl;
813  else print_(ostr, temp->child(), temp);
814  temp = temp->right();
815  } while (temp!=0 && temp != tree);
816  }
817 
818  return ostr;
819  }
820 
821 
822  template <typename P, typename T>
823  inline
824  void fibonacci_heap<P,T>::consolidate()
825  {
826  internal::fibonacci_heap_node<P,T> *x, *y, *w;
827  internal::fibonacci_heap_node<P,T> *a[1 + 8 * sizeof (long)]; // 1+lg(n)
828  short dn = 1 + 8 * sizeof (long);
829 
830  // Initialize the consolidation detection array.
831  for (int i = 0; i < dn; ++i)
832  a[i] = 0;
833 
834  // We need to loop through all elements on root list.
835  // When a collision of degree is found, the two trees
836  // are consolidated in favor of the one with the lesser
837  // element key value. We first need to break the circle
838  // so that we can have a stopping condition (we can't go
839  // around until we reach the tree we started with
840  // because all root trees are subject to becoming a
841  // child during the consolidation).
842  min_root->left()->set_right(0);
843  min_root->set_left(0);
844  w = min_root;
845 
846  short d;
847  do {
848  x = w;
849  d = x->degree();
850  w = w->right();
851 
852  // We need another loop here because the consolidated result
853  // may collide with another large tree on the root list.
854  while (a[d] != 0)
855  {
856  y = a[d];
857  if (*y < *x)
858  exchange(x, y);
859  if (w == y) w = y->right();
860  link(y, x);
861  a[d] = 0;
862  ++d;
863  }
864  a[d] = x;
865 
866  } while (w != 0);
867 
868  // Now we rebuild the root list, find the new minimum,
869  // set all root list nodes' parent pointers to 0 and
870  // count the number of subtrees.
871  min_root = 0;
872  num_trees = 0;
873  for (int i = 0; i < dn; ++i)
874  if (a[i] != 0)
875  add_to_root_list(a[i]);
876  }
877 
878 
879  template <typename P, typename T>
880  inline
881  void
882  fibonacci_heap<P,T>::link(internal::fibonacci_heap_node<P,T> *y,
883  internal::fibonacci_heap_node<P,T> *x)
884  {
885  // Remove node y from root list.
886  if (y->right() != 0)
887  y->right()->set_left(y->left());
888  if (y->left() != 0)
889  y->left()->set_right(y->right());
890  --num_trees;
891 
892  // Make node y a singleton circular list with a parent of x.
893  y->set_left(y);
894  y->set_right(y);
895  y->set_parent(x);
896 
897  // If node x has no children, then list y is its new child list.
898  if (x->child() == 0)
899  x->set_child(y);
900 
901  // Otherwise, node y must be added to node x's child list.
902  else
903  {
904  y->set_left(x->child());
905  y->set_right(x->child()->right());
906  x->child()->set_right(y);
907  y->right()->set_left(y);
908  }
909 
910  // Increase the degree of node x because it's now a bigger tree.
911  x->set_degree(x->degree() + 1);
912 
913  // Node y has just been made a child, so clear its mark.
914  if (y->mark())
915  --num_marked_nodes;
916  y->set_mark(0);
917  }
918 
919 
920  template <typename P, typename T>
921  inline
922  void
923  fibonacci_heap<P,T>::add_to_root_list(internal::fibonacci_heap_node<P,T> *x)
924  {
925  if (x->mark())
926  --num_marked_nodes;
927  x->set_mark(0);
928 
929  --num_nodes;
930  insert(x);
931  }
932 
933 
934  template <typename P, typename T>
935  inline
936  void
937  fibonacci_heap<P,T>::cut(internal::fibonacci_heap_node<P,T> *x,
938  internal::fibonacci_heap_node<P,T> *y)
939  {
940  if (y->child() == x)
941  y->child() = x->right();
942  if (y->child() == x)
943  y->child() = 0;
944 
945  y->set_degree(y->degree() - 1);
946 
947  x->left()->right() = x->right();
948  x->right()->left() = x->left();
949 
950  add_to_root_list(x);
951  }
952 
953 
954  template <typename P, typename T>
955  inline
956  void
957  fibonacci_heap<P,T>::cascading_cut(internal::fibonacci_heap_node<P,T> *y)
958  {
959  internal::fibonacci_heap_node<P,T> *z = y->parent();
960 
961  while (z != 0)
962  {
963  if (y->mark() == 0)
964  {
965  y->mark() = 1;
966  ++num_marked_nodes;
967  z = 0;
968  }
969  else
970  {
971  cut(y, z);
972  y = z;
973  z = y->parent();
974  }
975  }
976  }
977 
978 
979  template <typename P, typename T>
980  inline
981  void
982  fibonacci_heap<P,T>::insert(internal::fibonacci_heap_node<P,T> *node)
983  {
984  if (node == 0)
985  return;
986 
987  // If the heap is currently empty, then new node becomes singleton
988  // circular root list.
989  if (min_root == 0)
990  {
991  min_root = node;
992  node->set_left(node);
993  node->set_right(node);
994  }
995  else
996  {
997  // Pointers from node set to insert between min_root and
998  // min_root->right().
999  node->set_right(min_root->right());
1000  node->set_left(min_root);
1001 
1002  // Set pointers to node.
1003  node->left()->set_right(node);
1004  node->right()->set_left(node);
1005 
1006  // The new node becomes new min_root if it is less than current
1007  // min_root.
1008  if (*node < *min_root)
1009  min_root = node;
1010  }
1011 
1012  // We have one more node in the heap, and it is a tree on the root list.
1013  ++num_nodes;
1014  ++num_trees;
1015  node->set_parent(0);
1016  }
1017 
1018 
1019  template <typename P, typename T>
1020  inline
1021  void
1022  fibonacci_heap<P,T>::exchange(internal::fibonacci_heap_node<P,T>*& n1,
1023  internal::fibonacci_heap_node<P,T>*& n2)
1024  {
1025  internal::fibonacci_heap_node<P,T> *temp;
1026 
1027  temp = n1;
1028  n1 = n2;
1029  n2 = temp;
1030  }
1031 
1032 
1033  template <typename P, typename T>
1034  std::ostream&
1035  operator<<(std::ostream& ostr, const fibonacci_heap<P,T>& heap)
1036  {
1037  return heap.print_(ostr);
1038  }
1039 
1040 # endif // ! MLN_INCLUDE_ONLY
1041 
1042 
1043 
1044  } // end of namespace mln::util
1045 
1046 } // end of namespace mln
1047 
1048 #endif // ! MLN_UTIL_FIBONACCI_HEAP_HH