![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
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; // I'm assuming key is a native numerical type - float or int 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 //Clear(true, _FILE_AND_LINE_); 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 // If the weight of what we are inserting is greater than / less than in order of the heap of every sibling and sibling of parent, then can optimize next push 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 // Every child is less than its parent 00088 if (weight>heap[parentIndex].weight) 00089 { 00090 // Can't optimize 00091 Push(weight,data,file,line); 00092 return; 00093 } 00094 } 00095 else 00096 { 00097 // Every child is greater than than its parent 00098 if (weight<heap[parentIndex].weight) 00099 { 00100 // Can't optimize 00101 Push(weight,data,file,line); 00102 return; 00103 } 00104 } 00105 } 00106 } 00107 00108 // Parent's subsequent siblings and this row's siblings all are less than / greater than inserted element. Can insert all further elements straight to the end 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 // While we have children, swap out with the larger of the two children. 00157 00158 // This line will assert on an empty heap 00159 data_type returnValue=heap[startingIndex].data; 00160 00161 // Move the last element to the head, and re-heapify 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 // Done 00180 return returnValue; 00181 } 00182 if (rightChild >= heap.Size()) 00183 { 00184 // Only left node. 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 // Swap with the bigger/smaller of the two children and continue 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 inline 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 inline 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 inline 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 inline 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 inline 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 inline 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
Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.