00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef LEMON_BIN_HEAP_H
00018 #define LEMON_BIN_HEAP_H
00019
00023
00024 #include <vector>
00025 #include <utility>
00026 #include <functional>
00027
00028 namespace lemon {
00029
00032
00034
00050 template <typename Item, typename Prio, typename ItemIntMap,
00051 typename Compare = std::less<Prio> >
00052 class BinHeap {
00053
00054 public:
00055 typedef Item ItemType;
00056
00057 typedef Prio PrioType;
00058 typedef std::pair<ItemType,PrioType> PairType;
00059 typedef ItemIntMap ItemIntMapType;
00060 typedef Compare PrioCompare;
00061
00070 enum state_enum {
00071 IN_HEAP = 0,
00072 PRE_HEAP = -1,
00073 POST_HEAP = -2
00074 };
00075
00076 private:
00077 std::vector<PairType> data;
00078 Compare comp;
00079 ItemIntMap &iim;
00080
00081 public:
00088 explicit BinHeap(ItemIntMap &_iim) : iim(_iim) {}
00089
00098 BinHeap(ItemIntMap &_iim, const Compare &_comp)
00099 : iim(_iim), comp(_comp) {}
00100
00101
00105 int size() const { return data.size(); }
00106
00110 bool empty() const { return data.empty(); }
00111
00112 private:
00113 static int parent(int i) { return (i-1)/2; }
00114 static int second_child(int i) { return 2*i+2; }
00115 bool less(const PairType &p1, const PairType &p2) const {
00116 return comp(p1.second, p2.second);
00117 }
00118
00119 int bubble_up(int hole, PairType p);
00120 int bubble_down(int hole, PairType p, int length);
00121
00122 void move(const PairType &p, int i) {
00123 data[i] = p;
00124 iim.set(p.first, i);
00125 }
00126
00127 void rmidx(int h) {
00128 int n = data.size()-1;
00129 if( h>=0 && h<=n ) {
00130 iim.set(data[h].first, POST_HEAP);
00131 if ( h<n ) {
00132 bubble_down(h, data[n], n);
00133 }
00134 data.pop_back();
00135 }
00136 }
00137
00138 public:
00143 void push(const PairType &p) {
00144 int n = data.size();
00145 data.resize(n+1);
00146 bubble_up(n, p);
00147 }
00148
00154 void push(const Item &i, const Prio &p) { push(PairType(i,p)); }
00155
00161 Item top() const {
00162 return data[0].first;
00163 }
00164
00169 Prio prio() const {
00170 return data[0].second;
00171 }
00172
00178 void pop() {
00179 rmidx(0);
00180 }
00181
00187 void erase(const Item &i) {
00188 rmidx(iim[i]);
00189 }
00190
00191
00197 Prio operator[](const Item &i) const {
00198 int idx = iim[i];
00199 return data[idx].second;
00200 }
00201
00209 void set(const Item &i, const Prio &p) {
00210 int idx = iim[i];
00211 if( idx < 0 ) {
00212 push(i,p);
00213 }
00214 else if( comp(p, data[idx].second) ) {
00215 bubble_up(idx, PairType(i,p));
00216 }
00217 else {
00218 bubble_down(idx, PairType(i,p), data.size());
00219 }
00220 }
00221
00223
00229 void decrease(const Item &i, const Prio &p) {
00230 int idx = iim[i];
00231 bubble_up(idx, PairType(i,p));
00232 }
00233
00241 void increase(const Item &i, const Prio &p) {
00242 int idx = iim[i];
00243 bubble_down(idx, PairType(i,p), data.size());
00244 }
00245
00254 state_enum state(const Item &i) const {
00255 int s = iim[i];
00256 if( s>=0 )
00257 s=0;
00258 return state_enum(s);
00259 }
00260
00261 };
00262
00263
00264 template <typename K, typename V, typename M, typename C>
00265 int BinHeap<K,V,M,C>::bubble_up(int hole, PairType p) {
00266 int par = parent(hole);
00267 while( hole>0 && less(p,data[par]) ) {
00268 move(data[par],hole);
00269 hole = par;
00270 par = parent(hole);
00271 }
00272 move(p, hole);
00273 return hole;
00274 }
00275
00276 template <typename K, typename V, typename M, typename C>
00277 int BinHeap<K,V,M,C>::bubble_down(int hole, PairType p, int length) {
00278 int child = second_child(hole);
00279 while(child < length) {
00280 if( less(data[child-1], data[child]) ) {
00281 --child;
00282 }
00283 if( !less(data[child], p) )
00284 goto ok;
00285 move(data[child], hole);
00286 hole = child;
00287 child = second_child(hole);
00288 }
00289 child--;
00290 if( child<length && less(data[child], p) ) {
00291 move(data[child], hole);
00292 hole=child;
00293 }
00294 ok:
00295 move(p, hole);
00296 return hole;
00297 }
00298
00300
00301 }
00302
00303 #endif // LEMON_BIN_HEAP_H