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