src/work/deba/bin_heap.h
author deba
Wed, 08 Sep 2004 12:06:45 +0000
changeset 822 88226d9fe821
parent 542 69bde1d90c04
child 921 818510fa3d99
permissions -rw-r--r--
The MapFactories have been removed from the code because
if we use macros then they increases only the complexity.

The pair iterators of the maps are separeted from the maps.

Some macros and comments has been changed.
klao@274
     1
// -*- C++ -*- //
klao@274
     2
klao@39
     3
/* FIXME: Copyright ... 
klao@39
     4
 *
klao@39
     5
 * This implementation is heavily based on STL's heap functions and
klao@39
     6
 * the similar class by Alpar Juttner in IKTA...
klao@39
     7
 */
klao@39
     8
klao@39
     9
/******
klao@39
    10
 *
klao@172
    11
 * BinHeap<ItemType, PrioType, ItemIntMap, [PrioCompare]>
klao@39
    12
 *
klao@172
    13
 * Ez az osztaly item-prioritas parok tarolasara alkalmas binaris kupacot
klao@39
    14
 * valosit meg.
klao@172
    15
 * A kupacban legfolul mindig az a par talalhato, amiben a prioritas a
klao@39
    16
 * legkisebb. (Gondolj a Dijkstra pont-tavolsag kupacara; igazabol ahhoz
klao@39
    17
 * lett keszitve...)
klao@39
    18
 *
klao@172
    19
 * Megjegyzes: a kupacos temakorokben a prioritast kulcsnak szoktak nevezni,
klao@172
    20
 * de mivel ez zavaro tud lenni a property-map-es kulcs-ertek szohasznalata
klao@172
    21
 * miatt, megprobaltunk valami semleges elnevezeseket kitalalni.
klao@39
    22
 *
klao@39
    23
 * A hasznalatahoz szukseg van egy irhato/olvashato property_map-re, ami
klao@172
    24
 * az itemekhez egy int-et tud tarolni (ezzel tudom megkeresni az illeto
klao@39
    25
 * elemet a kupacban a csokkentes es hasonlo muveletekhez).
klao@39
    26
 * A map-re csak referenciat tarol, ugy hogy a kupac elete folyan a map-nek
klao@39
    27
 * is elnie kell. (???)
klao@39
    28
 *
klao@39
    29
 * Ketfele modon hasznalhato:
klao@39
    30
 * Lusta mod:
klao@172
    31
 * set(Item, Prio) metodussal pakolunk a kupacba,
klao@39
    32
 * aztan o majd eldonti, hogy ez az elem mar benne van-e es ha igen, akkor
klao@39
    33
 * csokkentettunk-e rajta, vagy noveltunk.
klao@39
    34
 * Ehhez nagyon fontos, hogy az atadott property map inicializalva legyen
klao@39
    35
 * minden szobajovo kulcs ertekre, -1 -es ertekkel!
klao@39
    36
 * Es ilyen esetben a kulcsokrol lekerdezheto az allapotuk a state metodussal:
klao@39
    37
 * (nem jart meg a kupacban PRE_HEAP=-1, epp a kupacban van IN_HEAP=0,
klao@39
    38
 *  mar kikerult a kupacbol POST_HEAP=-2).
klao@39
    39
 * Szoval ebben a modban a kupac nagyjabol hasznalhato property_map-kent, csak
klao@172
    40
 * meg meg tudja mondani a "legkisebb" prioritasu elemet. De csak nagyjabol,
klao@39
    41
 * hiszen a kupacbol kikerult elemeknek elvesz az ertekuk...
klao@39
    42
 *
klao@39
    43
 * Kozvetlen mod:
klao@172
    44
 * push(Item, Prio) metodussal belerakunk a kupacba (ha az illeto kulcs mar
klao@39
    45
 * benn volt, akkor gaz).
klao@172
    46
 * increase/decrease(Item i, Prio new_prio) metodusokkal lehet
klao@172
    47
 * novelni/csokkenteni az illeto elemhez tartozo prioritast. (Ha nem volt
klao@172
    48
 * megbenne a kupacban az illeto elem, vagy nem abba az iranyba valtoztattad
klao@39
    49
 * az erteket, amerre mondtad -- gaz).
klao@39
    50
 *
klao@39
    51
 * Termeszetesen a fenti ket modot ertelemszeruen lehet keverni.
klao@39
    52
 * Ja es mindig nagyon gaz, ha belepiszkalsz a map-be, amit a kupac
klao@39
    53
 * hasznal. :-))
klao@39
    54
 *
klao@39
    55
 *
klao@39
    56
 * Bocs, most faradt vagyok, majd egyszer leforditom. (Misi)
klao@39
    57
 *
klao@39
    58
 */
