src/include/bin_heap.hh
changeset 212 c07e4dd32438
parent 114 bb07dd5b2d67
child 214 44f01e580f16
equal deleted inserted replaced
3:6065f44a7450 4:4966e0fb69f3
     4  * the similar class by Alpar Juttner in IKTA...
     4  * the similar class by Alpar Juttner in IKTA...
     5  */
     5  */
     6 
     6 
     7 /******
     7 /******
     8  *
     8  *
     9  * BinHeap<KeyType, ValueType, KeyIntMap, [ValueCompare]>
     9  * BinHeap<ItemType, PrioType, ItemIntMap, [PrioCompare]>
    10  *
    10  *
    11  * Ez az osztaly kulcs-ertek parok tarolasara alkalmas binaris kupacot
    11  * Ez az osztaly item-prioritas parok tarolasara alkalmas binaris kupacot
    12  * valosit meg.
    12  * valosit meg.
    13  * A kupacban legfolul mindig az a par talalhato, amiben az _ertek_ a
    13  * A kupacban legfolul mindig az a par talalhato, amiben a prioritas a
    14  * legkisebb. (Gondolj a Dijkstra pont-tavolsag kupacara; igazabol ahhoz
    14  * legkisebb. (Gondolj a Dijkstra pont-tavolsag kupacara; igazabol ahhoz
    15  * lett keszitve...)
    15  * lett keszitve...)
    16  *
    16  *
    17  * Megjegyzes: egy kicsit gyanus nekem, hogy a kupacos temakorben nem
    17  * Megjegyzes: a kupacos temakorokben a prioritast kulcsnak szoktak nevezni,
    18  * azt hivjak kulcsnak, amit most en annak nevezek. :) En olyan 
    18  * de mivel ez zavaro tud lenni a property-map-es kulcs-ertek szohasznalata
    19  * property_map -os ertelemben hasznalom.
    19  * miatt, megprobaltunk valami semleges elnevezeseket kitalalni.
    20  *
    20  *
    21  * A hasznalatahoz szukseg van egy irhato/olvashato property_map-re, ami
    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
    22  * az itemekhez egy int-et tud tarolni (ezzel tudom megkeresni az illeto
    23  * elemet a kupacban a csokkentes es hasonlo muveletekhez).
    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
    24  * A map-re csak referenciat tarol, ugy hogy a kupac elete folyan a map-nek
    25  * is elnie kell. (???)
    25  * is elnie kell. (???)
    26  *
    26  *
    27  * Ketfele modon hasznalhato:
    27  * Ketfele modon hasznalhato:
    28  * Lusta mod:
    28  * Lusta mod:
    29  * put(Key, Value) metodussal pakolunk a kupacba,
    29  * set(Item, Prio) metodussal pakolunk a kupacba,
    30  * aztan o majd eldonti, hogy ez az elem mar benne van-e es ha igen, akkor
    30  * aztan o majd eldonti, hogy ez az elem mar benne van-e es ha igen, akkor
    31  * csokkentettunk-e rajta, vagy noveltunk.
    31  * csokkentettunk-e rajta, vagy noveltunk.
    32  * Ehhez nagyon fontos, hogy az atadott property map inicializalva legyen
    32  * Ehhez nagyon fontos, hogy az atadott property map inicializalva legyen
    33  * minden szobajovo kulcs ertekre, -1 -es ertekkel!
    33  * minden szobajovo kulcs ertekre, -1 -es ertekkel!
    34  * Es ilyen esetben a kulcsokrol lekerdezheto az allapotuk a state metodussal:
    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,
    35  * (nem jart meg a kupacban PRE_HEAP=-1, epp a kupacban van IN_HEAP=0,
    36  *  mar kikerult a kupacbol POST_HEAP=-2).
    36  *  mar kikerult a kupacbol POST_HEAP=-2).
    37  * Szoval ebben a modban a kupac nagyjabol hasznalhato property_map-kent, csak
    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,
    38  * meg meg tudja mondani a "legkisebb" prioritasu elemet. De csak nagyjabol,
    39  * hiszen a kupacbol kikerult elemeknek elvesz az ertekuk...
    39  * hiszen a kupacbol kikerult elemeknek elvesz az ertekuk...
    40  *
    40  *
    41  * Kozvetlen mod:
    41  * Kozvetlen mod:
    42  * push(Key, Value) metodussal belerakunk a kupacba (ha az illeto kulcs mar
    42  * push(Item, Prio) metodussal belerakunk a kupacba (ha az illeto kulcs mar
    43  * benn volt, akkor gaz).
    43  * benn volt, akkor gaz).
    44  * increase/decrease(Key k, Value new_value) metodusokkal lehet
    44  * increase/decrease(Item i, Prio new_prio) metodusokkal lehet
    45  * novelni/csokkenteni az illeto kulcshoz tartozo erteket. (Ha nem volt meg
    45  * novelni/csokkenteni az illeto elemhez tartozo prioritast. (Ha nem volt
    46  * benne a kupacban az illeto kulcs, vagy nem abba az iranyba valtoztattad
    46  * megbenne a kupacban az illeto elem, vagy nem abba az iranyba valtoztattad
    47  * az erteket, amerre mondtad -- gaz).
    47  * az erteket, amerre mondtad -- gaz).
    48  *
    48  *
    49  * Termeszetesen a fenti ket modot ertelemszeruen lehet keverni.
    49  * Termeszetesen a fenti ket modot ertelemszeruen lehet keverni.
    50  * Ja es mindig nagyon gaz, ha belepiszkalsz a map-be, amit a kupac
    50  * Ja es mindig nagyon gaz, ha belepiszkalsz a map-be, amit a kupac
    51  * hasznal. :-))
    51  * hasznal. :-))
    63 #include <utility>
    63 #include <utility>
    64 #include <functional>
    64 #include <functional>
    65 
    65 
    66 namespace hugo {
    66 namespace hugo {
    67 
    67 
    68   template <typename Key, typename Val, typename KeyIntMap,
    68   template <typename Item, typename Prio, typename ItemIntMap,
    69 	    typename Compare = std::less<Val> >
    69 	    typename Compare = std::less<Prio> >
    70   class BinHeap {
    70   class BinHeap {
    71 
    71 
    72   public:
    72   public:
    73     typedef Key	             KeyType;
    73     typedef Item                             ItemType;
    74     // FIXME: stl-ben nem ezt hivjak value_type -nak, hanem a kovetkezot...
    74     // FIXME: stl-ben nem ezt hivjak value_type -nak, hanem a kovetkezot...
    75     typedef Val              ValueType;
    75     typedef Prio                             PrioType;
    76     typedef std::pair<KeyType,ValueType>     PairType;
    76     typedef std::pair<ItemType,PrioType>     PairType;
    77     typedef KeyIntMap        KeyIntMapType;
    77     typedef ItemIntMap                       ItemIntMapType;
    78     typedef Compare          ValueCompare;
    78     typedef Compare                          PrioCompare;
    79 
    79 
    80     /**
    80     /**
    81      * Each Key element have a state associated to it. It may be "in heap",
    81      * Each Item element have a state associated to it. It may be "in heap",
    82      * "pre heap" or "post heap". The later two are indifferent from the
    82      * "pre heap" or "post heap". The later two are indifferent from the
    83      * heap's point of view, but may be useful to the user.
    83      * heap's point of view, but may be useful to the user.
    84      *
    84      *
    85      * The KeyIntMap _should_ be initialized in such way, that it maps
    85      * The ItemIntMap _should_ be initialized in such way, that it maps
    86      * PRE_HEAP (-1) to any element to be put in the heap...
    86      * PRE_HEAP (-1) to any element to be put in the heap...
    87      */
    87      */
    88     enum state_enum {
    88     enum state_enum {
    89       IN_HEAP = 0,
    89       IN_HEAP = 0,
    90       PRE_HEAP = -1,
    90       PRE_HEAP = -1,
    93 
    93 
    94   private:
    94   private:
    95     std::vector<PairType> data;
    95     std::vector<PairType> data;
    96     Compare comp;
    96     Compare comp;
    97     // FIXME: jo ez igy???
    97     // FIXME: jo ez igy???
    98     KeyIntMap &kim;
    98     ItemIntMap &iim;
    99 
    99 
   100   public:
   100   public:
   101     BinHeap(KeyIntMap &_kim) : kim(_kim) {}
   101     BinHeap(ItemIntMap &_iim) : iim(_iim) {}
   102     BinHeap(KeyIntMap &_kim, const Compare &_comp) : comp(_comp), kim(_kim) {}
   102     BinHeap(ItemIntMap &_iim, const Compare &_comp) : comp(_comp), iim(_iim) {}
   103 
   103 
   104 
   104 
   105     int size() const { return data.size(); }
   105     int size() const { return data.size(); }
   106     bool empty() const { return data.empty(); }
   106     bool empty() const { return data.empty(); }
   107 
   107 
   115     int bubble_up(int hole, PairType p);
   115     int bubble_up(int hole, PairType p);
   116     int bubble_down(int hole, PairType p, int length);
   116     int bubble_down(int hole, PairType p, int length);
   117 
   117 
   118     void move(const PairType &p, int i) {
   118     void move(const PairType &p, int i) {
   119       data[i] = p;
   119       data[i] = p;
   120       kim.put(p.first, i);
   120       iim.set(p.first, i);
   121     }
   121     }
   122 
   122 
   123     void rmidx(int h) {
   123     void rmidx(int h) {
   124       int n = data.size()-1;
   124       int n = data.size()-1;
   125       if( h>=0 && h<=n ) {
   125       if( h>=0 && h<=n ) {
   126 	kim.put(data[h].first, POST_HEAP);
   126 	iim.set(data[h].first, POST_HEAP);
   127 	if ( h<n ) {
   127 	if ( h<n ) {
   128 	  bubble_down(h, data[n], n);
   128 	  bubble_down(h, data[n], n);
   129 	}
   129 	}
   130 	data.pop_back();
   130 	data.pop_back();
   131       }
   131       }
   135     void push(const PairType &p) {
   135     void push(const PairType &p) {
   136       int n = data.size();
   136       int n = data.size();
   137       data.resize(n+1);
   137       data.resize(n+1);
   138       bubble_up(n, p);
   138       bubble_up(n, p);
   139     }
   139     }
   140     void push(const Key &k, const Val &v) { push(PairType(k,v)); }
   140     void push(const Item &i, const Prio &p) { push(PairType(i,p)); }
   141 
   141 
   142     Key top() const {
   142     Item top() const {
   143       // FIXME: test size>0 ?
   143       // FIXME: test size>0 ?
   144       return data[0].first;
   144       return data[0].first;
   145     }
   145     }
   146     Val topValue() const {
   146     Prio topPrio() const {
   147       // FIXME: test size>0 ?
   147       // FIXME: test size>0 ?
   148       return data[0].second;
   148       return data[0].second;
   149     }
   149     }
   150 
   150 
   151     void pop() {
   151     void pop() {
   152       rmidx(0);
   152       rmidx(0);
   153     }
   153     }
   154 
   154 
   155     void erase(const Key &k) {
   155     void erase(const Item &i) {
   156       rmidx(kim.get(k));
   156       rmidx(iim.get(i));
   157     }
   157     }
   158 
   158 
   159     const Val get(const Key &k) const {
   159     const Prio get(const Item &i) const {
   160       int idx = kim.get(k);
   160       int idx = iim.get(i);
   161       return data[idx].second;
   161       return data[idx].second;
   162     }
   162     }
   163     void put(const Key &k, const Val &v) {
   163     void set(const Item &i, const Prio &p) {
   164       int idx = kim.get(k);
   164       int idx = iim.get(i);
   165       if( idx < 0 ) {
   165       if( idx < 0 ) {
   166 	push(k,v);
   166 	push(i,p);
   167       }
   167       }
   168       else if( comp(v, data[idx].second) ) {
   168       else if( comp(p, data[idx].second) ) {
   169 	bubble_up(idx, PairType(k,v));
   169 	bubble_up(idx, PairType(i,p));
   170       }
   170       }
   171       else {
   171       else {
   172 	bubble_down(idx, PairType(k,v), data.size());
   172 	bubble_down(idx, PairType(i,p), data.size());
   173       }
   173       }
   174     }
   174     }
   175 
   175 
   176     void decrease(const Key &k, const Val &v) {
   176     void decrease(const Item &i, const Prio &p) {
   177       int idx = kim.get(k);
   177       int idx = iim.get(i);
   178       bubble_up(idx, PairType(k,v));
   178       bubble_up(idx, PairType(i,p));
   179     }
   179     }
   180     void increase(const Key &k, const Val &v) {
   180     void increase(const Item &i, const Prio &p) {
   181       int idx = kim.get(k);
   181       int idx = iim.get(i);
   182       bubble_down(idx, PairType(k,v), data.size());
   182       bubble_down(idx, PairType(i,p), data.size());
   183     }
   183     }
   184 
   184 
   185     state_enum state(const Key &k) const {
   185     state_enum state(const Item &i) const {
   186       int s = kim.get(k);
   186       int s = iim.get(i);
   187       if( s>=0 )
   187       if( s>=0 )
   188 	s=0;
   188 	s=0;
   189       return state_enum(s);
   189       return state_enum(s);
   190     }
   190     }
   191 
   191