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