klao@39
    59
klao@39
    60
ladanyi@542
    61
#ifndef HUGO_BIN_HEAP_H
ladanyi@542
    62
#define HUGO_BIN_HEAP_H
klao@37
    63
klao@491
    64
///\ingroup auxdat
klao@274
    65
///\file
klao@274
    66
///\brief Binary Heap implementation.
klao@274
    67
klao@37
    68
#include <vector>
klao@37
    69
#include <utility>
klao@37
    70
#include <functional>
klao@37
    71
alpar@114
    72
namespace hugo {
klao@37
    73
alpar@430
    74
  /// \addtogroup auxdat
alpar@430
    75
  /// @{
alpar@430
    76
alpar@430
    77
   /// A Binary Heap implementation.
klao@172
    78
  template <typename Item, typename Prio, typename ItemIntMap,
klao@172
    79
	    typename Compare = std::less<Prio> >
klao@37
    80
  class BinHeap {
klao@37
    81
klao@37
    82
  public:
klao@172
    83
    typedef Item                             ItemType;
klao@37
    84
    // FIXME: stl-ben nem ezt hivjak value_type -nak, hanem a kovetkezot...
klao@172
    85
    typedef Prio                             PrioType;
klao@172
    86
    typedef std::pair<ItemType,PrioType>     PairType;
klao@172
    87
    typedef ItemIntMap                       ItemIntMapType;
klao@172
    88
    typedef Compare                          PrioCompare;
klao@37
    89
klao@37
    90
    /**
klao@172
    91
     * Each Item element have a state associated to it. It may be "in heap",
klao@37
    92
     * "pre heap" or "post heap". The later two are indifferent from the
klao@37
    93
     * heap's point of view, but may be useful to the user.
klao@37
    94
     *
klao@172
    95
     * The ItemIntMap _should_ be initialized in such way, that it maps
klao@37
    96
     * PRE_HEAP (-1) to any element to be put in the heap...
klao@37
    97
     */
klao@274
    98
    ///\todo it is used nowhere
klao@274
    99
    ///
klao@39
   100
    enum state_enum {
klao@37
   101
      IN_HEAP = 0,
klao@37
   102
      PRE_HEAP = -1,
klao@37
   103
      POST_HEAP = -2
klao@37
   104
    };
klao@37
   105
klao@37
   106
  private:
klao@37
   107
    std::vector<PairType> data;
klao@37
   108
    Compare comp;
klao@37
   109
    // FIXME: jo ez igy???
klao@172
   110
    ItemIntMap &iim;
klao@37
   111
klao@37
   112
  public:
klao@172
   113
    BinHeap(ItemIntMap &_iim) : iim(_iim) {}
klao@172
   114
    BinHeap(ItemIntMap &_iim, const Compare &_comp) : comp(_comp), iim(_iim) {}
klao@37
   115
klao@37
   116
klao@37
   117
    int size() const { return data.size(); }
klao@41
   118
    bool empty() const { return data.empty(); }
klao@37
   119
klao@37
   120
  private:
klao@37
   121
    static int parent(int i) { return (i-1)/2; }
klao@37
   122
    static int second_child(int i) { return 2*i+2; }
klao@214
   123
    bool less(const PairType &p1, const PairType &p2) const {
klao@37
   124
      return comp(p1.second, p2.second);
klao@37
   125
    }
klao@37
   126
klao@37
   127
    int bubble_up(int hole, PairType p);
klao@37
   128
    int bubble_down(int hole, PairType p, int length);
klao@37
   129
klao@37
   130
    void move(const PairType &p, int i) {
klao@37
   131
      data[i] = p;
klao@172
   132
      iim.set(p.first, i);
klao@37
   133
    }
klao@37
   134
klao@41
   135
    void rmidx(int h) {
klao@41
   136
      int n = data.size()-1;
klao@41
   137
      if( h>=0 && h<=n ) {
klao@172
   138
	iim.set(data[h].first, POST_HEAP);
klao@41
   139
	if ( h<n ) {
klao@41
   140
	  bubble_down(h, data[n], n);
klao@41
   141
	}
klao@41
   142
	data.pop_back();
klao@41
   143
      }
klao@41
   144
    }
klao@41
   145
klao@37
   146
  public:
klao@37
   147
    void push(const PairType &p) {
klao@37
   148
      int n = data.size();
klao@37
   149
      data.resize(n+1);
klao@37
   150
      bubble_up(n, p);
klao@37
   151
    }
klao@172
   152
    void push(const Item &i, const Prio &p) { push(PairType(i,p)); }
klao@37
   153
klao@172
   154
    Item top() const {
klao@37
   155
      return data[0].first;
klao@37
   156
    }
klao@274
   157
    /// Returns the prio of the top element of the heap.
klao@274
   158
    Prio prio() const {
klao@37
   159
      return data[0].second;
klao@37
   160
    }
klao@37
   161
klao@37
   162
    void pop() {
klao@41
   163
      rmidx(0);
klao@41
   164
    }
klao@41
   165
klao@172
   166
    void erase(const Item &i) {
jacint@221
   167
      rmidx(iim[i]);
klao@37
   168
    }
klao@37
   169
klao@274
   170
    Prio operator[](const Item &i) const {
jacint@221
   171
      int idx = iim[i];
klao@37
   172
      return data[idx].second;
klao@37
   173
    }
klao@274
   174
klao@172
   175
    void set(const Item &i, const Prio &p) {
jacint@221
   176
      int idx = iim[i];
klao@37
   177
      if( idx < 0 ) {
klao@172
   178
	push(i,p);
klao@37
   179
      }
klao@172
   180
      else if( comp(p, data[idx].second) ) {
klao@172
   181
	bubble_up(idx, PairType(i,p));
klao@37
   182
      }
klao@37
   183
      else {
klao@172
   184
	bubble_down(idx, PairType(i,p), data.size());
klao@37
   185
      }
klao@37
   186
    }
klao@37
   187
klao@172
   188
    void decrease(const Item &i, const Prio &p) {
jacint@221
   189
      int idx = iim[i];
klao@172
   190
      bubble_up(idx, PairType(i,p));
klao@37
   191
    }
klao@172
   192
    void increase(const Item &i, const Prio &p) {
jacint@221
   193
      int idx = iim[i];
klao@172
   194
      bubble_down(idx, PairType(i,p), data.size());
klao@37
   195
    }
klao@37
   196
klao@172
   197
    state_enum state(const Item &i) const {
jacint@221
   198
      int s = iim[i];
klao@39
   199
      if( s>=0 )
klao@39
   200
	s=0;
klao@39
   201
      return state_enum(s);
klao@39
   202
    }
klao@39
   203
klao@37
   204
  }; // class BinHeap
klao@37
   205
klao@37
   206
  
klao@37
   207
  template <typename K, typename V, typename M, typename C>
klao@37
   208
  int BinHeap<K,V,M,C>::bubble_up(int hole, PairType p) {
klao@37
   209
    int par = parent(hole);
klao@37
   210
    while( hole>0 && less(p,data[par]) ) {
klao@37
   211
      move(data[par],hole);
klao@37
   212
      hole = par;
klao@37
   213
      par = parent(hole);
klao@37
   214
    }
klao@37
   215
    move(p, hole);
klao@37
   216
    return hole;
klao@37
   217
  }
klao@37
   218
klao@37
   219
  template <typename K, typename V, typename M, typename C>
klao@37
   220
  int BinHeap<K,V,M,C>::bubble_down(int hole, PairType p, int length) {
klao@37
   221
    int child = second_child(hole);
klao@37
   222
    while(child < length) {
klao@37
   223
      if( less(data[child-1], data[child]) ) {
klao@37
   224
	--child;
klao@37
   225
      }
klao@37
   226
      if( !less(data[child], p) )
klao@37
   227
	goto ok;
klao@37
   228
      move(data[child], hole);
klao@37
   229
      hole = child;
klao@37
   230
      child = second_child(hole);
klao@37
   231
    }
klao@37
   232
    child--;
klao@37
   233
    if( child<length && less(data[child], p) ) {
klao@37
   234
      move(data[child], hole);
klao@37
   235
      hole=child;
klao@37
   236
    }
klao@37
   237
  ok:
klao@37
   238
    move(p, hole);
klao@37
   239
    return hole;
klao@37
   240
  }
klao@37
   241
alpar@430
   242
  ///@}
alpar@430
   243
alpar@114
   244
} // namespace hugo
klao@37
   245
klao@37
   246
#endif // BIN_HEAP_HH