ScummVM API documentation
dgTree.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 #ifndef __dgTree__
23 #define __dgTree__
24 
25 #include "dgStdafx.h"
26 #include "dgRef.h"
27 #include "dgDebug.h"
28 #include "dgMemory.h"
29 
30 
31 
32 // Note: this is a low level class for dgTree use only
33 // unpredictable result will happen if you attempt to manipulate
34 // any member of this class
36 public:
37  enum REDBLACK_COLOR {
38  RED = true,
39  BLACK = false
40  };
41 
42  DG_CLASS_ALLOCATOR(allocator)
43 
44  dgRedBackNode() {
45  }
46 
47  virtual ~dgRedBackNode() {
48  }
49 
50  void RemoveAllLow();
51  void RotateLeft(dgRedBackNode **const head);
52  void RotateRight(dgRedBackNode **const head);
53  void RemoveFixup(dgRedBackNode *const node, dgRedBackNode * * const head);
54 
55  dgRedBackNode *GetLeft() const;
56  dgRedBackNode *GetRight() const;
57  dgRedBackNode *GetParent() const;
58 
59  dgRedBackNode(dgRedBackNode *const parent);
60  inline void Initdata(dgRedBackNode *const parent);
61  inline void SetColor(REDBLACK_COLOR color);
62  REDBLACK_COLOR GetColor() const;
63  dgUnsigned32 IsInTree() const;
64  inline void SetInTreeFlag(dgUnsigned32 flag);
65 
66  void RemoveAll();
67  const dgRedBackNode *Prev() const;
68  const dgRedBackNode *Next() const;
69  const dgRedBackNode *Minimum() const;
70  const dgRedBackNode *Maximum() const;
71  dgRedBackNode *Prev();
72  dgRedBackNode *Next();
73  dgRedBackNode *Minimum();
74  dgRedBackNode *Maximum();
75  void Remove(dgRedBackNode **const head);
76  void Unlink(dgRedBackNode **const head);
77  void InsertFixup(dgRedBackNode **const head);
78 
79  dgRedBackNode *m_left;
80  dgRedBackNode *m_right;
81  dgRedBackNode *m_parent;
82  dgUnsigned32 m_color : 1;
83  dgUnsigned32 m_inTree : 1;
84 // dgUnsigned32 m_pad[2];
85 };
86 
87 template<class OBJECT, class KEY>
88 class dgTree {
89 public:
90  class dgTreeNode: public dgRedBackNode {
91  dgTreeNode(
92  const OBJECT &info,
93  const KEY &key,
94  dgTreeNode *parentNode)
95  : dgRedBackNode(parentNode), m_info(info), m_key(key) {
96 // NEWTON_ASSERT ((dgUnsigned64 (&m_info) & 0x0f) == 0);
97  }
98 
99  ~dgTreeNode() {
100  }
101 
102  dgTreeNode *GetLeft() const {
103  return (dgTreeNode *)dgRedBackNode::m_left;
104  }
105 
106  dgTreeNode *GetRight() const {
107  return (dgTreeNode *)dgRedBackNode::m_right;
108  }
109 
110  dgTreeNode *GetParent() {
111  return (dgTreeNode *)dgRedBackNode::m_parent;
112  }
113 
114  void SetLeft(dgTreeNode *const node) {
115  dgRedBackNode::m_left = node;
116  }
117 
118  void SetRight(dgTreeNode *const node) {
119  dgRedBackNode::m_right = node;
120  }
121 
122  void SetParent(dgTreeNode *const node) {
123  dgRedBackNode::m_parent = node;
124  }
125 
126  public:
127  const KEY &GetKey() const {
128  return m_key;
129  }
130 
131  OBJECT &GetInfo() {
132  return m_info;
133  }
134 
135  const OBJECT &GetInfo() const {
136  return m_info;
137  }
138 
139  private:
140  OBJECT m_info;
141  KEY m_key;
142  friend class dgTree<OBJECT, KEY>;
143 
144  };
145 
146  class Iterator {
147 
148  public:
149  Iterator(const dgTree<OBJECT, KEY> &me) {
150  m_ptr = NULL;
151  m_tree = &me;
152  }
153 
154  ~Iterator() {
155  }
156 
157  void Begin() {
158  m_ptr = m_tree->Minimum();
159  }
160 
161  void End() {
162  m_ptr = m_tree->Maximum();
163  }
164 
165  void Set(dgTreeNode *const node) {
166  m_ptr = node;
167  }
168 
169  operator dgInt32() const {
170  return m_ptr != NULL;
171  }
172 
173  void operator++ () {
174  NEWTON_ASSERT(m_ptr);
175  m_ptr = m_ptr->Next();
176  }
177 
178  void operator++ (int) {
179  NEWTON_ASSERT(m_ptr);
180  m_ptr = m_ptr->Next();
181  }
182 
183  void operator-- () {
184  NEWTON_ASSERT(m_ptr);
185  m_ptr = m_ptr->Prev();
186  }
187 
188  void operator-- (int) {
189  NEWTON_ASSERT(m_ptr);
190  m_ptr = m_ptr->Prev();
191  }
192 
193  OBJECT &operator* () const {
194  return ((dgTreeNode *)m_ptr)->GetInfo();
195  }
196 
197  dgTreeNode *GetNode() const {
198  return (dgTreeNode *)m_ptr;
199  }
200 
201  KEY GetKey() const {
202  dgTreeNode *const tmp = (dgTreeNode *)m_ptr;
203  return tmp ? tmp->GetKey() : KEY(0);
204  }
205 
206  private:
207  dgRedBackNode *m_ptr;
208  const dgTree *m_tree;
209 
210  };
211 
212 
213  // ***********************************************************
214  // member functions
215  // ***********************************************************
216 public:
217  DG_CLASS_ALLOCATOR(allocator)
218 
219 // dgTree ();
220  dgTree(dgMemoryAllocator *const allocator);
221  virtual ~dgTree();
222 
223  dgMemoryAllocator *GetAllocator() const;
224  void SetAllocator(dgMemoryAllocator *const allocator);
225 
226 
227  operator dgInt32() const;
228  dgInt32 GetCount() const;
229 
230  dgTreeNode *GetRoot() const;
231  dgTreeNode *Minimum() const;
232  dgTreeNode *Maximum() const;
233 
234  dgTreeNode *Find(KEY key) const;
235  dgTreeNode *FindGreater(KEY key) const;
236  dgTreeNode *FindGreaterEqual(KEY key) const;
237  dgTreeNode *FindLessEqual(KEY key) const;
238 
239  dgTreeNode *GetNodeFromInfo(OBJECT &info) const;
240 
241  dgTreeNode *Insert(const OBJECT &element, KEY key, bool &elementWasInTree);
242  dgTreeNode *Insert(const OBJECT &element, KEY key);
243  dgTreeNode *Insert(dgTreeNode *const node, KEY key);
244 
245  dgTreeNode *Replace(OBJECT &element, KEY key);
246  dgTreeNode *ReplaceKey(KEY oldKey, KEY newKey);
247  dgTreeNode *ReplaceKey(dgTreeNode *const node, KEY key);
248 
249  void Remove(KEY key);
250  void Remove(dgTreeNode *const node);
251  void RemoveAll();
252 
253  void Unlink(dgTreeNode *const node);
254  void SwapInfo(dgTree &tree);
255 
256  bool SanityCheck() const;
257 
258  // ***********************************************************
259  // member variables
260  // ***********************************************************
261 private:
262  dgInt32 m_count;
263  dgTreeNode *m_head;
264  dgMemoryAllocator *m_allocator;
265 
266  dgInt32 CompareKeys(const KEY &key0, const KEY &key1) const;
267  bool SanityCheck(dgTreeNode *const ptr, dgInt32 height) const;
268 
269  friend class dgTreeNode;
270 };
271 
272 
273 inline dgRedBackNode::dgRedBackNode(dgRedBackNode *const parent) {
274  Initdata(parent);
275 }
276 
277 inline void dgRedBackNode::Initdata(dgRedBackNode *const parent) {
278  SetColor(RED);
279  SetInTreeFlag(true);
280  m_left = NULL;
281  m_right = NULL;
282  m_parent = parent;
283 }
284 
285 inline void dgRedBackNode::SetColor(dgRedBackNode::REDBLACK_COLOR color) {
286  m_color = color;
287 }
288 
289 
290 
291 inline dgRedBackNode::REDBLACK_COLOR dgRedBackNode::GetColor() const {
292  return REDBLACK_COLOR(m_color);
293 }
294 
295 
296 inline void dgRedBackNode::SetInTreeFlag(dgUnsigned32 flag) {
297  m_inTree = flag;
298 }
299 
300 inline dgUnsigned32 dgRedBackNode::IsInTree() const {
301  return m_inTree;
302 }
303 
304 /*
305 template<class OBJECT, class KEY>
306 dgTree<OBJECT, KEY>::dgTree ()
307 {
308  m_count = 0;
309  m_head = NULL;
310  m_allocator = NULL;
311 }
312 */
313 
314 template<class OBJECT, class KEY>
316  m_count = 0;
317  m_head = NULL;
318  m_allocator = allocator;
319 }
320 
321 
322 template<class OBJECT, class KEY>
324  RemoveAll();
325 }
326 
327 template<class OBJECT, class KEY>
329  return m_allocator;
330 }
331 
332 template<class OBJECT, class KEY>
334  if ((m_count == 0) && (m_allocator == NULL)) {
335  m_allocator = allocator;
336  }
337 }
338 
339 
340 template<class OBJECT, class KEY>
341 dgTree<OBJECT, KEY>::operator dgInt32() const {
342  return m_head != NULL;
343 }
344 
345 template<class OBJECT, class KEY>
346 dgInt32 dgTree<OBJECT, KEY>::GetCount() const {
347  return m_count;
348 }
349 
350 template<class OBJECT, class KEY>
352  return m_head ? (dgTreeNode *)m_head->Minimum() : NULL;
353 }
354 
355 template<class OBJECT, class KEY>
357  return m_head ? (dgTreeNode *)m_head->Maximum() : NULL;
358 }
359 
360 template<class OBJECT, class KEY>
362  return m_head;
363 }
364 
365 template<class OBJECT, class KEY>
367  if (m_head == NULL) {
368  return NULL;
369  }
370 
371  dgTreeNode *ptr = m_head;
372  while (ptr != NULL) {
373  if (key < ptr->m_key) {
374  NEWTON_ASSERT(CompareKeys(ptr->m_key, key) == -1) ;
375  ptr = ptr->GetLeft();
376  } else if (key > ptr->m_key) {
377  NEWTON_ASSERT(CompareKeys(ptr->m_key, key) == 1) ;
378  ptr = ptr->GetRight();
379  } else {
380  NEWTON_ASSERT(CompareKeys(ptr->m_key, key) == 0) ;
381  break;
382  }
383  }
384  return ptr;
385 }
386 
387 template<class OBJECT, class KEY>
389  dgTreeNode *const node = (dgTreeNode *) &info;
390  dgInt64 offset = ((char *) &node->m_info) - ((char *) node);
391  dgTreeNode *const retnode = (dgTreeNode *)(((char *) node) - offset);
392 
393  NEWTON_ASSERT(retnode->IsInTree());
394  NEWTON_ASSERT(&retnode->GetInfo() == &info);
395  return (retnode->IsInTree()) ? retnode : NULL;
396 
397 }
398 
399 template<class OBJECT, class KEY>
401  if (m_head == NULL) {
402  return NULL;
403  }
404 
405  dgTreeNode *prev = NULL;
406  dgTreeNode *ptr = m_head;
407 
408  while (ptr != NULL) {
409  if (key < ptr->m_key) {
410  prev = ptr;
411  ptr = ptr->GetLeft();
412  } else {
413  ptr = ptr->GetRight();
414  }
415  }
416 
417 #ifdef __ENABLE_SANITY_CHECK
418  if (prev) {
419  Iterator iter(*this);
420  for (iter.Begin(); iter.GetNode() != prev; iter ++) {
421  KEY key1 = iter.GetKey();
422  NEWTON_ASSERT(key1 <= key);
423  }
424  for (; iter.GetNode(); iter ++) {
425  KEY key1 = iter.GetKey();
426  NEWTON_ASSERT(key1 > key);
427  }
428  }
429 #endif
430 
431  return (dgTreeNode *)prev;
432 }
433 
434 template<class OBJECT, class KEY>
436  if (m_head == NULL) {
437  return NULL;
438  }
439 
440  dgTreeNode *prev = NULL;
441  dgTreeNode *ptr = m_head;
442 
443  while (ptr != NULL) {
444  if (key == ptr->m_key) {
445  return ptr;
446  }
447  if (key < ptr->m_key) {
448  prev = ptr;
449  ptr = ptr->GetLeft();
450  } else {
451  ptr = ptr->GetRight();
452  }
453  }
454 
455 #ifdef __ENABLE_SANITY_CHECK
456  if (prev) {
457  Iterator iter(*this);
458  for (iter.Begin(); iter.GetNode() != prev; iter ++) {
459  KEY key1 = iter.GetKey();
460  NEWTON_ASSERT(key1 <= key);
461  }
462  for (; iter.GetNode(); iter ++) {
463  KEY key1 = iter.GetKey();
464  NEWTON_ASSERT(key1 >= key);
465  }
466  }
467 #endif
468 
469  return (dgTreeNode *)prev;
470 }
471 
472 template<class OBJECT, class KEY>
474  if (m_head == NULL) {
475  return NULL;
476  }
477 
478  dgTreeNode *prev = NULL;
479  dgTreeNode *ptr = m_head;
480 
481  while (ptr != NULL) {
482  if (key == ptr->m_key) {
483  return ptr;
484  }
485 
486  if (key < ptr->m_key) {
487  ptr = ptr->GetLeft();
488  } else {
489  prev = ptr;
490  ptr = ptr->GetRight();
491  }
492 
493  }
494 
495 #ifdef __ENABLE_SANITY_CHECK
496  if (prev) {
497  Iterator iter(*this);
498  for (iter.End(); iter.GetNode() != prev; iter --) {
499  KEY key1 = iter.GetKey();
500  NEWTON_ASSERT(key1 >= key);
501  }
502  for (; iter.GetNode(); iter --) {
503  KEY key1 = iter.GetKey();
504  NEWTON_ASSERT(key1 < key);
505  }
506  }
507 #endif
508 
509  return (dgTreeNode *)prev;
510 }
511 
512 template<class OBJECT, class KEY>
513 typename dgTree<OBJECT, KEY>::dgTreeNode *dgTree<OBJECT, KEY>::Insert(const OBJECT &element, KEY key, bool &elementWasInTree) {
514  dgTreeNode *parent = NULL;
515  dgTreeNode *ptr = m_head;
516  dgInt32 val = 0;
517  elementWasInTree = false;
518  while (ptr != NULL) {
519  parent = ptr;
520 
521  if (key < ptr->m_key) {
522  NEWTON_ASSERT(CompareKeys(ptr->m_key, key) == -1) ;
523  val = -1;
524  ptr = ptr->GetLeft();
525  } else if (key > ptr->m_key) {
526  NEWTON_ASSERT(CompareKeys(ptr->m_key, key) == 1) ;
527  val = 1;
528  ptr = ptr->GetRight();
529  } else {
530  NEWTON_ASSERT(CompareKeys(ptr->m_key, key) == 0) ;
531  elementWasInTree = true;
532  return ptr;
533  }
534  }
535 
536  m_count ++;
537  NEWTON_ASSERT(m_allocator);
538  ptr = new (m_allocator) dgTreeNode(element, key, parent);
539  if (!parent) {
540  m_head = ptr;
541  } else {
542  if (val < 0) {
543  parent->m_left = ptr;
544  } else {
545  parent->m_right = ptr;
546  }
547  }
548 
549  dgTreeNode **const headPtr = (dgTreeNode **) &m_head;
550 // ptr->InsertFixup ((dgRedBackNode**)&m_head);
551  ptr->InsertFixup((dgRedBackNode **)headPtr);
552  return ptr;
553 }
554 
555 template<class OBJECT, class KEY>
556 typename dgTree<OBJECT, KEY>::dgTreeNode *dgTree<OBJECT, KEY>::Insert(const OBJECT &element, KEY key) {
557  bool foundState;
558 
559  dgTreeNode *const node = Insert(element, key, foundState);
560  if (foundState) {
561  return NULL;
562  }
563  return node;
564 }
565 
566 template<class OBJECT, class KEY>
568  dgInt32 val = 0;
569  dgTreeNode *ptr = m_head;
570  dgTreeNode *parent = NULL;
571  while (ptr != NULL) {
572  parent = ptr;
573 // val = CompareKeys (ptr->m_key, key);
574 // if (val < 0) {
575 // ptr = ptr->GetLeft();
576 // } else if (val > 0) {
577 // ptr = ptr->GetRight();
578 // } else {
579 // return NULL;
580 // }
581 
582  if (key < ptr->m_key) {
583  NEWTON_ASSERT(CompareKeys(ptr->m_key, key) == -1) ;
584  val = -1;
585  ptr = ptr->GetLeft();
586  } else if (key > ptr->m_key) {
587  NEWTON_ASSERT(CompareKeys(ptr->m_key, key) == 1) ;
588  val = 1;
589  ptr = ptr->GetRight();
590  } else {
591  NEWTON_ASSERT(CompareKeys(ptr->m_key, key) == 0) ;
592  return NULL;
593  }
594  }
595 
596  m_count ++;
597 
598  ptr = node;
599  ptr->m_key = key;
600  ptr->Initdata(parent);
601 
602  if (!parent) {
603  m_head = ptr;
604  } else {
605  if (val < 0) {
606  parent->m_left = ptr;
607  } else {
608  parent->m_right = ptr;
609  }
610  }
611 
612  dgTreeNode **const headPtr = (dgTreeNode **) &m_head;
613 // ptr->InsertFixup ((dgRedBackNode**)&m_head);
614  ptr->InsertFixup((dgRedBackNode **)headPtr);
615  return ptr;
616 }
617 
618 
619 template<class OBJECT, class KEY>
620 typename dgTree<OBJECT, KEY>::dgTreeNode *dgTree<OBJECT, KEY>::Replace(OBJECT &element, KEY key) {
621  dgTreeNode *parent = NULL;
622  dgTreeNode *ptr = m_head;
623  dgInt32 val = 0;
624  while (ptr != NULL) {
625  parent = ptr;
626 
627  NEWTON_ASSERT(0);
628  val = CompareKeys(ptr->m_key, key);
629  if (val == 0) {
630  ptr->m_info = element;
631  return ptr;
632  }
633  if (val < 0) {
634  ptr = ptr->GetLeft();
635  } else {
636  ptr = ptr->GetRight();
637  }
638  }
639 
640  NEWTON_ASSERT(m_allocator);
641  ptr = new (m_allocator) dgTreeNode(element, key, parent);
642  if (!parent) {
643  m_head = ptr;
644  } else {
645  if (val < 0) {
646  parent->m_left = ptr;
647  } else {
648  parent->m_right = ptr;
649  }
650  }
651 
652  dgTreeNode **const headPtr = (dgTreeNode **) &m_head;
653 // ptr->InsertFixup ((dgRedBackNode**)&m_head);
654  ptr->InsertFixup((dgRedBackNode **)headPtr);
655  return ptr;
656 }
657 
658 
659 template<class OBJECT, class KEY>
661  Unlink(node);
662  dgTreeNode *const ptr = Insert(node, key);
663  NEWTON_ASSERT(ptr);
664  return ptr;
665 }
666 
667 template<class OBJECT, class KEY>
668 typename dgTree<OBJECT, KEY>::dgTreeNode *dgTree<OBJECT, KEY>::ReplaceKey(KEY oldKey, KEY newKey) {
669  dgTreeNode *const node = Find(oldKey);
670  return node ? ReplaceKey(node, newKey) : NULL;
671 }
672 
673 template<class OBJECT, class KEY>
675  m_count --;
676 
677  dgTreeNode **const headPtr = (dgTreeNode **) &m_head;
678  node->Unlink((dgRedBackNode **)headPtr);
679  NEWTON_ASSERT(!Find(node->GetKey()));
680 }
681 
682 
683 template<class OBJECT, class KEY>
685  m_count --;
686  dgTreeNode **const headPtr = (dgTreeNode **) &m_head;
687  node->Remove((dgRedBackNode **)headPtr);
688 }
689 
690 template<class OBJECT, class KEY>
691 void dgTree<OBJECT, KEY>::Remove(KEY key) {
692  dgTreeNode *node;
693 
694  // find node in tree
695  node = Find(key);
696  if (node == NULL) {
697  return;
698  }
699  Remove(node);
700 }
701 
702 template<class OBJECT, class KEY>
704  if (m_head) {
705  m_count = 0;
706  m_head->RemoveAll();
707  m_head = NULL;
708  }
709 }
710 
711 template<class OBJECT, class KEY>
713  return SanityCheck(m_head, 0);
714 }
715 
716 
717 template<class OBJECT, class KEY>
718 bool dgTree<OBJECT, KEY>::SanityCheck(typename dgTree<OBJECT, KEY>::dgTreeNode *const ptr, dgInt32 height) const {
719  if (!ptr) {
720  return true;
721  }
722 
723  if (!ptr->IsInTree()) {
724  return false;
725  }
726 
727  if (ptr->m_left) {
728  if (CompareKeys(ptr->m_key, ptr->GetLeft()->m_key) > 0) {
729  return false;
730  }
731  }
732 
733  if (ptr->m_right) {
734  if (CompareKeys(ptr->m_key, ptr->GetRight()->m_key) < 0) {
735  return false;
736  }
737  }
738 
739  if (ptr->GetColor() == dgTreeNode::BLACK) {
740  height ++;
741  } else if (!((!ptr->m_left || (ptr->m_left->GetColor() == dgTreeNode::BLACK)) &&
742  (!ptr->m_right || (ptr->m_right->GetColor() == dgTreeNode::BLACK)))) {
743  return false;
744  }
745 
746  if (!ptr->m_left && !ptr->m_right) {
747  dgInt32 bh = 0;
748  for (dgTreeNode *x = ptr; x; x = x->GetParent()) {
749  if (x->GetColor() == dgTreeNode::BLACK) {
750  bh ++;
751  }
752  }
753  if (bh != height) {
754  return false;
755  }
756  }
757 
758  if (ptr->m_left && !SanityCheck(ptr->GetLeft(), height)) {
759  return false;
760  }
761 
762  if (ptr->m_right && !SanityCheck(ptr->GetRight(), height)) {
763  return false;
764  }
765  return true;
766 }
767 
768 
769 template<class OBJECT, class KEY>
770 dgInt32 dgTree<OBJECT, KEY>::CompareKeys(const KEY &key0, const KEY &key1) const {
771  if (key1 < key0) {
772  return - 1;
773  }
774  if (key1 > key0) {
775  return 1;
776  }
777  return 0;
778 }
779 
780 template<class OBJECT, class KEY>
782  Swap(m_head, tree.m_head);
783  Swap(m_count, tree.m_count);
784 }
785 
786 //template<class OBJECT, class KEY> dgInt32 dgTree<OBJECT,KEY>::m_size = 0;
787 //template<class OBJECT, class KEY> dgMemoryAllocator* dgTree<OBJECT,KEY>::m_staticAllocator = NULL;
788 
789 
790 #endif
Definition: dgTree.h:90
Definition: dgTree.h:88
Definition: dgTree.h:146
Definition: dgMemory.h:80
Definition: dgTree.h:35