lemon/fib_heap.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
parent 1956 a055123339d5
child 2263 9273fe7d850c
permissions -rw-r--r--
Update the Path concept
Concept check for paths

DirPath renamed to Path
The interface updated to the new lemon interface
Make difference between the empty path and the path from one node
Builder interface have not been changed
// I wanted but there was not accordance about it

UPath is removed
It was a buggy implementation, it could not iterate on the
nodes in the right order
Right way to use undirected paths => path of edges in undirected graphs

The tests have been modified to the current implementation
alpar@906
     1
/* -*- C++ -*-
alpar@906
     2
 *
alpar@1956
     3
 * This file is a part of LEMON, a generic C++ optimization library
alpar@1956
     4
 *
alpar@1956
     5
 * Copyright (C) 2003-2006
alpar@1956
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1359
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@906
     8
 *
alpar@906
     9
 * Permission to use, modify and distribute this software is granted
alpar@906
    10
 * provided that this copyright notice appears in all copies. For
alpar@906
    11
 * precise terms see the accompanying LICENSE file.
alpar@906
    12
 *
alpar@906
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@906
    14
 * express or implied, and with no claim as to its suitability for any
alpar@906
    15
 * purpose.
alpar@906
    16
 *
alpar@906
    17
 */
alpar@255
    18
alpar@921
    19
#ifndef LEMON_FIB_HEAP_H
alpar@921
    20
#define LEMON_FIB_HEAP_H
alpar@255
    21
jacint@857
    22
///\file
klao@491
    23
///\ingroup auxdat
alpar@255
    24
///\brief Fibonacci Heap implementation.
alpar@255
    25
alpar@255
    26
#include <vector>
alpar@255
    27
#include <functional>
deba@1332
    28
#include <cmath>
alpar@255
    29
alpar@921
    30
