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