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, |
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 |