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