namespace lemon {
alpar@255
    31
  
deba@1834
    32
  /// \ingroup auxdat
alpar@430
    33
jacint@857
    34
  /// Fibonacci Heap.
jacint@373
    35
jacint@857
    36
  ///This class implements the \e Fibonacci \e heap data structure. A \e heap
jacint@857
    37
  ///is a data structure for storing items with specified values called \e
jacint@857
    38
  ///priorities in such a way that finding the item with minimum priority is
alpar@911
    39
  ///efficient. \c Compare specifies the ordering of the priorities. In a heap
jacint@857
    40
  ///one can change the priority of an item, add or erase an item, etc.
jacint@857
    41
  ///
jacint@857
    42
  ///The methods \ref increase and \ref erase are not efficient in a Fibonacci
jacint@857
    43
  ///heap. In case of many calls to these operations, it is better to use a
jacint@857
    44
  ///\e binary \e heap.
jacint@857
    45
  ///
jacint@857
    46
  ///\param Item Type of the items to be stored.  
jacint@857
    47
  ///\param Prio Type of the priority of the items.
alpar@1204
    48
  ///\param ItemIntMap A read and writable Item int map, used internally
alpar@1204
    49
  ///to handle the cross references.
jacint@857
    50
  ///\param Compare A class for the ordering of the priorities. The
jacint@857
    51
  ///default is \c std::less<Prio>.
jacint@857
    52
  ///
alpar@967
    53
  ///\sa BinHeap
alpar@967
    54
  ///\sa Dijkstra
jacint@857
    55
  ///\author Jacint Szabo 
jacint@857
    56
 
jacint@373
    57
#ifdef DOXYGEN
jacint@373
    58
  template <typename Item, 
jacint@373
    59
	    typename Prio, 
jacint@373
    60
	    typename ItemIntMap, 
jacint@373
    61
	    typename Compare>
jacint@373
    62
#else
jacint@373
    63
  template <typename Item, 
jacint@373
    64
	    typename Prio, 
jacint@373
    65
	    typename ItemIntMap, 
alpar@255
    66
	    typename Compare = std::less<Prio> >
jacint@373
    67
#endif
alpar@255
    68
  class FibHeap {
jacint@387
    69
  public:     
alpar@255
    70
    typedef Prio PrioType;
alpar@255
    71
    
jacint@373
    72
  private:
alpar@255
    73
    class store;
alpar@255
    74
    
alpar@255
    75
    std::vector<store> container;
alpar@255
    76
    int minimum;
alpar@255
    77
    ItemIntMap &iimap;
alpar@255
    78
    Compare comp;
alpar@255
    79
    int num_items;
jacint@373
    80
    
alpar@255
    81
  public:
alpar@1127
    82
    ///Status of the nodes
alpar@255
    83
    enum state_enum {
alpar@1127
    84
      ///The node is in the heap
alpar@255
    85
      IN_HEAP = 0,
alpar@1127
    86
      ///The node has never been in the heap
alpar@255
    87
      PRE_HEAP = -1,
alpar@1127
    88
      ///The node was in the heap but it got out of it
alpar@255
    89
      POST_HEAP = -2
alpar@255
    90
    };
alpar@255
    91
    
deba@1717
    92
    /// \brief The constructor
deba@1717
    93
    ///
deba@1717
    94
    /// \c _iimap should be given to the constructor, since it is
deba@1717
    95
    ///   used internally to handle the cross references.
deba@1185
    96
    explicit FibHeap(ItemIntMap &_iimap) 
deba@1185
    97
      : minimum(0), iimap(_iimap), num_items() {} 
jacint@1270
    98
 
deba@1717
    99
    /// \brief The constructor
deba@1717
   100
    ///
deba@1717
   101
    /// \c _iimap should be given to the constructor, since it is used
deba@1717
   102
    /// internally to handle the cross references. \c _comp is an
deba@1717
   103
    /// object for ordering of the priorities. 
jacint@373
   104
    FibHeap(ItemIntMap &_iimap, const Compare &_comp) : minimum(0), 
jacint@1270
   105
		  iimap(_iimap), comp(_comp), num_items() {}
alpar@255
   106
    
deba@1717
   107
    /// \brief The number of items stored in the heap.
deba@1717
   108
    ///
deba@1717
   109
    /// Returns the number of items stored in the heap.
jacint@373
   110
    int size() const { return num_items; }
jacint@373
   111
deba@1717
   112
    /// \brief Checks if the heap stores no items.
deba@1717
   113
    ///
deba@1717
   114
    ///   Returns \c true if and only if the heap stores no items.
jacint@373
   115
    bool empty() const { return num_items==0; }
jacint@373
   116
deba@1717
   117
    /// \brief Make empty this heap.
deba@1717
   118
    /// 
deba@2050
   119
    /// Make empty this heap. It does not change the cross reference
deba@2050
   120
    /// map.  If you want to reuse a heap what is not surely empty you
deba@2050
   121
    /// should first clear the heap and after that you should set the
deba@2050
   122
    /// cross reference map for each item to \c PRE_HEAP.
deba@1753
   123
    void clear() {
deba@1717
   124
      container.clear(); minimum = 0; num_items = 0;
deba@1717
   125
    }
jacint@373
   126
deba@1717
   127
    /// \brief \c item gets to the heap with priority \c value independently 
deba@1717
   128
    /// if \c item was already there.
deba@1717
   129
    ///
deba@1717
   130
    /// This method calls \ref push(\c item, \c value) if \c item is not
deba@1717
   131
    /// stored in the heap and it calls \ref decrease(\c item, \c value) or
deba@1717
   132
    /// \ref increase(\c item, \c value) otherwise.
jacint@387
   133
    void set (Item const item, PrioType const value); 
jacint@373
   134
    
deba@1717
   135
    /// \brief Adds \c item to the heap with priority \c value. 
deba@1717
   136
    ///    
deba@1717
   137
    /// Adds \c item to the heap with priority \c value. 
deba@1717
   138
    /// \pre \c item must not be stored in the heap. 
jacint@387
   139
    void push (Item const item, PrioType const value);
jacint@373
   140
    
deba@1717
   141
    /// \brief Returns the item with minimum priority relative to \c Compare.
deba@1717
   142
    ///
deba@1717
   143
    /// This method returns the item with minimum priority relative to \c
deba@1717
   144
    /// Compare.  
deba@1717
   145
    /// \pre The heap must be nonempty.  
jacint@373
   146
    Item top() const { return container[minimum].name; }
jacint@373
   147
deba@1717
   148
    /// \brief Returns the minimum priority relative to \c Compare.
deba@1717
   149
    ///
deba@1717
   150
    /// It returns the minimum priority relative to \c Compare.
deba@1717
   151
    /// \pre The heap must be nonempty.
jacint@373
   152
    PrioType prio() const { return container[minimum].prio; }
jacint@373
   153
    
deba@1717
   154
    /// \brief Returns the priority of \c item.
deba@1717
   155
    ///
deba@1717
   156
    /// This function returns the priority of \c item.
deba@1717
   157
    /// \pre \c item must be in the heap.
jacint@387
   158
    PrioType& operator[](const Item& item) { 
jacint@387
   159
      return container[iimap[item]].prio; 
jacint@387
   160
    }
jacint@373
   161
    
deba@1717
   162
    /// \brief Returns the priority of \c item.
deba@1717
   163
    ///
deba@1717
   164
    /// It returns the priority of \c item.
deba@1717
   165
    /// \pre \c item must be in the heap.
jacint@387
   166
    const PrioType& operator[](const Item& item) const { 
jacint@387
   167
      return container[iimap[item]].prio; 
alpar@255
   168
    }
alpar@255
   169
alpar@255
   170
deba@1717
   171
    /// \brief Deletes the item with minimum priority relative to \c Compare.
deba@1717
   172
    ///
deba@1717
   173
    /// This method deletes the item with minimum priority relative to \c
deba@1717
   174
    /// Compare from the heap.  
deba@1717
   175
    /// \pre The heap must be non-empty.  
jacint@373
   176
    void pop();
jacint@373
   177
deba@1717
   178
    /// \brief Deletes \c item from the heap.
deba@1717
   179
    ///
deba@1717
   180
    /// This method deletes \c item from the heap, if \c item was already
deba@1717
   181
    /// stored in the heap. It is quite inefficient in Fibonacci heaps.
jacint@387
   182
    void erase (const Item& item); 
jacint@373
   183
deba@1717
   184
    /// \brief Decreases the priority of \c item to \c value.
deba@1717
   185
    ///
deba@1717
   186
    /// This method decreases the priority of \c item to \c value.
deba@1717
   187
    /// \pre \c item must be stored in the heap with priority at least \c
deba@1717
   188
    ///   value relative to \c Compare.
jacint@387
   189
    void decrease (Item item, PrioType const value); 
jacint@373
   190
deba@1717
   191
    /// \brief Increases the priority of \c item to \c value.
deba@1717
   192
    ///
deba@1717
   193
    /// This method sets the priority of \c item to \c value. Though
deba@1717
   194
    /// there is no precondition on the priority of \c item, this
deba@1717
   195
    /// method should be used only if it is indeed necessary to increase
deba@1717
   196
    /// (relative to \c Compare) the priority of \c item, because this
deba@1717
   197
    /// method is inefficient.
jacint@387
   198
    void increase (Item item, PrioType const value) {
jacint@387
   199
      erase(item);
jacint@387
   200
      push(item, value);
jacint@373
   201
    }
jacint@373
   202
jacint@373
   203
deba@1717
   204
    /// \brief Returns if \c item is in, has already been in, or has never 
deba@1717
   205
    /// been in the heap.
deba@1717
   206
    ///
deba@1717
   207
    /// This method returns PRE_HEAP if \c item has never been in the
deba@1717
   208
    /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
deba@1717
   209
    /// otherwise. In the latter case it is possible that \c item will
deba@1717
   210
    /// get back to the heap again.
jacint@387
   211
    state_enum state(const Item &item) const {
jacint@387
   212
      int i=iimap[item];
jacint@387
   213
      if( i>=0 ) {
jacint@387
   214
	if ( container[i].in ) i=0;
jacint@387
   215
	else i=-2; 
jacint@387
   216
      }
jacint@387
   217
      return state_enum(i);
jacint@387
   218
    }    
deba@1902
   219
deba@1902
   220
    /// \brief Sets the state of the \c item in the heap.
deba@1902
   221
    ///
deba@1902
   222
    /// Sets the state of the \c item in the heap. It can be used to
deba@1902
   223
    /// manually clear the heap when it is important to achive the
deba@1902
   224
    /// better time complexity.
deba@1902
   225
    /// \param i The item.
deba@1902
   226
    /// \param st The state. It should not be \c IN_HEAP. 
deba@1902
   227
    void state(const Item& i, state_enum st) {
deba@1902
   228
      switch (st) {
deba@1902
   229
      case POST_HEAP:
deba@1902
   230
      case PRE_HEAP:
deba@1902
   231
        if (state(i) == IN_HEAP) {
deba@1902
   232
          erase(i);
deba@1902
   233
        }
deba@1903
   234
        iimap[i] = st;
deba@1902
   235
        break;
deba@1906
   236
      case IN_HEAP:
deba@1906
   237
        break;
deba@1902
   238
      }
deba@1902
   239
    }
jacint@387
   240
    
jacint@387
   241
  private:
jacint@387
   242
    
jacint@387
   243
    void balance();
jacint@387
   244
    void makeroot(int c);
jacint@387
   245
    void cut(int a, int b);
jacint@387
   246
    void cascade(int a);
jacint@387
   247
    void fuse(int a, int b);
jacint@387
   248
    void unlace(int a);
jacint@373
   249
jacint@373
   250
jacint@387
   251
    class store {
jacint@387
   252
      friend class FibHeap;
jacint@387
   253
      
jacint@387
   254
      Item name;
jacint@387
   255
      int parent;
jacint@387
   256
      int left_neighbor;
jacint@387
   257
      int right_neighbor;
jacint@387
   258
      int child;
jacint@387
   259
      int degree;  
jacint@387
   260
      bool marked;
jacint@387
   261
      bool in;
jacint@387
   262
      PrioType prio;
jacint@387
   263
      
jacint@387
   264
      store() : parent(-1), child(-1), degree(), marked(false), in(true) {} 
jacint@387
   265
    };
jacint@387
   266
  };    
jacint@387
   267
 
jacint@387
   268
jacint@373
   269
jacint@373
   270
    // **********************************************************************
jacint@373
   271
    //  IMPLEMENTATIONS
jacint@373
   272
    // **********************************************************************
jacint@373
   273
    
jacint@387
   274
  template <typename Item, typename Prio, typename ItemIntMap, 
jacint@387
   275
    typename Compare>
jacint@387
   276
  void FibHeap<Item, Prio, ItemIntMap, Compare>::set 
jacint@387
   277
  (Item const item, PrioType const value) 
jacint@387
   278
  {
jacint@387
   279
    int i=iimap[item];
jacint@387
   280
    if ( i >= 0 && container[i].in ) {
jacint@387
   281
      if ( comp(value, container[i].prio) ) decrease(item, value); 
jacint@387
   282
      if ( comp(container[i].prio, value) ) increase(item, value); 
jacint@387
   283
    } else push(item, value);
jacint@387
   284
  }
alpar@255
   285
    
jacint@387
   286
  template <typename Item, typename Prio, typename ItemIntMap, 
jacint@387
   287
    typename Compare>
jacint@387
   288
  void FibHeap<Item, Prio, ItemIntMap, Compare>::push 
jacint@387
   289
  (Item const item, PrioType const value) {
jacint@387
   290
      int i=iimap[item];      
alpar@255
   291
      if ( i < 0 ) {
alpar@255
   292
	int s=container.size();
jacint@387
   293
	iimap.set( item, s );	
alpar@255
   294
	store st;
jacint@387
   295
	st.name=item;
alpar@255
   296
	container.push_back(st);
alpar@255
   297
	i=s;
alpar@255
   298
      } else {
alpar@255
   299
	container[i].parent=container[i].child=-1;
alpar@255
   300
	container[i].degree=0;
alpar@255
   301
	container[i].in=true;
alpar@255
   302
	container[i].marked=false;
alpar@255
   303
      }
alpar@255
   304
alpar@255
   305
      if ( num_items ) {
alpar@255
   306
	container[container[minimum].right_neighbor].left_neighbor=i;
alpar@255
   307
	container[i].right_neighbor=container[minimum].right_neighbor;
alpar@255
   308
	container[minimum].right_neighbor=i;
alpar@255
   309
	container[i].left_neighbor=minimum;
alpar@255
   310
	if ( comp( value, container[minimum].prio) ) minimum=i; 
alpar@255
   311
      } else {
alpar@255
   312
	container[i].right_neighbor=container[i].left_neighbor=i;
alpar@255
   313
	minimum=i;	
alpar@255
   314
      }
alpar@255
   315
      container[i].prio=value;
alpar@255
   316
      ++num_items;
alpar@255
   317
    }
alpar@255
   318
    
jacint@387
   319
  template <typename Item, typename Prio, typename ItemIntMap, 
jacint@387
   320
    typename Compare>
jacint@387
   321
  void FibHeap<Item, Prio, ItemIntMap, Compare>::pop() {
alpar@255
   322
      /*The first case is that there are only one root.*/
alpar@255
   323
      if ( container[minimum].left_neighbor==minimum ) {
alpar@255
   324
	container[minimum].in=false;
alpar@255
   325
	if ( container[minimum].degree!=0 ) { 
alpar@255
   326
	  makeroot(container[minimum].child);
alpar@255
   327
	  minimum=container[minimum].child;
alpar@255
   328
	  balance();
alpar@255
   329
	}
alpar@255
   330
      } else {
alpar@255
   331
	int right=container[minimum].right_neighbor;
alpar@255
   332
	unlace(minimum);
alpar@255
   333
	container[minimum].in=false;
alpar@255
   334
	if ( container[minimum].degree > 0 ) {
alpar@255
   335
	  int left=container[minimum].left_neighbor;
alpar@255
   336
	  int child=container[minimum].child;
alpar@255
   337
	  int last_child=container[child].left_neighbor;
alpar@255
   338
	
alpar@255
   339
	  makeroot(child);
alpar@255
   340
	  
alpar@255
   341
	  container[left].right_neighbor=child;
alpar@255
   342
	  container[child].left_neighbor=left;
alpar@255
   343
	  container[right].left_neighbor=last_child;
alpar@255
   344
	  container[last_child].right_neighbor=right;
alpar@255
   345
	}
alpar@255
   346
	minimum=right;
alpar@255
   347
	balance();
alpar@255
   348
      } // the case where there are more roots
alpar@255
   349
      --num_items;   
alpar@255
   350
    }
alpar@255
   351
jacint@387
   352
jacint@387
   353
  template <typename Item, typename Prio, typename ItemIntMap, 
jacint@387
   354
    typename Compare>
jacint@387
   355
  void FibHeap<Item, Prio, ItemIntMap, Compare>::erase 
jacint@387
   356
  (const Item& item) {
jacint@387
   357
      int i=iimap[item];
alpar@255
   358
      
alpar@255
   359
      if ( i >= 0 && container[i].in ) { 	
alpar@255
   360
	if ( container[i].parent!=-1 ) {
alpar@255
   361
	  int p=container[i].parent;
alpar@255
   362
	  cut(i,p);	    
alpar@255
   363
	  cascade(p);
alpar@255
   364
	}
alpar@255
   365
	minimum=i;     //As if its prio would be -infinity
alpar@255
   366
	pop();
alpar@255
   367
      }
jacint@387
   368
  }
alpar@255
   369
    
jacint@387
   370
  template <typename Item, typename Prio, typename ItemIntMap, 
jacint@387
   371
    typename Compare>
jacint@387
   372
  void FibHeap<Item, Prio, ItemIntMap, Compare>::decrease 
jacint@387
   373
  (Item item, PrioType const value) {
jacint@387
   374
      int i=iimap[item];
alpar@255
   375
      container[i].prio=value;
alpar@255
   376
      int p=container[i].parent;
alpar@255
   377
      
alpar@255
   378
      if ( p!=-1 && comp(value, container[p].prio) ) {
alpar@255
   379
	cut(i,p);	    
alpar@255
   380
	cascade(p);
alpar@255
   381
      }      
alpar@255
   382
      if ( comp(value, container[minimum].prio) ) minimum=i; 
jacint@387
   383
  }
jacint@387
   384
 
alpar@255
   385
jacint@387
   386
  template <typename Item, typename Prio, typename ItemIntMap, 
jacint@387
   387
    typename Compare>
jacint@387
   388
  void FibHeap<Item, Prio, ItemIntMap, Compare>::balance() {      
alpar@255
   389
deba@1332
   390
    int maxdeg=int( std::floor( 2.08*log(double(container.size()))))+1;
alpar@255
   391
  
alpar@255
   392
    std::vector<int> A(maxdeg,-1); 
alpar@255
   393
    
alpar@255
   394
    /*
alpar@255
   395
     *Recall that now minimum does not point to the minimum prio element.
alpar@255
   396
     *We set minimum to this during balance().
alpar@255
   397
     */
alpar@255
   398
    int anchor=container[minimum].left_neighbor; 
alpar@255
   399
    int next=minimum; 
alpar@255
   400
    bool end=false; 
alpar@255
   401
    	
alpar@255
   402
       do {
alpar@255
   403
	int active=next;
alpar@255
   404
	if ( anchor==active ) end=true;
alpar@255
   405
	int d=container[active].degree;
alpar@255
   406
	next=container[active].right_neighbor;
alpar@255
   407
alpar@255
   408
	while (A[d]!=-1) {	  
alpar@255
   409
	  if( comp(container[active].prio, container[A[d]].prio) ) {
alpar@255
   410
	    fuse(active,A[d]); 
alpar@255
   411
	  } else { 
alpar@255
   412
	    fuse(A[d],active);
alpar@255
   413
	    active=A[d];
alpar@255
   414
	  } 
alpar@255
   415
	  A[d]=-1;
alpar@255
   416
	  ++d;
alpar@255
   417
	}	
alpar@255
   418
	A[d]=active;
alpar@255
   419
       } while ( !end );
alpar@255
   420
alpar@255
   421
alpar@255
   422
       while ( container[minimum].parent >=0 ) minimum=container[minimum].parent;
alpar@255
   423
       int s=minimum;
alpar@255
   424
       int m=minimum;
alpar@255
   425
       do {  
alpar@255
   426
	 if ( comp(container[s].prio, container[minimum].prio) ) minimum=s;
alpar@255
   427
	 s=container[s].right_neighbor;
alpar@255
   428
       } while ( s != m );
alpar@255
   429
    }
alpar@255
   430
jacint@387
   431
  template <typename Item, typename Prio, typename ItemIntMap, 
jacint@387
   432
    typename Compare>
jacint@387
   433
  void FibHeap<Item, Prio, ItemIntMap, Compare>::makeroot 
jacint@387
   434
  (int c) {
alpar@255
   435
      int s=c;
alpar@255
   436
      do {  
alpar@255
   437
	container[s].parent=-1;
alpar@255
   438
	s=container[s].right_neighbor;
alpar@255
   439
      } while ( s != c );
alpar@255
   440
    }
jacint@387
   441
  
jacint@387
   442
  
jacint@387
   443
  template <typename Item, typename Prio, typename ItemIntMap, 
jacint@387
   444
    typename Compare>
jacint@387
   445
  void FibHeap<Item, Prio, ItemIntMap, Compare>::cut 
jacint@387
   446
  (int a, int b) {    
jacint@387
   447
    /*
jacint@387
   448
     *Replacing a from the children of b.
jacint@387
   449
     */
jacint@387
   450
    --container[b].degree;
alpar@255
   451
    
jacint@387
   452
    if ( container[b].degree !=0 ) {
jacint@387
   453
      int child=container[b].child;
jacint@387
   454
      if ( child==a ) 
jacint@387
   455
	container[b].child=container[child].right_neighbor;
jacint@387
   456
      unlace(a);
jacint@387
   457
    }
jacint@387
   458
    
jacint@387
   459
    
jacint@387
   460
    /*Lacing a to the roots.*/
jacint@387
   461
    int right=container[minimum].right_neighbor;
jacint@387
   462
    container[minimum].right_neighbor=a;
jacint@387
   463
    container[a].left_neighbor=minimum;
jacint@387
   464
    container[a].right_neighbor=right;
jacint@387
   465
    container[right].left_neighbor=a;
jacint@387
   466
    
jacint@387
   467
    container[a].parent=-1;
jacint@387
   468
    container[a].marked=false;
jacint@387
   469
  }
jacint@387
   470
  
alpar@255
   471
jacint@387
   472
  template <typename Item, typename Prio, typename ItemIntMap, 
jacint@387
   473
    typename Compare>
jacint@387
   474
  void FibHeap<Item, Prio, ItemIntMap, Compare>::cascade 
jacint@387
   475
  (int a) 
alpar@255
   476
    {
alpar@255
   477
      if ( container[a].parent!=-1 ) {
alpar@255
   478
	int p=container[a].parent;
alpar@255
   479
	
alpar@255
   480
	if ( container[a].marked==false ) container[a].marked=true;
alpar@255
   481
	else {
alpar@255
   482
	  cut(a,p);
alpar@255
   483
	  cascade(p);
alpar@255
   484
	}
alpar@255
   485
      }
alpar@255
   486
    }
alpar@255
   487
alpar@255
   488
jacint@387
   489
  template <typename Item, typename Prio, typename ItemIntMap, 
jacint@387
   490
    typename Compare>
jacint@387
   491
  void FibHeap<Item, Prio, ItemIntMap, Compare>::fuse 
jacint@387
   492
  (int a, int b) {
alpar@255
   493
      unlace(b);
alpar@255
   494
      
alpar@255
   495
      /*Lacing b under a.*/
alpar@255
   496
      container[b].parent=a;
alpar@255
   497
alpar@255
   498
      if (container[a].degree==0) {
alpar@255
   499
	container[b].left_neighbor=b;
alpar@255
   500
	container[b].right_neighbor=b;
alpar@255
   501
	container[a].child=b;	
alpar@255
   502
      } else {
alpar@255
   503
	int child=container[a].child;
alpar@255
   504
	int last_child=container[child].left_neighbor;
alpar@255
   505
	container[child].left_neighbor=b;
alpar@255
   506
	container[b].right_neighbor=child;
alpar@255
   507
	container[last_child].right_neighbor=b;
alpar@255
   508
	container[b].left_neighbor=last_child;
alpar@255
   509
      }
alpar@255
   510
alpar@255
   511
      ++container[a].degree;
alpar@255
   512
      
alpar@255
   513
      container[b].marked=false;
alpar@255
   514
    }
alpar@255
   515
jacint@387
   516
  
jacint@387
   517
  /*
jacint@387
   518
   *It is invoked only if a has siblings.
jacint@387
   519
   */
jacint@387
   520
  template <typename Item, typename Prio, typename ItemIntMap, 
jacint@387
   521
    typename Compare>
jacint@387
   522
  void FibHeap<Item, Prio, ItemIntMap, Compare>::unlace 
jacint@387
   523
  (int a) {      
alpar@255
   524
      int leftn=container[a].left_neighbor;
alpar@255
   525
      int rightn=container[a].right_neighbor;
alpar@255
   526
      container[leftn].right_neighbor=rightn;
alpar@255
   527
      container[rightn].left_neighbor=leftn;
jacint@387
   528
  }
alpar@255
   529
  
alpar@430
   530
alpar@921
   531
} //namespace lemon
alpar@477
   532
alpar@921
   533
#endif //LEMON_FIB_HEAP_H
alpar@477
   534