heap.h
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00038 #ifndef COLLECTIONS_HEAP_H
00039 #define COLLECTIONS_HEAP_H
00040
00041 #include "fastlib/col/arraylist.h"
00042
00043
00052 template <typename TKey, typename TValue = Empty>
00053 class MinHeap {
00054
00055
00056 public:
00057 typedef TKey Key;
00058 typedef TValue Value;
00059
00060 private:
00061 struct Entry {
00062 TKey key;
00063 TValue value;
00064
00065 OBJECT_TRAVERSAL_SHALLOW(Entry) {
00066 OT_OBJ(key);
00067 OT_OBJ(value);
00068 }
00069 };
00070
00071 ArrayList<Entry> entries_;
00072
00073 OBJECT_TRAVERSAL(MinHeap) {
00074 OT_OBJ(entries_);
00075 }
00076
00077 public:
00081 void Init() {
00082 entries_.Init();
00083 }
00084
00088 bool is_empty() const {
00089 return entries_.size() == 0;
00090 }
00091
00098 void Put(Key key, Value value) {
00099 Entry entry;
00100
00101 entries_.PushBack();
00102
00103 entry.key = key;
00104 entry.value = value;
00105
00106 WalkUp_(entry, entries_.size() - 1);
00107 }
00108
00114 Value Pop() {
00115 Value t = entries_[0].value;
00116
00117 PopOnly();
00118
00119 return t;
00120 }
00121
00128 void PopOnly() {
00129 Entry entry;
00130 entries_.PopBackInit(&entry);
00131
00132 if (likely(entries_.size() != 0)) {
00133 WalkDown_(entry, 0);
00134 }
00135 }
00136
00140 Value top() const {
00141 return entries_[0].value;
00142 }
00143
00147 Key top_key() const {
00148 return entries_[0].key;
00149 }
00150
00154 void set_top(Value v) {
00155 entries_[0].value = v;
00156 }
00157
00161 index_t size() const {
00162 return entries_.size();
00163 }
00164
00165 private:
00166 static index_t ChildIndex_(index_t i) {
00167 return (i << 1) + 1;
00168 }
00169
00170 static index_t ParentIndex_(index_t i) {
00171 return (i - 1) >> 1;
00172 }
00173
00174 index_t WalkDown_(const Entry& entry, index_t i) {
00175 Key key = entry.key;
00176 Entry *entries = entries_.begin();
00177 index_t last = entries_.size() - 1;
00178
00179 for (;;) {
00180 index_t c = ChildIndex_(i);
00181
00182 if (unlikely(c > last)) {
00183 break;
00184 }
00185
00186
00187 if (likely(c != last)) {
00188 c += entries[c + 1].key < entries[c].key ? 1 : 0;
00189 }
00190
00191 if (key <= entries[c].key) {
00192 break;
00193 }
00194
00195 entries[i] = entries[c];
00196 i = c;
00197 }
00198
00199 entries[i] = entry;
00200
00201 return i;
00202 }
00203
00204 index_t WalkUp_(const Entry& entry, index_t i) {
00205 Key key = entry.key;
00206 Entry *entries = entries_.begin();
00207
00208 for (;;) {
00209 index_t p;
00210
00211 if (unlikely(i == 0)) {
00212 break;
00213 }
00214
00215 p = ParentIndex_(i);
00216
00217 if (key >= entries[p].key) {
00218 break;
00219 }
00220
00221 entries[i] = entries[p];
00222
00223 i = p;
00224 }
00225
00226 entries[i] = entry;
00227
00228 return i;
00229 }
00230 };
00231
00232 #endif