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