Newton Dynamics  4.00
dHeap.h
1 /* Copyright (c) <2003-2019> <Julio Jerez, Newton Game Dynamics>
2 *
3 * This software is provided 'as-is', without any express or implied
4 * warranty. In no event will the authors be held liable for any damages
5 * arising from the use of this software.
6 *
7 * Permission is granted to anyone to use this software for any purpose,
8 * including commercial applications, and to alter it and redistribute it
9 * freely, subject to the following restrictions:
10 *
11 * 1. The origin of this software must not be misrepresented; you must not
12 * claim that you wrote the original software. If you use this software
13 * in a product, an acknowledgment in the product documentation would be
14 * appreciated but is not required.
15 *
16 * 2. Altered source versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software.
18 *
19 * 3. This notice may not be removed or altered from any source distribution.
20 */
21 
22 /****************************************************************************
23 *
24 * Visual C++ 6.0 created by: Julio Jerez
25 *
26 ****************************************************************************/
27 #ifndef __dHeapBase__
28 #define __dHeapBase__
29 
30 #include "dCoreStdafx.h"
31 #include "dTypes.h"
32 #include "dMemory.h"
33 
34 //#define DG_HEAP_DEBUG_CHECK
35 
36 template <class OBJECT, class KEY>
37 class dHeapBase
38 {
39  protected:
40  struct RECORD
41  {
42  KEY m_key;
43  OBJECT m_obj;
44 
45  RECORD (KEY key, const OBJECT& obj)
46  :m_key(key), m_obj(obj)
47  {
48  }
49  };
50 
51  dHeapBase (dInt32 maxElements);
52  dHeapBase (const void * const buffer, dInt32 sizeInBytes);
53  ~dHeapBase ();
54 
55  public:
56  void Flush ();
57  KEY MaxValue() const;
58  KEY Value(dInt32 i = 0) const;
59  dInt32 GetCount() const;
60  dInt32 GetMaxCount() const;
61  const OBJECT& operator[] (dInt32 i) const;
62  dInt32 Find (OBJECT &obj);
63  dInt32 Find (KEY key);
64 
65  RECORD *m_pool;
66  dInt32 m_curCount;
67  dInt32 m_maxCount;
68  bool m_bufferIsOwnned;
69 };
70 
71 template <class OBJECT, class KEY>
72 class dDownHeap: public dHeapBase<OBJECT, KEY>
73 {
74  public:
75  dDownHeap (dInt32 maxElements);
76  dDownHeap (const void * const buffer, dInt32 sizeInBytes);
77 
78  void Pop () {Remove (0);}
79  void Push (OBJECT &obj, KEY key);
80  void Sort ();
81  void Remove (dInt32 Index);
82  bool SanityCheck();
83 };
84 
85 template <class OBJECT, class KEY>
86 class dUpHeap: public dHeapBase<OBJECT, KEY>
87 {
88  public:
89  dUpHeap (dInt32 maxElements);
90  dUpHeap (const void * const buffer, dInt32 sizeInBytes);
91 
92  void Pop () {Remove (0);}
93  void Push (OBJECT &obj, KEY key);
94  void Sort ();
95  void Remove (dInt32 Index);
96  bool SanityCheck();
97 };
98 
99 template <class OBJECT, class KEY>
100 dHeapBase<OBJECT,KEY>::dHeapBase (dInt32 maxElements)
101  :m_pool((RECORD *)dMemory::Malloc(maxElements * sizeof(RECORD)))
102  ,m_curCount(0)
103  ,m_maxCount(maxElements)
104  ,m_bufferIsOwnned(true)
105 {
106  Flush();
107 }
108 
109 template <class OBJECT, class KEY>
110 dHeapBase<OBJECT,KEY>::dHeapBase (const void * const buffer, dInt32 sizeInBytes)
111  :m_pool((RECORD *)buffer)
112  ,m_curCount(0)
113  ,m_maxCount(dInt32(sizeInBytes / sizeof(RECORD)))
114  ,m_bufferIsOwnned(false)
115 {
116  Flush();
117 }
118 
119 template <class OBJECT, class KEY>
121 {
122  if (m_bufferIsOwnned)
123  {
124  dMemory::Free (m_pool);
125  }
126 }
127 
128 template <class OBJECT, class KEY>
129 KEY dHeapBase<OBJECT,KEY>::Value(dInt32 i) const
130 {
131  return m_pool[i].m_key;
132 }
133 
134 template <class OBJECT, class KEY>
135 dInt32 dHeapBase<OBJECT,KEY>::GetCount() const
136 {
137  return m_curCount;
138 }
139 
140 template <class OBJECT, class KEY>
142 {
143  m_curCount = 0;
144 
145  #ifdef _DEBUG
146 // dHeapBase<OBJECT,KEY>::m_pool[dHeapBase<OBJECT,KEY>::m_curCount].m_key = KEY (0);
147  #endif
148 }
149 
150 template <class OBJECT, class KEY>
152 {
153  return m_pool[0].m_key;
154 }
155 
156 template <class OBJECT, class KEY>
158 {
159  return m_maxCount;
160 }
161 
162 template <class OBJECT, class KEY>
163 dInt32 dHeapBase<OBJECT,KEY>::Find (OBJECT &obj)
164 {
165  // For now let perform a linear search
166  // this is efficient if the size of the heap is small
167  // ex: m_curCount < 32
168  // this will be change to a binary search in the heap should the
169  // the size of the heap get larger than 32
170  // dAssert (m_curCount <= 32);
171  for (dInt32 i = 0; i < m_curCount; i ++)
172  {
173  if (m_pool[i].obj == obj)
174  {
175  return i;
176  }
177  }
178  return - 1;
179 }
180 
181 template <class OBJECT, class KEY>
182 dInt32 dHeapBase<OBJECT,KEY>::Find (KEY key)
183 {
184  // ex: m_curCount < 32
185  // this will be change to a binary search in the heap shoud the
186  // the size of the heap get larger than 32
187  dAssert (m_curCount <= 32);
188  for (dInt32 i = 0; i < m_curCount; i ++)
189  {
190  if (m_pool[i].m_key == key)
191  {
192  return i;
193  }
194  }
195  return - 1;
196 }
197 
198 template <class OBJECT, class KEY>
199 const OBJECT& dHeapBase<OBJECT,KEY>::operator[] (dInt32 i) const
200 {
201  dAssert (i<= m_curCount);
202  return m_pool[i].m_obj;
203 }
204 
205 // **************************************************************************
206 //
207 // down Heap
208 //
209 // **************************************************************************
210 template <class OBJECT, class KEY>
211 dDownHeap<OBJECT,KEY>::dDownHeap (dInt32 maxElements)
212  :dHeapBase<OBJECT, KEY> (maxElements)
213 {
214 }
215 
216 template <class OBJECT, class KEY>
217 dDownHeap<OBJECT,KEY>::dDownHeap (const void * const buffer, dInt32 sizeInBytes)
218  :dHeapBase<OBJECT, KEY> (buffer, sizeInBytes)
219 {
220 }
221 
222 template <class OBJECT, class KEY>
223 void dDownHeap<OBJECT,KEY>::Push (OBJECT &obj, KEY key)
224 {
226 
227  //dInt32 j;
229  for (dInt32 j = 0; i; i = j)
230  {
231  j = i >> 1;
232  if (!j || (dHeapBase<OBJECT,KEY>::m_pool[j - 1].m_key > key))
233  {
234  break;
235  }
237  }
238  dAssert (i);
239  dHeapBase<OBJECT,KEY>::m_pool[i - 1].m_key = key;
240  dHeapBase<OBJECT,KEY>::m_pool[i - 1].m_obj = obj;
241 
242  dAssert (SanityCheck());
243 }
244 
245 template <class OBJECT, class KEY>
246 void dDownHeap<OBJECT,KEY>::Remove (dInt32 index)
247 {
250  while (index && dHeapBase<OBJECT, KEY>::m_pool[(index - 1) >> 1].m_key < dHeapBase<OBJECT, KEY>::m_pool[index].m_key)
251  {
252  dSwap(dHeapBase<OBJECT, KEY>::m_pool[(index - 1) >> 1], dHeapBase<OBJECT, KEY>::m_pool[index]);
253  index = (index - 1) >> 1;
254  }
255 
256  while ((2 * index + 1) < dHeapBase<OBJECT, KEY>::m_curCount)
257  {
258  dInt32 i0 = 2 * index + 1;
259  dInt32 i1 = 2 * index + 2;
261  {
262  i0 = (dHeapBase<OBJECT, KEY>::m_pool[i0].m_key > dHeapBase<OBJECT, KEY>::m_pool[i1].m_key) ? i0 : i1;
263  if (dHeapBase<OBJECT, KEY>::m_pool[i0].m_key <= dHeapBase<OBJECT, KEY>::m_pool[index].m_key)
264  {
265  break;
266  }
268  index = i0;
269  }
270  else
271  {
273  {
275  }
276  index = i0;
277  }
278  }
279  dAssert (SanityCheck());
280 }
281 
282 template <class OBJECT, class KEY>
284 {
285  dInt32 count = dHeapBase<OBJECT,KEY>::m_curCount;
286  for (dInt32 i = 1; i < count; i ++)
287  {
288  KEY key (dHeapBase<OBJECT,KEY>::m_pool[0].m_key);
289  OBJECT obj (dHeapBase<OBJECT,KEY>::m_pool[0].m_obj);
290 
291  Pop();
292 
295  }
296 
298  for (dInt32 i = 0; i < count / 2; i ++)
299  {
300  KEY key (dHeapBase<OBJECT,KEY>::m_pool[i].m_key);
301  OBJECT obj (dHeapBase<OBJECT,KEY>::m_pool[i].m_obj);
302 
303  dHeapBase<OBJECT,KEY>::m_pool[i].m_key = dHeapBase<OBJECT,KEY>::m_pool[count - i - 1].m_key;
304  dHeapBase<OBJECT,KEY>::m_pool[i].m_obj = dHeapBase<OBJECT,KEY>::m_pool[count - i - 1].m_obj;
305 
306  dHeapBase<OBJECT,KEY>::m_pool[count - i - 1].m_key = key;
307  dHeapBase<OBJECT,KEY>::m_pool[count - i - 1].m_obj = obj;
308  }
309  dAssert (SanityCheck());
310 }
311 
312 template <class OBJECT, class KEY>
314 {
315 #ifdef DG_HEAP_DEBUG_CHECK
316  for (dInt32 i = 0; i < m_curCount; i++)
317  {
318  dInt32 i1 = 2 * i + 1;
319  dInt32 i2 = 2 * i + 2;
320  if ((i1 < m_curCount) && (dHeapBase<OBJECT, KEY>::m_pool[i].m_key < dHeapBase<OBJECT, KEY>::m_pool[i1].m_key))
321  {
322  return false;
323  }
324  if ((i2 < m_curCount) && (dHeapBase<OBJECT, KEY>::m_pool[i].m_key < dHeapBase<OBJECT, KEY>::m_pool[i2].m_key))
325  {
326  return false;
327  }
328  }
329 #endif
330  return true;
331 }
332 
333 // **************************************************************************
334 //
335 // down Heap
336 //
337 // **************************************************************************
338 template <class OBJECT, class KEY>
339 dUpHeap<OBJECT,KEY>::dUpHeap (dInt32 maxElements)
340 // :dHeapBase<OBJECT, KEY> (maxElements, allocator)
341  :dHeapBase<OBJECT, KEY>(maxElements)
342 {
343 }
344 
345 template <class OBJECT, class KEY>
346 dUpHeap<OBJECT,KEY>::dUpHeap (const void * const buffer, dInt32 sizeInBytes)
347  :dHeapBase<OBJECT, KEY> (buffer, sizeInBytes)
348 {
349 }
350 
351 template <class OBJECT, class KEY>
353 {
354 #ifdef DG_HEAP_DEBUG_CHECK
355  for (dInt32 i = 0; i < m_curCount; i ++)
356  {
357  dInt32 i1 = 2 * i + 1;
358  dInt32 i2 = 2 * i + 2;
359  if ((i1 < m_curCount) && (dHeapBase<OBJECT,KEY>::m_pool[i].m_key > dHeapBase<OBJECT,KEY>::m_pool[i1].m_key))
360  {
361  return false;
362  }
363  if ((i2 < m_curCount) && (dHeapBase<OBJECT,KEY>::m_pool[i].m_key > dHeapBase<OBJECT,KEY>::m_pool[i2].m_key))
364  {
365  return false;
366  }
367  }
368 #endif
369  return true;
370 }
371 
372 template <class OBJECT, class KEY>
373 void dUpHeap<OBJECT,KEY>::Push (OBJECT &obj, KEY key)
374 {
376 
377  //dInt32 j;
379  for (dInt32 j = 0; i; i = j)
380  {
381  j = i >> 1;
382  if (!j || (dHeapBase<OBJECT,KEY>::m_pool[j - 1].m_key < key))
383  {
384  break;
385  }
387  }
388  dAssert (i);
389  dHeapBase<OBJECT,KEY>::m_pool[i - 1].m_key = key;
390  dHeapBase<OBJECT,KEY>::m_pool[i - 1].m_obj = obj;
391  dAssert (SanityCheck());
392 }
393 
394 template <class OBJECT, class KEY>
396 {
397  dInt32 count = dHeapBase<OBJECT,KEY>::m_curCount;
398  for (dInt32 i = 1; i < count; i ++)
399  {
400  KEY key (dHeapBase<OBJECT,KEY>::m_pool[0].m_key);
401  OBJECT obj (dHeapBase<OBJECT,KEY>::m_pool[0].m_obj);
402 
403  Pop();
404 
407  }
408 
410  for (dInt32 i = 0; i < count / 2; i ++)
411  {
412  KEY key (dHeapBase<OBJECT,KEY>::m_pool[i].m_key);
413  OBJECT obj (dHeapBase<OBJECT,KEY>::m_pool[i].m_obj);
414 
415  dHeapBase<OBJECT,KEY>::m_pool[i].m_key = dHeapBase<OBJECT,KEY>::m_pool[count - i - 1].m_key;
416  dHeapBase<OBJECT,KEY>::m_pool[i].m_obj = dHeapBase<OBJECT,KEY>::m_pool[count - i - 1].m_obj;
417 
418  dHeapBase<OBJECT,KEY>::m_pool[count - i - 1].m_key = key;
419  dHeapBase<OBJECT,KEY>::m_pool[count - i - 1].m_obj = obj;
420  }
421  dAssert (SanityCheck());
422 }
423 
424 template <class OBJECT, class KEY>
425 void dUpHeap<OBJECT,KEY>::Remove (dInt32 index)
426 {
429  while (index && dHeapBase<OBJECT, KEY>::m_pool[(index - 1) >> 1].m_key > dHeapBase<OBJECT, KEY>::m_pool[index].m_key)
430  {
431  dSwap(dHeapBase<OBJECT, KEY>::m_pool[(index - 1) >> 1], dHeapBase<OBJECT, KEY>::m_pool[index]);
432  index = (index - 1) >> 1;
433  }
434 
435  while ((2 * index + 1) < dHeapBase<OBJECT, KEY>::m_curCount)
436  {
437  dInt32 i0 = 2 * index + 1;
438  dInt32 i1 = 2 * index + 2;
440  {
441  i0 = (dHeapBase<OBJECT, KEY>::m_pool[i0].m_key < dHeapBase<OBJECT, KEY>::m_pool[i1].m_key) ? i0 : i1;
442  if (dHeapBase<OBJECT, KEY>::m_pool[i0].m_key >= dHeapBase<OBJECT, KEY>::m_pool[index].m_key)
443  {
444  break;
445  }
447  index = i0;
448  }
449  else
450  {
452  {
454  }
455  index = i0;
456  }
457  }
458  dAssert (SanityCheck());
459 }
460 
461 #endif
dDownHeap
Definition: dHeap.h:73
dHeapBase::RECORD
Definition: dHeap.h:41
dMemory::Free
static D_CORE_API void Free(void *const ptr)
Destroy a memory buffer previously allocated by Malloc.
Definition: dMemory.cpp:58
dMemory
Definition: dMemory.h:31
dHeapBase
Definition: dHeap.h:38
dUpHeap
Definition: dHeap.h:87