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
00017
00018 #define BINARYHEAP_CHECK 0
00019
00020 #if BINARYHEAP_CHECK
00021 #define CHECK_CONSISTY() this->CheckConsistency()
00022 #else
00023 #define CHECK_CONSISTY() ;
00024 #endif
00025
00050 template <class T>
00051 class CBinaryHeapT {
00052 private:
00053 uint items;
00054 uint capacity;
00055 T **data;
00056
00057 public:
00058 explicit CBinaryHeapT(uint max_items)
00059 : items(0)
00060 , capacity(max_items)
00061 {
00062 this->data = MallocT<T *>(max_items + 1);
00063 }
00064
00065 ~CBinaryHeapT()
00066 {
00067 this->Clear();
00068 free(this->data);
00069 this->data = NULL;
00070 }
00071
00072 protected:
00082 FORCEINLINE uint HeapifyDown(uint gap, T *item)
00083 {
00084 assert(gap != 0);
00085
00086
00087 uint child = gap * 2;
00088
00089
00090 while (child <= this->items) {
00091
00092 if (child < this->items && *this->data[child + 1] < *this->data[child]) {
00093 child++;
00094 }
00095
00096 if (!(*this->data[child] < *item)) {
00097
00098 break;
00099 }
00100
00101 this->data[gap] = this->data[child];
00102 gap = child;
00103
00104 child = gap * 2;
00105 }
00106 return gap;
00107 }
00108
00118 FORCEINLINE uint HeapifyUp(uint gap, T *item)
00119 {
00120 assert(gap != 0);
00121
00122 uint parent;
00123
00124 while (gap > 1) {
00125
00126 parent = gap / 2;
00127 if (!(*item < *this->data[parent])) {
00128
00129 break;
00130 }
00131 this->data[gap] = this->data[parent];
00132 gap = parent;
00133 }
00134 return gap;
00135 }
00136
00137 #if BINARYHEAP_CHECK
00138
00139 FORCEINLINE void CheckConsistency()
00140 {
00141 for (uint child = 2; child <= this->items; child++) {
00142 uint parent = child / 2;
00143 assert(!(*this->data[child] < *this->data[parent]));
00144 }
00145 }
00146 #endif
00147
00148 public:
00154 FORCEINLINE uint Length() const { return this->items; }
00155
00161 FORCEINLINE bool IsEmpty() const { return this->items == 0; }
00162
00168 FORCEINLINE bool IsFull() const { return this->items >= this->capacity; }
00169
00175 FORCEINLINE T *Begin()
00176 {
00177 assert(!this->IsEmpty());
00178 return this->data[1];
00179 }
00180
00188 FORCEINLINE T *End()
00189 {
00190 return this->data[1 + this->items];
00191 }
00192
00198 FORCEINLINE void Include(T *new_item)
00199 {
00200 if (this->IsFull()) {
00201 assert(this->capacity < UINT_MAX / 2);
00202
00203 this->capacity *= 2;
00204 this->data = ReallocT<T*>(this->data, this->capacity + 1);
00205 }
00206
00207
00208 uint gap = this->HeapifyUp(++items, new_item);
00209 this->data[gap] = new_item;
00210 CHECK_CONSISTY();
00211 }
00212
00219 FORCEINLINE T *Shift()
00220 {
00221 assert(!this->IsEmpty());
00222
00223 T *first = this->Begin();
00224
00225 this->items--;
00226
00227 T *last = this->End();
00228 uint gap = this->HeapifyDown(1, last);
00229
00230 if (!this->IsEmpty()) this->data[gap] = last;
00231
00232 CHECK_CONSISTY();
00233 return first;
00234 }
00235
00241 FORCEINLINE void Remove(uint index)
00242 {
00243 if (index < this->items) {
00244 assert(index != 0);
00245 this->items--;
00246
00247
00248 T *last = this->End();
00249
00250 uint gap = this->HeapifyUp(index, last);
00251 gap = this->HeapifyDown(gap, last);
00252
00253 if (!this->IsEmpty()) this->data[gap] = last;
00254 } else {
00255 assert(index == this->items);
00256 this->items--;
00257 }
00258 CHECK_CONSISTY();
00259 }
00260
00269 FORCEINLINE uint FindIndex(const T &item) const
00270 {
00271 if (this->IsEmpty()) return 0;
00272 for (T **ppI = this->data + 1, **ppLast = ppI + this->items; ppI <= ppLast; ppI++) {
00273 if (*ppI == &item) {
00274 return ppI - this->data;
00275 }
00276 }
00277 return 0;
00278 }
00279
00284 FORCEINLINE void Clear() { this->items = 0; }
00285 };
00286
00287 #endif