00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef __RAKNET_HEAP_H
00011 #define __RAKNET_HEAP_H
00012
00013 #include "RakMemoryOverride.h"
00014 #include "DS_List.h"
00015 #include "Export.h"
00016 #include "RakAssert.h"
00017
00018 #ifdef _MSC_VER
00019 #pragma warning( push )
00020 #endif
00021
00024 namespace DataStructures
00025 {
00026 template <class weight_type, class data_type, bool isMaxHeap>
00027 class RAK_DLL_EXPORT Heap
00028 {
00029 public:
00030 struct HeapNode
00031 {
00032 HeapNode() {}
00033 HeapNode(const weight_type &w, const data_type &d) : weight(w), data(d) {}
00034 weight_type weight;
00035 data_type data;
00036 };
00037
00038 Heap();
00039 ~Heap();
00040 void Push(const weight_type &weight, const data_type &data, const char *file, unsigned int line);
00042 void StartSeries(void) {optimizeNextSeriesPush=false;}
00044 void PushSeries(const weight_type &weight, const data_type &data, const char *file, unsigned int line);
00045 data_type Pop(const unsigned startingIndex);
00046 data_type Peek(const unsigned startingIndex=0) const;
00047 weight_type PeekWeight(const unsigned startingIndex=0) const;
00048 void Clear(bool doNotDeallocateSmallBlocks, const char *file, unsigned int line);
00049 data_type& operator[] ( const unsigned int position ) const;
00050 unsigned Size(void) const;
00051
00052 protected:
00053 unsigned LeftChild(const unsigned i) const;
00054 unsigned RightChild(const unsigned i) const;
00055 unsigned Parent(const unsigned i) const;
00056 void Swap(const unsigned i, const unsigned j);
00057 DataStructures::List<HeapNode> heap;
00058 bool optimizeNextSeriesPush;
00059 };
00060
00061 template <class weight_type, class data_type, bool isMaxHeap>
00062 Heap<weight_type, data_type, isMaxHeap>::Heap()
00063 {
00064 optimizeNextSeriesPush=false;
00065 }
00066
00067 template <class weight_type, class data_type, bool isMaxHeap>
00068 Heap<weight_type, data_type, isMaxHeap>::~Heap()
00069 {
00070
00071 }
00072
00073 template <class weight_type, class data_type, bool isMaxHeap>
00074 void Heap<weight_type, data_type, isMaxHeap>::PushSeries(const weight_type &weight, const data_type &data, const char *file, unsigned int line)
00075 {
00076 if (optimizeNextSeriesPush==false)
00077 {
00078
00079 unsigned currentIndex = heap.Size();
00080 unsigned parentIndex;
00081 if (currentIndex>0)
00082 {
00083 for (parentIndex = Parent(currentIndex); parentIndex < currentIndex; parentIndex++)
00084 {
00085 if (isMaxHeap)
00086 {
00087
00088 if (weight>heap[parentIndex].weight)
00089 {
00090
00091 Push(weight,data,file,line);
00092 return;
00093 }
00094 }
00095 else
00096 {
00097
00098 if (weight<heap[parentIndex].weight)
00099 {
00100
00101 Push(weight,data,file,line);
00102 return;
00103 }
00104 }
00105 }
00106 }
00107
00108
00109 heap.Insert(HeapNode(weight, data), file, line);
00110 optimizeNextSeriesPush=true;
00111 }
00112 else
00113 {
00114 heap.Insert(HeapNode(weight, data), file, line);
00115 }
00116 }
00117
00118 template <class weight_type, class data_type, bool isMaxHeap>
00119 void Heap<weight_type, data_type, isMaxHeap>::Push(const weight_type &weight, const data_type &data, const char *file, unsigned int line)
00120 {
00121 unsigned currentIndex = heap.Size();
00122 unsigned parentIndex;
00123 heap.Insert(HeapNode(weight, data), file, line);
00124 while (currentIndex!=0)
00125 {
00126 parentIndex = Parent(currentIndex);
00127 #ifdef _MSC_VER
00128 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
00129 #endif
00130 if (isMaxHeap)
00131 {
00132 if (heap[parentIndex].weight < weight)
00133 {
00134 Swap(currentIndex, parentIndex);
00135 currentIndex=parentIndex;
00136 }
00137 else
00138 break;
00139 }
00140 else
00141 {
00142 if (heap[parentIndex].weight > weight)
00143 {
00144 Swap(currentIndex, parentIndex);
00145 currentIndex=parentIndex;
00146 }
00147 else
00148 break;
00149 }
00150 }
00151 }
00152
00153 template <class weight_type, class data_type, bool isMaxHeap>
00154 data_type Heap<weight_type, data_type, isMaxHeap>::Pop(const unsigned startingIndex)
00155 {
00156
00157
00158
00159 data_type returnValue=heap[startingIndex].data;
00160
00161
00162 heap[startingIndex]=heap[heap.Size()-1];
00163
00164 unsigned currentIndex,leftChild,rightChild;
00165 weight_type currentWeight;
00166 currentIndex=startingIndex;
00167 currentWeight=heap[startingIndex].weight;
00168 heap.RemoveFromEnd();
00169
00170 #ifdef _MSC_VER
00171 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
00172 #endif
00173 while (1)
00174 {
00175 leftChild=LeftChild(currentIndex);
00176 rightChild=RightChild(currentIndex);
00177 if (leftChild >= heap.Size())
00178 {
00179
00180 return returnValue;
00181 }
00182 if (rightChild >= heap.Size())
00183 {
00184
00185 if ((isMaxHeap==true && currentWeight < heap[leftChild].weight) ||
00186 (isMaxHeap==false && currentWeight > heap[leftChild].weight))
00187 Swap(leftChild, currentIndex);
00188
00189 return returnValue;
00190 }
00191 else
00192 {
00193
00194 if (isMaxHeap)
00195 {
00196 if (heap[leftChild].weight <= currentWeight && heap[rightChild].weight <= currentWeight)
00197 return returnValue;
00198
00199 if (heap[leftChild].weight > heap[rightChild].weight)
00200 {
00201 Swap(leftChild, currentIndex);
00202 currentIndex=leftChild;
00203 }
00204 else
00205 {
00206 Swap(rightChild, currentIndex);
00207 currentIndex=rightChild;
00208 }
00209 }
00210 else
00211 {
00212 if (heap[leftChild].weight >= currentWeight && heap[rightChild].weight >= currentWeight)
00213 return returnValue;
00214
00215 if (heap[leftChild].weight < heap[rightChild].weight)
00216 {
00217 Swap(leftChild, currentIndex);
00218 currentIndex=leftChild;
00219 }
00220 else
00221 {
00222 Swap(rightChild, currentIndex);
00223 currentIndex=rightChild;
00224 }
00225 }
00226 }
00227 }
00228 }
00229
00230 template <class weight_type, class data_type, bool isMaxHeap>
00231 data_type Heap<weight_type, data_type, isMaxHeap>::Peek(const unsigned startingIndex) const
00232 {
00233 return heap[startingIndex].data;
00234 }
00235
00236 template <class weight_type, class data_type, bool isMaxHeap>
00237 weight_type Heap<weight_type, data_type, isMaxHeap>::PeekWeight(const unsigned startingIndex) const
00238 {
00239 return heap[startingIndex].weight;
00240 }
00241
00242 template <class weight_type, class data_type, bool isMaxHeap>
00243 void Heap<weight_type, data_type, isMaxHeap>::Clear(bool doNotDeallocateSmallBlocks, const char *file, unsigned int line)
00244 {
00245 heap.Clear(doNotDeallocateSmallBlocks, file, line);
00246 }
00247
00248 template <class weight_type, class data_type, bool isMaxHeap>
00249 data_type& Heap<weight_type, data_type, isMaxHeap>::operator[] ( const unsigned int position ) const
00250 {
00251 return heap[position].data;
00252 }
00253 template <class weight_type, class data_type, bool isMaxHeap>
00254 unsigned Heap<weight_type, data_type, isMaxHeap>::Size(void) const
00255 {
00256 return heap.Size();
00257 }
00258
00259 template <class weight_type, class data_type, bool isMaxHeap>
00260 unsigned Heap<weight_type, data_type, isMaxHeap>::LeftChild(const unsigned i) const
00261 {
00262 return i*2+1;
00263 }
00264
00265 template <class weight_type, class data_type, bool isMaxHeap>
00266 unsigned Heap<weight_type, data_type, isMaxHeap>::RightChild(const unsigned i) const
00267 {
00268 return i*2+2;
00269 }
00270
00271 template <class weight_type, class data_type, bool isMaxHeap>
00272 unsigned Heap<weight_type, data_type, isMaxHeap>::Parent(const unsigned i) const
00273 {
00274 #ifdef _DEBUG
00275 RakAssert(i!=0);
00276 #endif
00277 return (i-1)/2;
00278 }
00279
00280 template <class weight_type, class data_type, bool isMaxHeap>
00281 void Heap<weight_type, data_type, isMaxHeap>::Swap(const unsigned i, const unsigned j)
00282 {
00283 HeapNode temp;
00284 temp=heap[i];
00285 heap[i]=heap[j];
00286 heap[j]=temp;
00287 }
00288 }
00289
00290 #ifdef _MSC_VER
00291 #pragma warning( pop )
00292 #endif
00293
00294 #endif