jacint@170: /* FIXME: Copyright ... jacint@170: * jacint@170: * This implementation is heavily based on STL's heap functions and jacint@170: * the similar class by Alpar Juttner in IKTA... jacint@170: */ jacint@170: jacint@170: /****** jacint@170: * jacint@170: * BinHeap jacint@170: * jacint@170: * Ez az osztaly kulcs-ertek parok tarolasara alkalmas binaris kupacot jacint@170: * valosit meg. jacint@170: * A kupacban legfolul mindig az a par talalhato, amiben az _ertek_ a jacint@170: * legkisebb. (Gondolj a Dijkstra pont-tavolsag kupacara; igazabol ahhoz jacint@170: * lett keszitve...) jacint@170: * jacint@170: * Megjegyzes: egy kicsit gyanus nekem, hogy a kupacos temakorben nem jacint@170: * azt hivjak kulcsnak, amit most en annak nevezek. :) En olyan jacint@170: * property_map -os ertelemben hasznalom. jacint@170: * jacint@170: * A hasznalatahoz szukseg van egy irhato/olvashato property_map-re, ami jacint@170: * a kulcsokhoz egy int-et tud tarolni (ezzel tudom megkeresni az illeto jacint@170: * elemet a kupacban a csokkentes es hasonlo muveletekhez). jacint@170: * A map-re csak referenciat tarol, ugy hogy a kupac elete folyan a map-nek jacint@170: * is elnie kell. (???) jacint@170: * jacint@170: * Ketfele modon hasznalhato: jacint@170: * Lusta mod: jacint@170: * put(Key, Value) metodussal pakolunk a kupacba, jacint@170: * aztan o majd eldonti, hogy ez az elem mar benne van-e es ha igen, akkor jacint@170: * csokkentettunk-e rajta, vagy noveltunk. jacint@170: * Ehhez nagyon fontos, hogy az atadott property map inicializalva legyen jacint@170: * minden szobajovo kulcs ertekre, -1 -es ertekkel! jacint@170: * Es ilyen esetben a kulcsokrol lekerdezheto az allapotuk a state metodussal: jacint@170: * (nem jart meg a kupacban PRE_HEAP=-1, epp a kupacban van IN_HEAP=0, jacint@170: * mar kikerult a kupacbol POST_HEAP=-2). jacint@170: * Szoval ebben a modban a kupac nagyjabol hasznalhato property_map-kent, csak jacint@170: * meg meg tudja mondani a "legkisebb" erteku elemet. De csak nagyjabol, jacint@170: * hiszen a kupacbol kikerult elemeknek elvesz az ertekuk... jacint@170: * jacint@170: * Kozvetlen mod: jacint@170: * push(Key, Value) metodussal belerakunk a kupacba (ha az illeto kulcs mar jacint@170: * benn volt, akkor gaz). jacint@170: * increase/decrease(Key k, Value new_value) metodusokkal lehet jacint@170: * novelni/csokkenteni az illeto kulcshoz tartozo erteket. (Ha nem volt meg jacint@170: * benne a kupacban az illeto kulcs, vagy nem abba az iranyba valtoztattad jacint@170: * az erteket, amerre mondtad -- gaz). jacint@170: * jacint@170: * Termeszetesen a fenti ket modot ertelemszeruen lehet keverni. jacint@170: * Ja es mindig nagyon gaz, ha belepiszkalsz a map-be, amit a kupac jacint@170: * hasznal. :-)) jacint@170: * jacint@170: * jacint@170: * Bocs, most faradt vagyok, majd egyszer leforditom. (Misi) jacint@170: * jacint@170: */ jacint@170: jacint@170: jacint@170: #ifndef BIN_HEAP_HH jacint@170: #define BIN_HEAP_HH jacint@170: jacint@170: #include jacint@170: #include jacint@170: #include jacint@170: jacint@170: namespace hugo { jacint@170: jacint@170: template > jacint@170: class BinHeap { jacint@170: jacint@170: public: jacint@170: typedef Key KeyType; jacint@170: // FIXME: stl-ben nem ezt hivjak value_type -nak, hanem a kovetkezot... jacint@170: typedef Val ValueType; jacint@170: typedef std::pair PairType; jacint@170: typedef KeyIntMap KeyIntMapType; jacint@170: typedef Compare ValueCompare; jacint@170: jacint@170: /** jacint@170: * Each Key element have a state associated to it. It may be "in heap", jacint@170: * "pre heap" or "post heap". The later two are indifferent from the jacint@170: * heap's point of view, but may be useful to the user. jacint@170: * jacint@170: * The KeyIntMap _should_ be initialized in such way, that it maps jacint@170: * PRE_HEAP (-1) to any element to be put in the heap... jacint@170: */ jacint@170: enum state_enum { jacint@170: IN_HEAP = 0, jacint@170: PRE_HEAP = -1, jacint@170: POST_HEAP = -2 jacint@170: }; jacint@170: jacint@170: private: jacint@170: std::vector data; jacint@170: Compare comp; jacint@170: // FIXME: jo ez igy??? jacint@170: KeyIntMap &kim; jacint@170: jacint@170: public: jacint@170: BinHeap(KeyIntMap &_kim) : kim(_kim) {} jacint@170: BinHeap(KeyIntMap &_kim, const Compare &_comp) : comp(_comp), kim(_kim) {} jacint@170: jacint@170: jacint@170: int size() const { return data.size(); } jacint@170: bool empty() const { return data.empty(); } jacint@170: jacint@170: private: jacint@170: static int parent(int i) { return (i-1)/2; } jacint@170: static int second_child(int i) { return 2*i+2; } jacint@170: bool less(const PairType &p1, const PairType &p2) { jacint@170: return comp(p1.second, p2.second); jacint@170: } jacint@170: jacint@170: int bubble_up(int hole, PairType p); jacint@170: int bubble_down(int hole, PairType p, int length); jacint@170: jacint@170: void move(const PairType &p, int i) { jacint@170: data[i] = p; jacint@170: kim.set(p.first, i); jacint@170: } jacint@170: jacint@170: void rmidx(int h) { jacint@170: int n = data.size()-1; jacint@170: if( h>=0 && h<=n ) { jacint@170: kim.set(data[h].first, POST_HEAP); jacint@170: if ( h0 ? jacint@170: return data[0].first; jacint@170: } jacint@170: Val topValue() const { jacint@170: // FIXME: test size>0 ? jacint@170: return data[0].second; jacint@170: } jacint@170: jacint@170: void pop() { jacint@170: rmidx(0); jacint@170: } jacint@170: jacint@170: void erase(const Key &k) { jacint@170: rmidx(kim.get(k)); jacint@170: } jacint@170: jacint@170: const Val get(const Key &k) const { jacint@170: int idx = kim.get(k); jacint@170: return data[idx].second; jacint@170: } jacint@170: void put(const Key &k, const Val &v) { jacint@170: int idx = kim.get(k); jacint@170: if( idx < 0 ) { jacint@170: push(k,v); jacint@170: } jacint@170: else if( comp(v, data[idx].second) ) { jacint@170: bubble_up(idx, PairType(k,v)); jacint@170: } jacint@170: else { jacint@170: bubble_down(idx, PairType(k,v), data.size()); jacint@170: } jacint@170: } jacint@170: jacint@170: void decrease(const Key &k, const Val &v) { jacint@170: int idx = kim.get(k); jacint@170: bubble_up(idx, PairType(k,v)); jacint@170: } jacint@170: void increase(const Key &k, const Val &v) { jacint@170: int idx = kim.get(k); jacint@170: bubble_down(idx, PairType(k,v), data.size()); jacint@170: } jacint@170: jacint@170: state_enum state(const Key &k) const { jacint@170: int s = kim.get(k); jacint@170: if( s>=0 ) jacint@170: s=0; jacint@170: return state_enum(s); jacint@170: } jacint@170: jacint@170: }; // class BinHeap jacint@170: jacint@170: jacint@170: template jacint@170: int BinHeap::bubble_up(int hole, PairType p) { jacint@170: int par = parent(hole); jacint@170: while( hole>0 && less(p,data[par]) ) { jacint@170: move(data[par],hole); jacint@170: hole = par; jacint@170: par = parent(hole); jacint@170: } jacint@170: move(p, hole); jacint@170: return hole; jacint@170: } jacint@170: jacint@170: template jacint@170: int BinHeap::bubble_down(int hole, PairType p, int length) { jacint@170: int child = second_child(hole); jacint@170: while(child < length) { jacint@170: if( less(data[child-1], data[child]) ) { jacint@170: --child; jacint@170: } jacint@170: if( !less(data[child], p) ) jacint@170: goto ok; jacint@170: move(data[child], hole); jacint@170: hole = child; jacint@170: child = second_child(hole); jacint@170: } jacint@170: child--; jacint@170: if( child