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