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