ScummVM API documentation
dgHeap.h
1 /* Copyright (c) <2003-2011> <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 __dgHeapBase__
28 #define __dgHeapBase__
29 
30 #include "dgStdafx.h"
31 #include "dgMemory.h"
32 
33 #include "common/util.h"
34 
35 
36 //#define DG_HEAP_SANITY_CHECK
37 
38 template <class OBJECT, class KEY>
39 class dgHeapBase {
40 protected:
41  struct RECORD {
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  dgHeapBase(dgInt32 maxElements, dgMemoryAllocator *const allocator);
51  dgHeapBase(const void *const buffer, dgInt32 sizeInBytes);
52  ~dgHeapBase();
53 
54 public:
55  DG_CLASS_ALLOCATOR(allocator)
56 
57  void Flush();
58  KEY MaxValue() const;
59  KEY Value(dgInt32 i = 0) const;
60  dgInt32 GetCount() const;
61  dgInt32 GetMaxCount() const;
62  const OBJECT &operator[](dgInt32 i) const;
63  OBJECT &operator[](dgInt32 i);
64  dgInt32 Find(OBJECT &obj);
65  dgInt32 Find(KEY key);
66 
67  dgInt32 m_curCount;
68  dgInt32 m_maxCount;
69 // bool m_allocated;
70  dgMemoryAllocator *m_allocator;
71  RECORD *m_pool;
72 };
73 
74 template <class OBJECT, class KEY>
75 class dgDownHeap: public dgHeapBase<OBJECT, KEY> {
76 public:
77  dgDownHeap(dgInt32 maxElements, dgMemoryAllocator *const allocator);
78  dgDownHeap(const void *const buffer, dgInt32 sizeInBytes);
79 
80  void Pop();
81  void Push(OBJECT &obj, KEY key);
82  void Sort();
83  void Remove(dgInt32 Index);
84 
85 #ifdef DG_HEAP_SANITY_CHECK
86  bool SanityCheck();
87 #endif
88 };
89 
90 template <class OBJECT, class KEY>
91 class dgUpHeap: public dgHeapBase<OBJECT, KEY> {
92 public:
93  dgUpHeap(dgInt32 maxElements, dgMemoryAllocator *const allocator);
94  dgUpHeap(const void *const buffer, dgInt32 sizeInBytes);
95 
96  void Pop();
97  void Push(OBJECT &obj, KEY key);
98  void Sort();
99  void Remove(dgInt32 Index);
100 
101 #ifdef DG_HEAP_SANITY_CHECK
102  bool SanityCheck();
103 #endif
104 };
105 
106 
107 
108 template <class OBJECT, class KEY>
109 dgHeapBase<OBJECT, KEY>::dgHeapBase(dgInt32 maxElements, dgMemoryAllocator *const allocator) {
110 // m_allocated = true;
111  m_allocator = allocator;
112  m_pool = (RECORD *)m_allocator->Malloc(maxElements * sizeof(RECORD));
113  m_maxCount = maxElements;
114  Flush();
115 }
116 
117 template <class OBJECT, class KEY>
118 dgHeapBase<OBJECT, KEY>::dgHeapBase(const void *const buffer, dgInt32 sizeInBytes) {
119 // NEWTON_ASSERT (0);
120 // m_allocated = false;
121  m_allocator = NULL;
122  m_pool = const_cast<RECORD *>((const RECORD *)buffer);
123  m_maxCount = dgInt32(sizeInBytes / sizeof(RECORD));
124  Flush();
125 }
126 
127 template <class OBJECT, class KEY>
129  if (m_allocator) {
130  m_allocator->Free(m_pool);
131  }
132 }
133 
134 
135 template <class OBJECT, class KEY>
136 KEY dgHeapBase<OBJECT, KEY>::Value(dgInt32 i) const {
137  return m_pool[i].m_key;
138 }
139 
140 
141 template <class OBJECT, class KEY>
142 dgInt32 dgHeapBase<OBJECT, KEY>::GetCount() const {
143  return m_curCount;
144 }
145 
146 
147 template <class OBJECT, class KEY>
149  m_curCount = 0;
150 
151 #ifdef _DEBUG
152 // dgHeapBase<OBJECT,KEY>::m_pool[dgHeapBase<OBJECT,KEY>::m_curCount].m_key = KEY (0);
153 #endif
154 }
155 
156 
157 template <class OBJECT, class KEY>
159  return m_pool[0].m_key;
160 }
161 
162 
163 template <class OBJECT, class KEY>
164 dgInt32 dgHeapBase<OBJECT, KEY>::GetMaxCount() const {
165  return m_maxCount;
166 }
167 
168 
169 template <class OBJECT, class KEY>
170 dgInt32 dgHeapBase<OBJECT, KEY>::Find(OBJECT &obj) {
171  // For now let perform a linear search
172  // this is efficient if the size of the heap is small
173  // ex: m_curCount < 32
174  // this will be change to a binary search in the heap should the
175  // the size of the heap get larger than 32
176  // NEWTON_ASSERT (m_curCount <= 32);
177  for (dgInt32 i = 0; i < m_curCount; i ++) {
178  if (m_pool[i].obj == obj) {
179  return i;
180  }
181  }
182  return - 1;
183 }
184 
185 
186 template <class OBJECT, class KEY>
187 dgInt32 dgHeapBase<OBJECT, KEY>::Find(KEY key) {
188  // ex: m_curCount < 32
189  // this will be change to a binary search in the heap shoud the
190  // the size of the heap get larger than 32
191  NEWTON_ASSERT(m_curCount <= 32);
192  for (dgInt32 i = 0; i < m_curCount; i ++) {
193  if (m_pool[i].m_key == key) {
194  return i;
195  }
196  }
197  return - 1;
198 }
199 
200 
201 template <class OBJECT, class KEY>
202 const OBJECT &dgHeapBase<OBJECT, KEY>::operator[](dgInt32 i) const {
203  NEWTON_ASSERT(i <= m_curCount);
204  return m_pool[i].m_obj;
205 }
206 
207 template <class OBJECT, class KEY>
208 OBJECT &dgHeapBase<OBJECT, KEY>::operator[](dgInt32 i) {
209  NEWTON_ASSERT(i <= m_curCount);
210  return m_pool[i].m_obj;
211 }
212 
213 
214 // **************************************************************************
215 //
216 // down Heap
217 //
218 // **************************************************************************
219 template <class OBJECT, class KEY>
220 dgDownHeap<OBJECT, KEY>::dgDownHeap(dgInt32 maxElements, dgMemoryAllocator *const allocator)
221  : dgHeapBase<OBJECT, KEY> (maxElements, allocator) {
222 }
223 
224 template <class OBJECT, class KEY>
225 dgDownHeap<OBJECT, KEY>::dgDownHeap(const void *const buffer, dgInt32 sizeInBytes)
226  : dgHeapBase<OBJECT, KEY> (buffer, sizeInBytes) {
227 }
228 
229 
230 template <class OBJECT, class KEY>
231 void dgDownHeap<OBJECT, KEY>::Push(OBJECT &obj, KEY key) {
232  dgInt32 i;
233  dgInt32 j;
234 #ifdef _DEBUG
235 // NEWTON_ASSERT (m_curCount < m_maxCount);
238  NEWTON_ASSERT(cc < cm);
239 #endif
240 
242 
243  for (i = dgHeapBase<OBJECT, KEY>::m_curCount; i; i = j) {
244  j = i >> 1;
245  if (!j || (dgHeapBase<OBJECT, KEY>::m_pool[j - 1].m_key > key)) {
246  break;
247  }
249  }
250  NEWTON_ASSERT(i);
251  dgHeapBase<OBJECT, KEY>::m_pool[i - 1].m_key = key;
252  dgHeapBase<OBJECT, KEY>::m_pool[i - 1].m_obj = obj;
253 
254 #ifdef DG_HEAP_SANITY_CHECK
255  NEWTON_ASSERT(SanityCheck());
256 #endif
257 }
258 
259 
260 template <class OBJECT, class KEY>
261 void dgDownHeap<OBJECT, KEY>::Remove(dgInt32 index) {
262  dgInt32 j;
263  dgInt32 k;
264 
267  for (k = index + 1; k <= (dgHeapBase<OBJECT, KEY>::m_curCount >> 1); k = j) {
268  j = k + k;
271  j ++;
272  }
273  if (key >= dgHeapBase<OBJECT, KEY>::m_pool[j - 1].m_key) {
274  break;
275  }
277  }
278  dgHeapBase<OBJECT, KEY>::m_pool[k - 1].m_key = key;
280 
281 #ifdef DG_HEAP_SANITY_CHECK
282  NEWTON_ASSERT(SanityCheck());
283 #endif
284 
285 }
286 
287 template <class OBJECT, class KEY>
289  dgInt32 j;
290  dgInt32 k;
291 
294  for (k = 1; k <= (dgHeapBase<OBJECT, KEY>::m_curCount >> 1); k = j) {
295  j = k + k;
298  j ++;
299  }
300  if (key >= dgHeapBase<OBJECT, KEY>::m_pool[j - 1].m_key) {
301  break;
302  }
304  }
305  dgHeapBase<OBJECT, KEY>::m_pool[k - 1].m_key = key;
307 
308 #ifdef DG_HEAP_SANITY_CHECK
309  NEWTON_ASSERT(SanityCheck());
310 #endif
311 }
312 
313 
314 
315 template <class OBJECT, class KEY>
317 
318  dgInt32 count = dgHeapBase<OBJECT, KEY>::m_curCount;
319  for (dgInt32 i = 1; i < count; i ++) {
320  KEY key(dgHeapBase<OBJECT, KEY>::m_pool[0].m_key);
321  OBJECT obj(dgHeapBase<OBJECT, KEY>::m_pool[0].m_obj);
322 
323  Pop();
324 
327  }
328 
330  for (dgInt32 i = 0; i < count / 2; i ++) {
331  KEY key(dgHeapBase<OBJECT, KEY>::m_pool[i].m_key);
332  OBJECT obj(dgHeapBase<OBJECT, KEY>::m_pool[i].m_obj);
333 
336 
337  dgHeapBase<OBJECT, KEY>::m_pool[count - i - 1].m_key = key;
338  dgHeapBase<OBJECT, KEY>::m_pool[count - i - 1].m_obj = obj;
339  }
340 #ifdef DG_HEAP_SANITY_CHECK
341  NEWTON_ASSERT(SanityCheck());
342 #endif
343 }
344 
345 #ifdef DG_HEAP_SANITY_CHECK
346 template <class OBJECT, class KEY>
348  for (dgInt32 i = 0; i < dgHeapBase<OBJECT, KEY>::m_curCount / 2; i ++) {
349  if (dgHeapBase<OBJECT, KEY>::m_pool[i].m_key < dgHeapBase<OBJECT, KEY>::m_pool[i * 2 + 1].m_key) {
350  return false;
351  }
352  if ((i * 2 + 2) < dgHeapBase<OBJECT, KEY>::m_curCount) {
353  if (dgHeapBase<OBJECT, KEY>::m_pool[i].m_key < dgHeapBase<OBJECT, KEY>::m_pool[i * 2 + 2].m_key) {
354  return false;
355  }
356  }
357  }
358 
359  return true;
360 }
361 #endif
362 
363 
364 
365 
366 // **************************************************************************
367 //
368 // down Heap
369 //
370 // **************************************************************************
371 template <class OBJECT, class KEY>
372 dgUpHeap<OBJECT, KEY>::dgUpHeap(dgInt32 maxElements, dgMemoryAllocator *const allocator)
373  : dgHeapBase<OBJECT, KEY> (maxElements, allocator) {
374 }
375 
376 template <class OBJECT, class KEY>
377 dgUpHeap<OBJECT, KEY>::dgUpHeap(const void *const buffer, dgInt32 sizeInBytes)
378  : dgHeapBase<OBJECT, KEY> (buffer, sizeInBytes) {
379 }
380 
381 #ifdef DG_HEAP_SANITY_CHECK
382 template <class OBJECT, class KEY>
384  for (dgInt32 i = 0; i < dgHeapBase<OBJECT, KEY>::m_curCount / 2; i ++) {
385  if (dgHeapBase<OBJECT, KEY>::m_pool[i].m_key > dgHeapBase<OBJECT, KEY>::m_pool[i * 2 + 1].m_key) {
386  return false;
387  }
388  if ((i * 2 + 2) < dgHeapBase<OBJECT, KEY>::m_curCount) {
389  if (dgHeapBase<OBJECT, KEY>::m_pool[i].m_key > dgHeapBase<OBJECT, KEY>::m_pool[i * 2 + 2].m_key) {
390  return false;
391  }
392  }
393  }
394 
395  return true;
396 }
397 #endif
398 
399 template <class OBJECT, class KEY>
400 void dgUpHeap<OBJECT, KEY>::Push(OBJECT &obj, KEY key) {
401  dgInt32 i;
402  dgInt32 j;
403 
404 #ifdef _DEBUG
405  // NEWTON_ASSERT (m_curCount < m_maxCount);
408  NEWTON_ASSERT(cc < cm);
409 #endif
411 
412  for (i = dgHeapBase<OBJECT, KEY>::m_curCount; i; i = j) {
413  j = i >> 1;
414  if (!j || (dgHeapBase<OBJECT, KEY>::m_pool[j - 1].m_key < key)) {
415  break;
416  }
418  }
419  NEWTON_ASSERT(i);
420  dgHeapBase<OBJECT, KEY>::m_pool[i - 1].m_key = key;
421  dgHeapBase<OBJECT, KEY>::m_pool[i - 1].m_obj = obj;
422 
423 #ifdef DG_HEAP_SANITY_CHECK
424  NEWTON_ASSERT(SanityCheck());
425 #endif
426 }
427 
428 
429 template <class OBJECT, class KEY>
431  dgInt32 count = dgHeapBase<OBJECT, KEY>::m_curCount;
432  for (dgInt32 i = 1; i < count; i ++) {
433  KEY key(dgHeapBase<OBJECT, KEY>::m_pool[0].m_key);
434  OBJECT obj(dgHeapBase<OBJECT, KEY>::m_pool[0].m_obj);
435 
436  Pop();
437 
440  }
441 
443  for (dgInt32 i = 0; i < count / 2; i ++) {
444  KEY key(dgHeapBase<OBJECT, KEY>::m_pool[i].m_key);
445  OBJECT obj(dgHeapBase<OBJECT, KEY>::m_pool[i].m_obj);
446 
449 
450  dgHeapBase<OBJECT, KEY>::m_pool[count - i - 1].m_key = key;
451  dgHeapBase<OBJECT, KEY>::m_pool[count - i - 1].m_obj = obj;
452  }
453 #ifdef DG_HEAP_SANITY_CHECK
454  NEWTON_ASSERT(SanityCheck());
455 #endif
456 }
457 
458 
459 template <class OBJECT, class KEY>
460 void dgUpHeap<OBJECT, KEY>::Remove(dgInt32 index) {
461  dgInt32 j;
462  dgInt32 k;
463 
466  for (k = index + 1; k <= (dgHeapBase<OBJECT, KEY>::m_curCount >> 1); k = j) {
467  j = k + k;
470  j ++;
471  }
472  if (key <= dgHeapBase<OBJECT, KEY>::m_pool[j - 1].m_key) {
473  break;
474  }
476  }
477  dgHeapBase<OBJECT, KEY>::m_pool[k - 1].m_key = key;
479 
480 #ifdef DG_HEAP_SANITY_CHECK
481  NEWTON_ASSERT(SanityCheck());
482 #endif
483 }
484 
485 
486 template <class OBJECT, class KEY>
488  dgInt32 j;
489  dgInt32 k;
490 
493  for (k = 1; k <= (dgHeapBase<OBJECT, KEY>::m_curCount >> 1); k = j) {
494  j = k + k;
497  j ++;
498  }
499  if (key <= dgHeapBase<OBJECT, KEY>::m_pool[j - 1].m_key) {
500  break;
501  }
503  }
504  dgHeapBase<OBJECT, KEY>::m_pool[k - 1].m_key = key;
506 
507 #ifdef DG_HEAP_SANITY_CHECK
508  NEWTON_ASSERT(SanityCheck());
509 #endif
510 }
511 
512 
513 #endif
Definition: dgHeap.h:41
Definition: lobject.h:59
Definition: dgHeap.h:75
Definition: dgHeap.h:39
Definition: dgHeap.h:91
Definition: dgMemory.h:80