Shadowrun: Awakened 29 September 2011 - Build 871
DS_Heap.h
Go to the documentation of this file.
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.

GNU Lesser General Public License 3 Sourceforge.net