00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #pragma once
00015
00019 #include "Array.h"
00020 #include "SortCmp.h"
00021
00022 namespace kNet
00023 {
00024
00028 template<typename T>
00029 class EmptyLookupNotify
00030 {
00031 public:
00035 void IndexUpdated(const T &element, int newIndex) {}
00036 };
00037
00051 template<typename T, typename PriorityCmp = sort::TriCmpObj<T>,
00052 typename EqualCmp = sort::TriCmpObj<T>,
00053 typename LookupNotify = EmptyLookupNotify<T>,
00054 typename AllocT = StdCAlloc>
00055 class MaxHeap
00056 {
00057 public:
00059 Array<T, AllocT> data;
00060 PriorityCmp cmp;
00061 EqualCmp equal;
00062
00063
00064
00065 LookupNotify notify;
00066
00068 static inline int ParentIndex(int i) { return (i+1)/2-1; }
00070 static inline int LeftChildIndex(int i) { return i*2+1; }
00072 static inline int RightChildIndex(int i) { return i*2+2; }
00073
00078 bool MaxHeapify(int i);
00079
00082 void KeyIncreased(int i);
00083
00086 void Insert(const T &value);
00087
00089 void PopFront();
00090
00092 void PopBack();
00093
00095 const T &Front() const { return data[0]; }
00096
00098 const T &Back() const { return data[LowestPriorityIndex()]; }
00099
00101 int LowestPriorityIndex() const;
00102
00104 int Size() const { return data.size(); }
00105
00107 void Reserve(int size) { data.reserve(size); }
00108
00109 void Clear() { data.clear(); }
00113 int Search(const T &value) { return Search(value, 0); }
00114
00115 private:
00117 int Search(const T &value, int index);
00118
00119 };
00120
00121 template<typename T, typename PriorityCmp, typename EqualCmp, typename LookupNotify, typename AllocT>
00122 bool MaxHeap<T, PriorityCmp, EqualCmp, LookupNotify, AllocT>::MaxHeapify(int i)
00123 {
00124 assert(i >= 0);
00125 if (i >= (int)data.size())
00126 return false;
00127
00128 bool changes = false;
00129
00130 for(;;)
00131 {
00132
00133 const int l = LeftChildIndex(i);
00134 const int r = RightChildIndex(i);
00135
00136
00137 int largest = i;
00138 if (l < (int)data.size() && cmp(data[l], data[i]) > 0)
00139 largest = l;
00140 if (r < (int)data.size() && cmp(data[r], data[largest]) > 0)
00141 largest = r;
00142
00143
00144 if (largest != i)
00145 {
00146 std::swap(data[largest], data[i]);
00147 notify.IndexUpdated(data[largest], largest);
00148 notify.IndexUpdated(data[i], i);
00149 i = largest;
00150 changes = true;
00151 }
00152 else
00153 return changes;
00154 }
00155 }
00156
00157 template<typename T, typename PriorityCmp, typename EqualCmp, typename LookupNotify, typename AllocT>
00158 void MaxHeap<T, PriorityCmp, EqualCmp, LookupNotify, AllocT>::Insert(const T &value)
00159 {
00160
00161 data.push_back(value);
00162 notify.IndexUpdated(data.back(), data.size()-1);
00163
00164 KeyIncreased(data.size()-1);
00165 }
00166
00167 template<typename T, typename PriorityCmp, typename EqualCmp, typename LookupNotify, typename AllocT>
00168 void MaxHeap<T, PriorityCmp, EqualCmp, LookupNotify, AllocT>::KeyIncreased(int i)
00169 {
00170
00171 bool changesMade = true;
00172 while(changesMade && i != 0)
00173 {
00174 i = ParentIndex(i);
00175 changesMade = MaxHeapify(i);
00176 }
00177 }
00178
00179 template<typename T, typename PriorityCmp, typename EqualCmp, typename LookupNotify, typename AllocT>
00180 void MaxHeap<T, PriorityCmp, EqualCmp, LookupNotify, AllocT>::PopFront()
00181 {
00182 std::swap(data[0], data[data.size()-1]);
00183 data.pop_back();
00184 MaxHeapify(0);
00185 }
00186
00187 template<typename T, typename PriorityCmp, typename EqualCmp, typename LookupNotify, typename AllocT>
00188 void MaxHeap<T, PriorityCmp, EqualCmp, LookupNotify, AllocT>::PopBack()
00189 {
00190 int i = LowestPriorityIndex();
00191 std::swap(data[i], data[data.size()-1]);
00192 data.pop_back();
00193 KeyIncreased(i);
00194 }
00195
00196 template<typename T, typename PriorityCmp, typename EqualCmp, typename LookupNotify, typename AllocT>
00197 int MaxHeap<T, PriorityCmp, EqualCmp, LookupNotify, AllocT>::LowestPriorityIndex() const
00198 {
00199 int i = data.size();
00200 int lowestIndex = data.size()-1;
00201 do
00202 {
00203 --i;
00204 if (cmp(data[i], data[lowestIndex]) < 0)
00205 lowestIndex = i;
00206 } while((i & (i-1)) != 0);
00207
00208 return lowestIndex;
00209 }
00210
00211 template<typename T, typename PriorityCmp, typename EqualCmp, typename LookupNotify, typename AllocT>
00212 int MaxHeap<T, PriorityCmp, EqualCmp, LookupNotify, AllocT>::Search(const T &value, int index)
00213 {
00214 assert(index >= 0);
00215 if (index >= (int)data.size())
00216 return -1;
00217
00218 int order = cmp(value, data[index]);
00219 if (order == 0 && equal(value, data[index]) == 0)
00220 return index;
00221 if (order > 0)
00222 return -1;
00223
00224
00225 int child = LeftChildIndex(index);
00226 assert(child >= 0);
00227 if (child >= (int)data.size())
00228 return -1;
00229
00230 int result = Search(value, child);
00231 if (result != -1)
00232 return result;
00233
00234 child = RightChildIndex(index);
00235 assert(child >= 0);
00236 if (child < (int)data.size())
00237 return Search(value, child);
00238 else
00239 return -1;
00240 }
00241
00242 }
00243