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