lemon/bin_heap.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
parent 1956 a055123339d5
child 2258 741995f3dbc4
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++ -*-
klao@39
     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).
klao@39
     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.
klao@39
    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.
klao@39
    16
 *
klao@39
    17
 */
klao@39
    18
alpar@921
    19
#ifndef LEMON_BIN_HEAP_H
alpar@921
    20
#define LEMON_BIN_HEAP_H
klao@37
    21
klao@491
    22
///\ingroup auxdat
klao@274
    23
///\file
klao@274
    24
///\brief Binary Heap implementation.
klao@274
    25
klao@37
    26
#include <vector>
klao@37
    27
#include <utility>
klao@37
    28
#include <functional>
klao@37
    29
alpar@921
    30
namespace lemon {
klao@37
    31
deba@1834
    32
  /// \ingroup auxdat
alpar@430
    33
jacint@1270
    34
  /// A Binary Heap implementation.
alpar@967
    35
  
jacint@1270
    36
  ///This class implements the \e binary \e heap data structure. A \e heap
jacint@1270
    37
  ///is a data structure for storing items with specified values called \e
jacint@1270
    38
  ///priorities in such a way that finding the item with minimum priority is
jacint@1270
    39
  ///efficient. \c Compare specifies the ordering of the priorities. In a heap
jacint@1270
    40
  ///one can change the priority of an item, add or erase an item, etc.
jacint@1270
    41
  ///
jacint@1270
    42
  ///\param Item Type of the items to be stored.  
jacint@1270
    43
  ///\param Prio Type of the priority of the items.
jacint@1270
    44
  ///\param ItemIntMap A read and writable Item int map, used internally
jacint@1270
    45
  ///to handle the cross references.
jacint@1270
    46
  ///\param Compare A class for the ordering of the priorities. The
jacint@1270
    47
  ///default is \c std::less<Prio>.
alpar@967
    48
  ///
alpar@967
    49
  ///\sa FibHeap
alpar@967
    50
  ///\sa Dijkstra
klao@172
    51
  template <typename Item, typename Prio, typename ItemIntMap,
klao@172
    52
	    typename Compare = std::less<Prio> >
klao@37
    53
  class BinHeap {
klao@37
    54
klao@37
    55
  public:
klao@172
    56
    typedef Item                             ItemType;
klao@37
    57
    // FIXME: stl-ben nem ezt hivjak value_type -nak, hanem a kovetkezot...
klao@172
    58
    typedef Prio                             PrioType;
klao@172
    59
    typedef std::pair<ItemType,PrioType>     PairType;
klao@172
    60
    typedef ItemIntMap                       ItemIntMapType;
klao@172
    61
    typedef Compare                          PrioCompare;
klao@37
    62
deba@1331
    63
    /// \brief Type to represent the items states.
klao@274
    64
    ///
deba@1331
    65
    /// Each Item element have a state associated to it. It may be "in heap",
alpar@1336
    66
    /// "pre heap" or "post heap". The latter two are indifferent from the
deba@1331
    67
    /// heap's point of view, but may be useful to the user.
deba@1331
    68
    ///
alpar@1336
    69
    /// The ItemIntMap \e should be initialized in such way that it maps
deba@1331
    70
    /// PRE_HEAP (-1) to any element to be put in the heap...
klao@39
    71
    enum state_enum {
klao@37
    72
      IN_HEAP = 0,
klao@37
    73
      PRE_HEAP = -1,
klao@37
    74
      POST_HEAP = -2
klao@37
    75
    };
klao@37
    76
klao@37
    77
  private:
klao@37
    78
    std::vector<PairType> data;
klao@37
    79
    Compare comp;
klao@172
    80
    ItemIntMap &iim;
klao@37
    81
klao@37
    82
  public:
deba@1331
    83
    /// \brief The constructor.
deba@1331
    84
    ///
deba@1331
    85
    /// The constructor.
deba@1331
    86
    /// \param _iim should be given to the constructor, since it is used
deba@1331
    87
    /// internally to handle the cross references. The value of the map
deba@1331
    88
    /// should be PRE_HEAP (-1) for each element.
deba@1185
    89
    explicit BinHeap(ItemIntMap &_iim) : iim(_iim) {}
jacint@1270
    90
    
deba@1331
    91
    /// \brief The constructor.
deba@1331
    92
    ///
deba@1331
    93
    /// The constructor.
deba@1331
    94
    /// \param _iim should be given to the constructor, since it is used
deba@1331
    95
    /// internally to handle the cross references. The value of the map
deba@1331
    96
    /// should be PRE_HEAP (-1) for each element.
deba@1331
    97
    ///
deba@1331
    98
    /// \param _comp The comparator function object.
deba@1191
    99
    BinHeap(ItemIntMap &_iim, const Compare &_comp) 
deba@1185
   100
      : iim(_iim), comp(_comp) {}
klao@37
   101
klao@37
   102
deba@1331
   103
    /// The number of items stored in the heap.
deba@1331
   104
    ///
deba@1331
   105
    /// \brief Returns the number of items stored in the heap.
klao@37
   106
    int size() const { return data.size(); }
jacint@1270
   107
    
deba@1331
   108
    /// \brief Checks if the heap stores no items.
deba@1331
   109
    ///
deba@1331
   110
    /// Returns \c true if and only if the heap stores no items.
klao@41
   111
    bool empty() const { return data.empty(); }
klao@37
   112
deba@1717
   113
    /// \brief Make empty this heap.
deba@1717
   114
    /// 
deba@2050
   115
    /// Make empty this heap. It does not change the cross reference map.
deba@2050
   116
    /// If you want to reuse what is not surely empty you should first clear
deba@2050
   117
    /// the heap and after that you should set the cross reference map for
deba@2050
   118
    /// each item to \c PRE_HEAP.
deba@1717
   119
    void clear() { 
deba@1717
   120
      data.clear(); 
deba@1717
   121
    }
deba@1717
   122
klao@37
   123
  private:
klao@37
   124
    static int parent(int i) { return (i-1)/2; }
klao@37
   125
    static int second_child(int i) { return 2*i+2; }
klao@214
   126
    bool less(const PairType &p1, const PairType &p2) const {
klao@37
   127
      return comp(p1.second, p2.second);
klao@37
   128
    }
klao@37
   129
klao@37
   130
    int bubble_up(int hole, PairType p);
klao@37
   131
    int bubble_down(int hole, PairType p, int length);
klao@37
   132
klao@37
   133
    void move(const PairType &p, int i) {
klao@37
   134
      data[i] = p;
klao@172
   135
      iim.set(p.first, i);
klao@37
   136
    }
klao@37
   137
klao@41
   138
    void rmidx(int h) {
klao@41
   139
      int n = data.size()-1;
klao@41
   140
      if( h>=0 && h<=n ) {
klao@172
   141
	iim.set(data[h].first, POST_HEAP);
klao@41
   142
	if ( h<n ) {
klao@41
   143
	  bubble_down(h, data[n], n);
klao@41
   144
	}
klao@41
   145
	data.pop_back();
klao@41
   146
      }
klao@41
   147
    }
klao@41
   148
klao@37
   149
  public:
deba@1331
   150
    /// \brief Insert a pair of item and priority into the heap.
deba@1331
   151
    ///
deba@1331
   152
    /// Adds \c p.first to the heap with priority \c p.second.
deba@1331
   153
    /// \param p The pair to insert.
klao@37
   154
    void push(const PairType &p) {
klao@37
   155
      int n = data.size();
klao@37
   156
      data.resize(n+1);
klao@37
   157
      bubble_up(n, p);
klao@37
   158
    }
jacint@1270
   159
deba@1331
   160
    /// \brief Insert an item into the heap with the given heap.
deba@1331
   161
    ///    
deba@1331
   162
    /// Adds \c i to the heap with priority \c p. 
deba@1331
   163
    /// \param i The item to insert.
deba@1331
   164
    /// \param p The priority of the item.
klao@172
   165
    void push(const Item &i, const Prio &p) { push(PairType(i,p)); }
klao@37
   166
deba@1331
   167
    /// \brief Returns the item with minimum priority relative to \c Compare.
deba@1331
   168
    ///
deba@1331
   169
    /// This method returns the item with minimum priority relative to \c
deba@1331
   170
    /// Compare.  
deba@1331
   171
    /// \pre The heap must be nonempty.  
klao@172
   172
    Item top() const {
klao@37
   173
      return data[0].first;
klao@37
   174
    }
jacint@1270
   175
deba@1331
   176
    /// \brief Returns the minimum priority relative to \c Compare.
deba@1331
   177
    ///
deba@1331
   178
    /// It returns the minimum priority relative to \c Compare.
deba@1331
   179
    /// \pre The heap must be nonempty.
klao@274
   180
    Prio prio() const {
klao@37
   181
      return data[0].second;
klao@37
   182
    }
klao@37
   183
deba@1331
   184
    /// \brief Deletes the item with minimum priority relative to \c Compare.
deba@1331
   185
    ///
deba@1331
   186
    /// This method deletes the item with minimum priority relative to \c
deba@1331
   187
    /// Compare from the heap.  
deba@1331
   188
    /// \pre The heap must be non-empty.  
klao@37
   189
    void pop() {
klao@41
   190
      rmidx(0);
klao@41
   191
    }
klao@41
   192
deba@1331
   193
    /// \brief Deletes \c i from the heap.
deba@1331
   194
    ///
deba@1331
   195
    /// This method deletes item \c i from the heap, if \c i was
deba@1331
   196
    /// already stored in the heap.
deba@1331
   197
    /// \param i The item to erase. 
klao@172
   198
    void erase(const Item &i) {
jacint@221
   199
      rmidx(iim[i]);
klao@37
   200
    }
klao@37
   201
jacint@1270
   202
    
deba@1331
   203
    /// \brief Returns the priority of \c i.
deba@1331
   204
    ///
deba@1331
   205
    /// This function returns the priority of item \c i.  
deba@1331
   206
    /// \pre \c i must be in the heap.
deba@1331
   207
    /// \param i The item.
klao@274
   208
    Prio operator[](const Item &i) const {
jacint@221
   209
      int idx = iim[i];
klao@37
   210
      return data[idx].second;
klao@37
   211
    }
klao@274
   212
deba@1331
   213
    /// \brief \c i gets to the heap with priority \c p independently 
deba@1331
   214
    /// if \c i was already there.
deba@1331
   215
    ///
deba@1331
   216
    /// This method calls \ref push(\c i, \c p) if \c i is not stored
deba@1331
   217
    /// in the heap and sets the priority of \c i to \c p otherwise.
deba@1331
   218
    /// \param i The item.
deba@1331
   219
    /// \param p The priority.
klao@172
   220
    void set(const Item &i, const Prio &p) {
jacint@221
   221
      int idx = iim[i];
klao@37
   222
      if( idx < 0 ) {
klao@172
   223
	push(i,p);
klao@37
   224
      }
klao@172
   225
      else if( comp(p, data[idx].second) ) {
klao@172
   226
	bubble_up(idx, PairType(i,p));
klao@37
   227
      }
klao@37
   228
      else {
klao@172
   229
	bubble_down(idx, PairType(i,p), data.size());
klao@37
   230
      }
klao@37
   231
    }
klao@37
   232
deba@1331
   233
    /// \brief Decreases the priority of \c i to \c p.
jacint@1270
   234
deba@1331
   235
    /// This method decreases the priority of item \c i to \c p.
deba@1331
   236
    /// \pre \c i must be stored in the heap with priority at least \c
deba@1331
   237
    /// p relative to \c Compare.
deba@1331
   238
    /// \param i The item.
deba@1331
   239
    /// \param p The priority.
klao@172
   240
    void decrease(const Item &i, const Prio &p) {
jacint@221
   241
      int idx = iim[i];
klao@172
   242
      bubble_up(idx, PairType(i,p));
klao@37
   243
    }
jacint@1270
   244
    
deba@1331
   245
    /// \brief Increases the priority of \c i to \c p.
deba@1331
   246
    ///
deba@1331
   247
    /// This method sets the priority of item \c i to \c p. 
deba@1331
   248
    /// \pre \c i must be stored in the heap with priority at most \c
deba@1331
   249
    /// p relative to \c Compare.
deba@1331
   250
    /// \param i The item.
deba@1331
   251
    /// \param p The priority.
klao@172
   252
    void increase(const Item &i, const Prio &p) {
jacint@221
   253
      int idx = iim[i];
klao@172
   254
      bubble_down(idx, PairType(i,p), data.size());
klao@37
   255
    }
klao@37
   256
deba@1331
   257
    /// \brief Returns if \c item is in, has already been in, or has 
deba@1331
   258
    /// never been in the heap.
deba@1331
   259
    ///
deba@1331
   260
    /// This method returns PRE_HEAP if \c item has never been in the
deba@1331
   261
    /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
deba@1331
   262
    /// otherwise. In the latter case it is possible that \c item will
deba@1331
   263
    /// get back to the heap again.
deba@1331
   264
    /// \param i The item.
klao@172
   265
    state_enum state(const Item &i) const {
jacint@221
   266
      int s = iim[i];
klao@39
   267
      if( s>=0 )
klao@39
   268
	s=0;
klao@39
   269
      return state_enum(s);
klao@39
   270
    }
klao@39
   271
deba@1902
   272
    /// \brief Sets the state of the \c item in the heap.
deba@1902
   273
    ///
deba@1902
   274
    /// Sets the state of the \c item in the heap. It can be used to
deba@1902
   275
    /// manually clear the heap when it is important to achive the
deba@1902
   276
    /// better time complexity.
deba@1902
   277
    /// \param i The item.
deba@1902
   278
    /// \param st The state. It should not be \c IN_HEAP. 
deba@1902
   279
    void state(const Item& i, state_enum st) {
deba@1902
   280
      switch (st) {
deba@1902
   281
      case POST_HEAP:
deba@1902
   282
      case PRE_HEAP:
deba@1902
   283
        if (state(i) == IN_HEAP) {
deba@1902
   284
          erase(i);
deba@1902
   285
        }
deba@1903
   286
        iim[i] = st;
deba@1902
   287
        break;
deba@1906
   288
      case IN_HEAP:
deba@1906
   289
        break;
deba@1902
   290
      }
deba@1902
   291
    }
deba@1902
   292
klao@37
   293
  }; // class BinHeap
klao@37
   294
klao@37
   295
  
klao@37
   296
  template <typename K, typename V, typename M, typename C>
klao@37
   297
  int BinHeap<K,V,M,C>::bubble_up(int hole, PairType p) {
klao@37
   298
    int par = parent(hole);
klao@37
   299
    while( hole>0 && less(p,data[par]) ) {
klao@37
   300
      move(data[par],hole);
klao@37
   301
      hole = par;
klao@37
   302
      par = parent(hole);
klao@37
   303
    }
klao@37
   304
    move(p, hole);
klao@37
   305
    return hole;
klao@37
   306
  }
klao@37
   307
klao@37
   308
  template <typename K, typename V, typename M, typename C>
klao@37
   309
  int BinHeap<K,V,M,C>::bubble_down(int hole, PairType p, int length) {
klao@37
   310
    int child = second_child(hole);
klao@37
   311
    while(child < length) {
klao@37
   312
      if( less(data[child-1], data[child]) ) {
klao@37
   313
	--child;
klao@37
   314
      }
klao@37
   315
      if( !less(data[child], p) )
klao@37
   316
	goto ok;
klao@37
   317
      move(data[child], hole);
klao@37
   318
      hole = child;
klao@37
   319
      child = second_child(hole);
klao@37
   320
    }
klao@37
   321
    child--;
klao@37
   322
    if( child<length && less(data[child], p) ) {
klao@37
   323
      move(data[child], hole);
klao@37
   324
      hole=child;
klao@37
   325
    }
klao@37
   326
  ok:
klao@37
   327
    move(p, hole);
klao@37
   328
    return hole;
klao@37
   329
  }
klao@37
   330
alpar@430
   331
alpar@921
   332
} // namespace lemon
klao@37
   333
alpar@921
   334
#endif // LEMON_BIN_HEAP_H