Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #ifndef BINARYHEAP_HPP
00013 #define BINARYHEAP_HPP
00014
00015 #include "../core/alloc_func.hpp"
00016
00018 #define BINARYHEAP_CHECK 0
00019
00020 #if BINARYHEAP_CHECK
00021
00022 #define CHECK_CONSISTY() this->CheckConsistency()
00023 #else
00024
00025 #define CHECK_CONSISTY() ;
00026 #endif
00027
00052 template <class T>
00053 class CBinaryHeapT {
00054 private:
00055 uint items;
00056 uint capacity;
00057 T **data;
00058
00059 public:
00064 explicit CBinaryHeapT(uint max_items)
00065 : items(0)
00066 , capacity(max_items)
00067 {
00068 this->data = MallocT<T *>(max_items + 1);
00069 }
00070
00071 ~CBinaryHeapT()
00072 {
00073 this->Clear();
00074 free(this->data);
00075 this->data = NULL;
00076 }
00077
00078 protected:
00088 FORCEINLINE uint HeapifyDown(uint gap, T *item)
00089 {
00090 assert(gap != 0);
00091
00092
00093 uint child = gap * 2;
00094
00095
00096 while (child <= this->items) {
00097
00098 if (child < this->items && *this->data[child + 1] < *this->data[child]) {
00099 child++;
00100 }
00101
00102 if (!(*this->data[child] < *item)) {
00103
00104 break;
00105 }
00106
00107 this->data[gap] = this->data[child];
00108 gap = child;
00109
00110 child = gap * 2;
00111 }
00112 return gap;
00113 }
00114
00124 FORCEINLINE uint HeapifyUp(uint gap, T *item)
00125 {
00126 assert(gap != 0);
00127
00128 uint parent;
00129
00130 while (gap > 1) {
00131
00132 parent = gap / 2;
00133 if (!(*item < *this->data[parent])) {
00134
00135 break;
00136 }
00137 this->data[gap] = this->data[parent];
00138 gap = parent;
00139 }
00140 return gap;
00141 }
00142
00143 #if BINARYHEAP_CHECK
00144
00145 FORCEINLINE void CheckConsistency()
00146 {
00147 for (uint child = 2; child <= this->items; child++) {
00148 uint parent = child / 2;
00149 assert(!(*this->data[child] < *this->data[parent]));
00150 }
00151 }
00152 #endif
00153
00154 public:
00160 FORCEINLINE uint Length() const { return this->items; }
00161
00167 FORCEINLINE bool IsEmpty() const { return this->items == 0; }
00168
00174 FORCEINLINE bool IsFull() const { return this->items >= this->capacity; }
00175
00181 FORCEINLINE T *Begin()
00182 {
00183 assert(!this->IsEmpty());
00184 return this->data[1];
00185 }
00186
00194 FORCEINLINE T *End()
00195 {
00196 return this->data[1 + this->items];
00197 }
00198
00204 FORCEINLINE void Include(T *new_item)
00205 {
00206 if (this->IsFull()) {
00207 assert(this->capacity < UINT_MAX / 2);
00208
00209 this->capacity *= 2;
00210 this->data = ReallocT<T*>(this->data, this->capacity + 1);
00211 }
00212
00213
00214 uint gap = this->HeapifyUp(++items, new_item);
00215 this->data[gap] = new_item;
00216 CHECK_CONSISTY();
00217 }
00218
00225 FORCEINLINE T *Shift()
00226 {
00227 assert(!this->IsEmpty());
00228
00229 T *first = this->Begin();
00230
00231 this->items--;
00232
00233 T *last = this->End();
00234 uint gap = this->HeapifyDown(1, last);
00235
00236 if (!this->IsEmpty()) this->data[gap] = last;
00237
00238 CHECK_CONSISTY();
00239 return first;
00240 }
00241
00247 FORCEINLINE void Remove(uint index)
00248 {
00249 if (index < this->items) {
00250 assert(index != 0);
00251 this->items--;
00252
00253
00254 T *last = this->End();
00255
00256 uint gap = this->HeapifyUp(index, last);
00257 gap = this->HeapifyDown(gap, last);
00258
00259 if (!this->IsEmpty()) this->data[gap] = last;
00260 } else {
00261 assert(index == this->items);
00262 this->items--;
00263 }
00264 CHECK_CONSISTY();
00265 }
00266
00275 FORCEINLINE uint FindIndex(const T &item) const
00276 {
00277 if (this->IsEmpty()) return 0;
00278 for (T **ppI = this->data + 1, **ppLast = ppI + this->items; ppI <= ppLast; ppI++) {
00279 if (*ppI == &item) {
00280 return ppI - this->data;
00281 }
00282 }
00283 return 0;
00284 }
00285
00290 FORCEINLINE void Clear() { this->items = 0; }
00291 };
00292
00293 #endif