.
     3  *template <typename Item, 
 
     6  *          typename Compare = std::less<Prio> >
 
    10  *FibHeap(ItemIntMap),   FibHeap(ItemIntMap, Compare)
 
    14  *int size() : returns the number of elements in the heap
 
    16  *bool empty() : true iff size()=0
 
    18  *void set(Item, Prio) : calls push(Item, Prio) if Item is not
 
    19  *     in the heap, and calls decrease/increase(Item, Prio) otherwise
 
    21  *void push(Item, Prio) : pushes Item to the heap with priority Prio. Item
 
    22  *     mustn't be in the heap.
 
    24  *Item top() : returns the Item with least Prio. 
 
    25  *     Must be called only if heap is nonempty.
 
    27  *Prio prio() : returns the least Prio
 
    28  *     Must be called only if heap is nonempty.
 
    30  *Prio get(Item) : returns Prio of Item
 
    31  *     Must be called only if Item is in heap.
 
    33  *void pop() : deletes the Item with least Prio
 
    35  *void erase(Item) : deletes Item from the heap if it was already there
 
    37  *void decrease(Item, P) : decreases prio of Item to P. 
 
    38  *     Item must be in the heap with prio at least P.
 
    40  *void increase(Item, P) : sets prio of Item to P. 
 
    42  *state_enum state(Item) : returns PRE_HEAP if Item has not been in the 
 
    43  *     heap until now, IN_HEAP if it is in the heap at the moment, and 
 
    44  *     POST_HEAP otherwise. In the latter case it is possible that Item
 
    45  *     will get back to the heap again. 
 
    47  *In Fibonacci heaps, increase and erase are not efficient, in case of
 
    48  *many calls to these operations, it is better to use bin_heap.
 
    60   template <typename Item, typename Prio, typename ItemIntMap, 
 
    61     typename Compare = std::less<Prio> >
 
    65     typedef Prio PrioType;
 
    69     std::vector<store> container;
 
    83     FibHeap(ItemIntMap &_iimap) : minimum(), iimap(_iimap), num_items() {} 
 
    84     FibHeap(ItemIntMap &_iimap, const Compare &_comp) : minimum(), 
 
    85       iimap(_iimap), comp(_comp), num_items() {}
 
    93     bool empty() const { return num_items==0; }
 
    96     void set (Item const it, PrioType const value) {
 
    98       if ( i >= 0 && container[i].in ) {
 
    99 	if ( comp(value, container[i].prio) ) decrease(it, value); 
 
   100 	if ( comp(container[i].prio, value) ) increase(it, value); 
 
   101       } else push(it, value);
 
   105     void push (Item const it, PrioType const value) {
 
   108 	int s=container.size();
 
   112 	container.push_back(st);
 
   115 	container[i].parent=container[i].child=-1;
 
   116 	container[i].degree=0;
 
   117 	container[i].in=true;
 
   118 	container[i].marked=false;
 
   122 	container[container[minimum].right_neighbor].left_neighbor=i;
 
   123 	container[i].right_neighbor=container[minimum].right_neighbor;
 
   124 	container[minimum].right_neighbor=i;
 
   125 	container[i].left_neighbor=minimum;
 
   126 	if ( comp( value, container[minimum].prio) ) minimum=i; 
 
   128 	container[i].right_neighbor=container[i].left_neighbor=i;
 
   131       container[i].prio=value;
 
   137       return container[minimum].name;
 
   141     PrioType prio() const {
 
   142       return container[minimum].prio;
 
   146     const PrioType get(const Item& it) const {
 
   147       return container[iimap.get(it)].prio;
 
   152       /*The first case is that there are only one root.*/
 
   153       if ( container[minimum].left_neighbor==minimum ) {
 
   154 	container[minimum].in=false;
 
   155 	if ( container[minimum].degree!=0 ) { 
 
   156 	  makeroot(container[minimum].child);
 
   157 	  minimum=container[minimum].child;
 
   161 	int right=container[minimum].right_neighbor;
 
   163 	container[minimum].in=false;
 
   164 	if ( container[minimum].degree > 0 ) {
 
   165 	  int left=container[minimum].left_neighbor;
 
   166 	  int child=container[minimum].child;
 
   167 	  int last_child=container[child].left_neighbor;
 
   171 	  container[left].right_neighbor=child;
 
   172 	  container[child].left_neighbor=left;
 
   173 	  container[right].left_neighbor=last_child;
 
   174 	  container[last_child].right_neighbor=right;
 
   178       } // the case where there are more roots
 
   183     void erase (const Item& it) {
 
   186       if ( i >= 0 && container[i].in ) { 	
 
   187 	if ( container[i].parent!=-1 ) {
 
   188 	  int p=container[i].parent;
 
   192 	minimum=i;     //As if its prio would be -infinity
 
   198     void decrease (Item it, PrioType const value) {
 
   200       container[i].prio=value;
 
   201       int p=container[i].parent;
 
   203       if ( p!=-1 && comp(value, container[p].prio) ) {
 
   207       if ( comp(value, container[minimum].prio) ) minimum=i; 
 
   211     void increase (Item it, PrioType const value) {
 
   217     state_enum state(const Item &it) const {
 
   220 	if ( container[i].in ) i=0;
 
   223       return state_enum(i);
 
   231     int maxdeg=int( floor( 2.08*log(double(container.size()))))+1;
 
   233     std::vector<int> A(maxdeg,-1); 
 
   236      *Recall that now minimum does not point to the minimum prio element.
 
   237      *We set minimum to this during balance().
 
   239     int anchor=container[minimum].left_neighbor; 
 
   245 	if ( anchor==active ) end=true;
 
   246 	int d=container[active].degree;
 
   247 	next=container[active].right_neighbor;
 
   250 	  if( comp(container[active].prio, container[A[d]].prio) ) {
 
   263        while ( container[minimum].parent >=0 ) minimum=container[minimum].parent;
 
   267 	 if ( comp(container[s].prio, container[minimum].prio) ) minimum=s;
 
   268 	 s=container[s].right_neighbor;
 
   273     void makeroot (int c) {
 
   276 	container[s].parent=-1;
 
   277 	s=container[s].right_neighbor;
 
   282     void cut (int a, int b) {    
 
   284        *Replacing a from the children of b.
 
   286       --container[b].degree;
 
   288       if ( container[b].degree !=0 ) {
 
   289 	int child=container[b].child;
 
   291 	  container[b].child=container[child].right_neighbor;
 
   296       /*Lacing a to the roots.*/
 
   297       int right=container[minimum].right_neighbor;
 
   298       container[minimum].right_neighbor=a;
 
   299       container[a].left_neighbor=minimum;
 
   300       container[a].right_neighbor=right;
 
   301       container[right].left_neighbor=a;
 
   303       container[a].parent=-1;
 
   304       container[a].marked=false;
 
   310       if ( container[a].parent!=-1 ) {
 
   311 	int p=container[a].parent;
 
   313 	if ( container[a].marked==false ) container[a].marked=true;
 
   322     void fuse (int a, int b) {
 
   325       /*Lacing b under a.*/
 
   326       container[b].parent=a;
 
   328       if (container[a].degree==0) {
 
   329 	container[b].left_neighbor=b;
 
   330 	container[b].right_neighbor=b;
 
   331 	container[a].child=b;	
 
   333 	int child=container[a].child;
 
   334 	int last_child=container[child].left_neighbor;
 
   335 	container[child].left_neighbor=b;
 
   336 	container[b].right_neighbor=child;
 
   337 	container[last_child].right_neighbor=b;
 
   338 	container[b].left_neighbor=last_child;
 
   341       ++container[a].degree;
 
   343       container[b].marked=false;
 
   348      *It is invoked only if a has siblings.
 
   350     void unlace (int a) {      
 
   351       int leftn=container[a].left_neighbor;
 
   352       int rightn=container[a].right_neighbor;
 
   353       container[leftn].right_neighbor=rightn;
 
   354       container[rightn].left_neighbor=leftn;
 
   359       friend class FibHeap;
 
   371       store() : parent(-1), child(-1), degree(), marked(false), in(true) {}