SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DS_Heap.h
Go to the documentation of this file.
1 /*
2 * Original work: Copyright (c) 2014, Oculus VR, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * RakNet License.txt file in the licenses directory of this source tree. An additional grant
7 * of patent rights can be found in the RakNet Patents.txt file in the same directory.
8 *
9 *
10 * Modified work: Copyright (c) 2016-2017, SLikeSoft UG (haftungsbeschränkt)
11 *
12 * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
13 * license found in the license.txt file in the root directory of this source tree.
14 */
15
20
21
22
23 #ifndef __RAKNET_HEAP_H
24 #define __RAKNET_HEAP_H
25
26 #include "memoryoverride.h"
27 #include "DS_List.h"
28 #include "Export.h"
29 #include "assert.h"
30
31 #ifdef _MSC_VER
32 #pragma warning( push )
33 #endif
34
37 namespace DataStructures
38 {
39 template <class weight_type, class data_type, bool isMaxHeap>
40 class RAK_DLL_EXPORT Heap
41 {
42 public:
43 struct HeapNode
44 {
45 HeapNode() {}
46 HeapNode(const weight_type &w, const data_type &d) : weight(w), data(d) {}
47 weight_type weight; // I'm assuming key is a native numerical type - float or int
48 data_type data;
49 };
50
51 Heap();
52 ~Heap();
53 void Push(const weight_type &weight, const data_type &data, const char *file, unsigned int line);
55 void StartSeries(void) {optimizeNextSeriesPush=false;}
57 void PushSeries(const weight_type &weight, const data_type &data, const char *file, unsigned int line);
58 data_type Pop(const unsigned startingIndex);
59 data_type Peek(const unsigned startingIndex=0) const;
60 weight_type PeekWeight(const unsigned startingIndex=0) const;
61 void Clear(bool doNotDeallocateSmallBlocks, const char *file, unsigned int line);
62 data_type& operator[] ( const unsigned int position ) const;
63 unsigned Size(void) const;
64
65 protected:
66 unsigned LeftChild(const unsigned i) const;
67 unsigned RightChild(const unsigned i) const;
68 unsigned Parent(const unsigned i) const;
69 void Swap(const unsigned i, const unsigned j);
70 DataStructures::List<HeapNode> heap;
71 bool optimizeNextSeriesPush;
72 };
73
74 template <class weight_type, class data_type, bool isMaxHeap>
75 Heap<weight_type, data_type, isMaxHeap>::Heap()
76 {
77 optimizeNextSeriesPush=false;
78 }
79
80 template <class weight_type, class data_type, bool isMaxHeap>
81 Heap<weight_type, data_type, isMaxHeap>::~Heap()
82 {
83 //Clear(true, _FILE_AND_LINE_);
84 }
85
86 template <class weight_type, class data_type, bool isMaxHeap>
87 void Heap<weight_type, data_type, isMaxHeap>::PushSeries(const weight_type &weight, const data_type &data, const char *file, unsigned int line)
88 {
89 if (optimizeNextSeriesPush==false)
90 {
91 // 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
92 unsigned currentIndex = heap.Size();
93 unsigned parentIndex;
94 if (currentIndex>0)
95 {
96 for (parentIndex = Parent(currentIndex); parentIndex < currentIndex; parentIndex++)
97 {
98 #ifdef _MSC_VER
99 #pragma warning(disable:4127) // conditional expression is constant
100 #endif
101 if (isMaxHeap)
102 {
103 // Every child is less than its parent
104 if (weight>heap[parentIndex].weight)
105 {
106 // Can't optimize
107 Push(weight,data,file,line);
108 return;
109 }
110 }
111 else
112 {
113 // Every child is greater than than its parent
114 if (weight<heap[parentIndex].weight)
115 {
116 // Can't optimize
117 Push(weight,data,file,line);
118 return;
119 }
120 }
121 }
122 }
123
124 // 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
125 heap.Insert(HeapNode(weight, data), file, line);
126 optimizeNextSeriesPush=true;
127 }
128 else
129 {
130 heap.Insert(HeapNode(weight, data), file, line);
131 }
132 }
133
134 template <class weight_type, class data_type, bool isMaxHeap>
135 void Heap<weight_type, data_type, isMaxHeap>::Push(const weight_type &weight, const data_type &data, const char *file, unsigned int line)
136 {
137 unsigned currentIndex = heap.Size();
138 unsigned parentIndex;
139 heap.Insert(HeapNode(weight, data), file, line);
140 while (currentIndex!=0)
141 {
142 parentIndex = Parent(currentIndex);
143 #ifdef _MSC_VER
144 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
145 #endif
146 if (isMaxHeap)
147 {
148 if (heap[parentIndex].weight < weight)
149 {
150 Swap(currentIndex, parentIndex);
151 currentIndex=parentIndex;
152 }
153 else
154 break;
155 }
156 else
157 {
158 if (heap[parentIndex].weight > weight)
159 {
160 Swap(currentIndex, parentIndex);
161 currentIndex=parentIndex;
162 }
163 else
164 break;
165 }
166 }
167 }
168
169 template <class weight_type, class data_type, bool isMaxHeap>
170 data_type Heap<weight_type, data_type, isMaxHeap>::Pop(const unsigned startingIndex)
171 {
172 // While we have children, swap out with the larger of the two children.
173
174 // This line will assert on an empty heap
175 data_type returnValue=heap[startingIndex].data;
176
177 // Move the last element to the head, and re-heapify
178 heap[startingIndex]=heap[heap.Size()-1];
179
180 unsigned currentIndex,leftChild,rightChild;
181 weight_type currentWeight;
182 currentIndex=startingIndex;
183 currentWeight=heap[startingIndex].weight;
184 heap.RemoveFromEnd();
185
186 #ifdef _MSC_VER
187 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
188 #endif
189 for(;;)
190 {
191 leftChild=LeftChild(currentIndex);
192 rightChild=RightChild(currentIndex);
193 if (leftChild >= heap.Size())
194 {
195 // Done
196 return returnValue;
197 }
198 if (rightChild >= heap.Size())
199 {
200 // Only left node.
201 if ((isMaxHeap==true && currentWeight < heap[leftChild].weight) ||
202 (isMaxHeap==false && currentWeight > heap[leftChild].weight))
203 Swap(leftChild, currentIndex);
204
205 return returnValue;
206 }
207 else
208 {
209 // Swap with the bigger/smaller of the two children and continue
210 if (isMaxHeap)
211 {
212 if (heap[leftChild].weight <= currentWeight && heap[rightChild].weight <= currentWeight)
213 return returnValue;
214
215 if (heap[leftChild].weight > heap[rightChild].weight)
216 {
217 Swap(leftChild, currentIndex);
218 currentIndex=leftChild;
219 }
220 else
221 {
222 Swap(rightChild, currentIndex);
223 currentIndex=rightChild;
224 }
225 }
226 else
227 {
228 if (heap[leftChild].weight >= currentWeight && heap[rightChild].weight >= currentWeight)
229 return returnValue;
230
231 if (heap[leftChild].weight < heap[rightChild].weight)
232 {
233 Swap(leftChild, currentIndex);
234 currentIndex=leftChild;
235 }
236 else
237 {
238 Swap(rightChild, currentIndex);
239 currentIndex=rightChild;
240 }
241 }
242 }
243 }
244 }
245
246 template <class weight_type, class data_type, bool isMaxHeap>
247 inline data_type Heap<weight_type, data_type, isMaxHeap>::Peek(const unsigned startingIndex) const
248 {
249 return heap[startingIndex].data;
250 }
251
252 template <class weight_type, class data_type, bool isMaxHeap>
253 inline weight_type Heap<weight_type, data_type, isMaxHeap>::PeekWeight(const unsigned startingIndex) const
254 {
255 return heap[startingIndex].weight;
256 }
257
258 template <class weight_type, class data_type, bool isMaxHeap>
259 void Heap<weight_type, data_type, isMaxHeap>::Clear(bool doNotDeallocateSmallBlocks, const char *file, unsigned int line)
260 {
261 heap.Clear(doNotDeallocateSmallBlocks, file, line);
262 }
263
264 template <class weight_type, class data_type, bool isMaxHeap>
265 inline data_type& Heap<weight_type, data_type, isMaxHeap>::operator[] ( const unsigned int position ) const
266 {
267 return heap[position].data;
268 }
269 template <class weight_type, class data_type, bool isMaxHeap>
270 unsigned Heap<weight_type, data_type, isMaxHeap>::Size(void) const
271 {
272 return heap.Size();
273 }
274
275 template <class weight_type, class data_type, bool isMaxHeap>
276 inline unsigned Heap<weight_type, data_type, isMaxHeap>::LeftChild(const unsigned i) const
277 {
278 return i*2+1;
279 }
280
281 template <class weight_type, class data_type, bool isMaxHeap>
282 inline unsigned Heap<weight_type, data_type, isMaxHeap>::RightChild(const unsigned i) const
283 {
284 return i*2+2;
285 }
286
287 template <class weight_type, class data_type, bool isMaxHeap>
288 inline unsigned Heap<weight_type, data_type, isMaxHeap>::Parent(const unsigned i) const
289 {
290 #ifdef _DEBUG
291 RakAssert(i!=0);
292 #endif
293 return (i-1)/2;
294 }
295
296 template <class weight_type, class data_type, bool isMaxHeap>
297 void Heap<weight_type, data_type, isMaxHeap>::Swap(const unsigned i, const unsigned j)
298 {
299 HeapNode temp;
300 temp=heap[i];
301 heap[i]=heap[j];
302 heap[j]=temp;
303 }
304 }
305
306 #ifdef _MSC_VER
307 #pragma warning( pop )
308 #endif
309
310 #endif