• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

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__,__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         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

Generated on Thu Sep 30 2010 01:27:22 for RakNet by  doxygen 1.7.1