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
00024
00025
#include <vector>
00026
#include <utility>
00027
#include <functional>
00028
00029
namespace lemon {
00030
00033
00035
template <
typename Item,
typename Prio,
typename ItemIntMap,
00036
typename Compare = std::less<Prio> >
00037 class BinHeap {
00038
00039
public:
00040
typedef Item ItemType;
00041
00042
typedef Prio PrioType;
00043
typedef std::pair<ItemType,PrioType> PairType;
00044
typedef ItemIntMap ItemIntMapType;
00045
typedef Compare PrioCompare;
00046
00055
00056
00057 enum state_enum {
00058 IN_HEAP = 0,
00059 PRE_HEAP = -1,
00060 POST_HEAP = -2
00061 };
00062
00063
private:
00064 std::vector<PairType> data;
00065 Compare comp;
00066
00067 ItemIntMap &iim;
00068
00069
public:
00070
BinHeap(ItemIntMap &_iim) : iim(_iim) {}
00071 BinHeap(ItemIntMap &_iim,
const Compare &_comp) : comp(_comp), iim(_iim) {}
00072
00073
00074
int size()
const {
return data.size(); }
00075
bool empty()
const {
return data.empty(); }
00076
00077
private:
00078
static int parent(
int i) {
return (i-1)/2; }
00079
static int second_child(
int i) {
return 2*i+2; }
00080
bool less(
const PairType &p1,
const PairType &p2)
const {
00081
return comp(p1.second, p2.second);
00082 }
00083
00084
int bubble_up(
int hole, PairType p);
00085
int bubble_down(
int hole, PairType p,
int length);
00086
00087
void move(
const PairType &p,
int i) {
00088 data[i] = p;
00089 iim.set(p.first, i);
00090 }
00091
00092
void rmidx(
int h) {
00093
int n = data.size()-1;
00094
if( h>=0 && h<=n ) {
00095 iim.set(data[h].first, POST_HEAP);
00096
if ( h<n ) {
00097 bubble_down(h, data[n], n);
00098 }
00099 data.pop_back();
00100 }
00101 }
00102
00103
public:
00104
void push(
const PairType &p) {
00105
int n = data.size();
00106 data.resize(n+1);
00107 bubble_up(n, p);
00108 }
00109
void push(
const Item &i,
const Prio &p) { push(PairType(i,p)); }
00110
00111 Item top()
const {
00112
return data[0].first;
00113 }
00115 Prio
prio()
const {
00116
return data[0].second;
00117 }
00118
00119
void pop() {
00120 rmidx(0);
00121 }
00122
00123
void erase(
const Item &i) {
00124 rmidx(iim[i]);
00125 }
00126
00127 Prio operator[](
const Item &i)
const {
00128
int idx = iim[i];
00129
return data[idx].second;
00130 }
00131
00132
void set(
const Item &i,
const Prio &p) {
00133
int idx = iim[i];
00134
if( idx < 0 ) {
00135 push(i,p);
00136 }
00137
else if( comp(p, data[idx].second) ) {
00138 bubble_up(idx, PairType(i,p));
00139 }
00140
else {
00141 bubble_down(idx, PairType(i,p), data.size());
00142 }
00143 }
00144
00145
void decrease(
const Item &i,
const Prio &p) {
00146
int idx = iim[i];
00147 bubble_up(idx, PairType(i,p));
00148 }
00149
void increase(
const Item &i,
const Prio &p) {
00150
int idx = iim[i];
00151 bubble_down(idx, PairType(i,p), data.size());
00152 }
00153
00154
state_enum state(
const Item &i)
const {
00155
int s = iim[i];
00156
if( s>=0 )
00157 s=0;
00158
return state_enum(s);
00159 }
00160
00161 };
00162
00163
00164
template <
typename K,
typename V,
typename M,
typename C>
00165
int BinHeap<K,V,M,C>::bubble_up(
int hole, PairType p) {
00166
int par = parent(hole);
00167
while( hole>0 && less(p,data[par]) ) {
00168 move(data[par],hole);
00169 hole = par;
00170 par = parent(hole);
00171 }
00172 move(p, hole);
00173
return hole;
00174 }
00175
00176
template <
typename K,
typename V,
typename M,
typename C>
00177
int BinHeap<K,V,M,C>::bubble_down(
int hole, PairType p,
int length) {
00178
int child = second_child(hole);
00179
while(child < length) {
00180
if( less(data[child-1], data[child]) ) {
00181 --child;
00182 }
00183
if( !less(data[child], p) )
00184
goto ok;
00185 move(data[child], hole);
00186 hole = child;
00187 child = second_child(hole);
00188 }
00189 child--;
00190
if( child<length && less(data[child], p) ) {
00191 move(data[child], hole);
00192 hole=child;
00193 }
00194 ok:
00195 move(p, hole);
00196
return hole;
00197 }
00198
00200
00201 }
00202
00203
#endif // LEMON_BIN_HEAP_H