FBX C++ API Reference
fbxredblacktree.h
Go to the documentation of this file.
1 /****************************************************************************************
2 
3  Copyright (C) 2015 Autodesk, Inc.
4  All rights reserved.
5 
6  Use of this software is subject to the terms of the Autodesk license agreement
7  provided at the time of installation or download, or which otherwise accompanies
8  this software in either electronic or hard copy form.
9 
10 ****************************************************************************************/
11 
13 #ifndef _FBXSDK_CORE_BASE_REDBLACKTREE_H_
14 #define _FBXSDK_CORE_BASE_REDBLACKTREE_H_
15 
16 #include <fbxsdk/fbxsdk_def.h>
17 
20 
21 #include <fbxsdk/fbxsdk_nsbegin.h>
22 
23 /*****************************************************************************************************************************
24 ** WARNING! Anything beyond these lines is for internal use, may not be documented and is subject to change without notice! **
25 *****************************************************************************************************************************/
26 #ifndef DOXYGEN_SHOULD_SKIP_THIS
27 
28 template <typename RecordType> class FbxRedBlackConstIterator;
29 
30 template <typename RecordType> class FbxRedBlackIterator
31 {
32 public:
33  FbxRedBlackIterator() : mRecord(0) {}
34  FbxRedBlackIterator(RecordType* pRecord) : mRecord(pRecord) {}
35  FbxRedBlackIterator(const FbxRedBlackIterator<RecordType>& pV) : mRecord(pV.mRecord) {}
36 
37  FbxRedBlackIterator& operator++()
38  {
39  FBX_ASSERT( mRecord != NULL );
40  mRecord = mRecord->Successor();
41  return *this;
42  }
43 
44  const FbxRedBlackIterator operator++(int)
45  {
46  FbxRedBlackIterator t(*this);
47  operator++();
48  return t;
49  }
50 
51  FbxRedBlackIterator& operator+=(int pCount)
52  {
53  FBX_ASSERT( mRecord != NULL );
54  for( int i = 0; i < pCount; ++i )
55  {
56  if( !mRecord ) break;
57  mRecord = mRecord->Successor();
58  }
59  return *this;
60  }
61 
62  FbxRedBlackIterator& operator--()
63  {
64  FBX_ASSERT( mRecord );
65  mRecord = mRecord->Predecessor();
66  return *this;
67  }
68 
69  const FbxRedBlackIterator operator--(int)
70  {
71  FbxRedBlackIterator t(*this);
72  operator--();
73  return t;
74  }
75 
76  FbxRedBlackIterator& operator-=(int pCount)
77  {
78  FBX_ASSERT( mRecord != NULL );
79  for( int i = 0; i < pCount; ++i )
80  {
81  if( !mRecord ) break;
82  mRecord = mRecord->Predecessor();
83  }
84  return *this;
85  }
86 
87  const RecordType& operator*() const
88  {
89  FBX_ASSERT( mRecord );
90 
91  return *mRecord;
92  }
93 
94  RecordType& operator*()
95  {
96  FBX_ASSERT( mRecord );
97 
98  return *mRecord;
99  }
100 
101  const RecordType* operator->() const
102  {
103  FBX_ASSERT( mRecord );
104 
105  return mRecord;
106  }
107 
108  RecordType* operator->()
109  {
110  FBX_ASSERT( mRecord );
111 
112  return mRecord;
113  }
114 
115  inline bool operator==(const FbxRedBlackIterator& pOther) const
116  {
117  return mRecord == pOther.mRecord;
118  }
119 
120  inline bool operator !=(const FbxRedBlackIterator& pOther) const
121  {
122  return mRecord != pOther.mRecord;
123  }
124 
125 protected:
126  RecordType* mRecord;
127 
128  friend class FbxRedBlackConstIterator<RecordType>;
129 };
130 
131 template <typename RecordType> class FbxRedBlackConstIterator
132 {
133 public:
134  FbxRedBlackConstIterator() : mRecord(0) {}
135  FbxRedBlackConstIterator(const RecordType* pRecord) : mRecord(pRecord) {}
136  FbxRedBlackConstIterator(const FbxRedBlackIterator<RecordType>& pV) : mRecord(pV.mRecord) {}
137  FbxRedBlackConstIterator(const FbxRedBlackConstIterator<RecordType>& pV) : mRecord(pV.mRecord) {}
138 
139  FbxRedBlackConstIterator & operator++()
140  {
141  FBX_ASSERT( mRecord != NULL );
142  mRecord = mRecord->Successor();
143  return *this;
144  }
145 
146  const FbxRedBlackConstIterator operator++(int)
147  {
148  FbxRedBlackConstIterator t(*this);
149  operator++();
150  return t;
151  }
152 
153  FbxRedBlackConstIterator& operator+=(int pCount)
154  {
155  FBX_ASSERT( mRecord != NULL );
156  for( int i = 0; i < pCount; ++i )
157  {
158  if( !mRecord ) break;
159  mRecord = mRecord->Successor();
160  }
161  return *this;
162  }
163 
164  FbxRedBlackConstIterator & operator--()
165  {
166  FBX_ASSERT( mRecord );
167  mRecord = mRecord->Predecessor();
168  return *this;
169  }
170 
171  const FbxRedBlackConstIterator operator--(int)
172  {
173  FbxRedBlackConstIterator t(*this);
174  operator--();
175  return t;
176  }
177 
178  FbxRedBlackConstIterator& operator-=(int pCount)
179  {
180  FBX_ASSERT( mRecord != NULL );
181  for( int i = 0; i < pCount; ++i )
182  {
183  if( !mRecord ) break;
184  mRecord = mRecord->Predecessor();
185  }
186  return *this;
187  }
188 
189  const RecordType& operator*() const
190  {
191  FBX_ASSERT( mRecord );
192 
193  return *mRecord;
194  }
195 
196  const RecordType& operator*()
197  {
198  FBX_ASSERT( mRecord );
199 
200  return *mRecord;
201  }
202 
203  const RecordType* operator->() const
204  {
205  FBX_ASSERT( mRecord );
206 
207  return mRecord;
208  }
209 
210  const RecordType* operator->()
211  {
212  FBX_ASSERT( mRecord );
213 
214  return mRecord;
215  }
216 
217  inline bool operator==(const FbxRedBlackConstIterator& pOther) const
218  {
219  return mRecord == pOther.mRecord;
220  }
221 
222  inline bool operator !=(const FbxRedBlackConstIterator& pOther) const
223  {
224  return mRecord != pOther.mRecord;
225  }
226 
227 protected:
228  const RecordType* mRecord;
229 
230  friend class FbxRedBlackIterator<RecordType>;
231 };
232 
234 template <typename Type, typename Compare, typename Allocator> class FbxRedBlackTree
235 {
236 public:
237  typedef Type DataType;
238  typedef typename Type::KeyType KeyType;
239  typedef typename Type::ConstKeyType ConstKeyType;
240  typedef typename Type::ValueType ValueType;
241  typedef typename Type::ConstValueType ConstValueType;
242  typedef Allocator AllocatorType;
243 
248  class RecordType
249  {
250  public:
251  inline ConstKeyType& GetKey() const { return mData.GetKey(); }
252  inline ConstValueType& GetValue() const { return mData.GetValue(); }
253  inline ValueType& GetValue() { return mData.GetValue(); }
254 
255  inline const RecordType* Minimum() const
256  {
257  const RecordType* lParent = 0;
258  const RecordType* lNode = this;
259  while (lNode != 0)
260  {
261  lParent = lNode;
262  lNode = lNode->mLeftChild;
263  }
264 
265  return lParent;
266  }
267 
268  inline RecordType* Minimum()
269  {
270  RecordType* lParent = 0;
271  RecordType* lNode = this;
272  while (lNode != 0)
273  {
274  lParent = lNode;
275  lNode = lNode->mLeftChild;
276  }
277 
278  return lParent;
279  }
280 
281  inline const RecordType* Maximum() const
282  {
283  const RecordType* lParent = 0;
284  const RecordType* lNode = this;
285  while (lNode != 0)
286  {
287  lParent = lNode;
288  lNode = lNode->mRightChild;
289  }
290 
291  return lParent;
292  }
293 
294  inline RecordType* Maximum()
295  {
296  RecordType* lParent = 0;
297  RecordType* lNode = this;
298  while (lNode != 0)
299  {
300  lParent = lNode;
301  lNode = lNode->mRightChild;
302  }
303 
304  return lParent;
305  }
306 
307  inline const RecordType* Predecessor() const
308  {
309  if (mLeftChild)
310  {
311  return mLeftChild->Maximum();
312  }
313  else
314  {
315  const RecordType* lParent = mParent;
316  const RecordType* lNode = this;
317 
318  while (lParent && lParent->mLefttChild == lNode)
319  {
320  lNode = lParent;
321  lParent = lParent->mParent;
322  }
323 
324  return lParent;
325  }
326  }
327 
328  inline RecordType* Predecessor()
329  {
330  if (mLeftChild)
331  {
332  return mLeftChild->Maximum();
333  }
334  else
335  {
336  RecordType* lParent = mParent;
337  RecordType* lNode = this;
338 
339  while (lParent && lParent->mLeftChild == lNode)
340  {
341  lNode = lParent;
342  lParent = lParent->mParent;
343  }
344 
345  return lParent;
346  }
347  }
348 
349  inline const RecordType* Successor() const
350  {
351  if (mRightChild)
352  {
353  return mRightChild->Minimum();
354  }
355  else
356  {
357  const RecordType* lParent = mParent;
358  const RecordType* lNode = this;
359 
360  while (lParent && lParent->mRightChild == lNode)
361  {
362  lNode = lParent;
363  lParent = lParent->mParent;
364  }
365 
366  return lParent;
367  }
368  }
369 
370  inline RecordType* Successor()
371  {
372  if (mRightChild)
373  {
374  return mRightChild->Minimum();
375  }
376  else
377  {
378  RecordType* lParent = mParent;
379  RecordType* lNode = this;
380 
381  while (lParent && lParent->mRightChild == lNode)
382  {
383  lNode = lParent;
384  lParent = lParent->mParent;
385  }
386 
387  return lParent;
388  }
389  }
390 
391  inline int GetBlackDepth() { return mBlackDepth; }
392 
393  private:
394  enum ETreeType {eRed, eBlack};
395 
396  inline RecordType(const DataType& pData)
397  : mData(pData)
398  , mParent(0)
399  , mLeftChild(0)
400  , mRightChild(0)
401  , mColor(eRed)
402  , mBlackDepth(0)
403  {
404  }
405 
406  inline RecordType(const RecordType& pRecordType)
407  : mData(pRecordType.mData)
408  , mParent(0)
409  , mLeftChild(0)
410  , mRightChild(0)
411  , mColor(pRecordType.mColor)
412  , mBlackDepth(pRecordType.mBlackDepth)
413  {
414  }
415 
416  DataType mData;
417 
418  friend class FbxRedBlackTree;
419 
420  RecordType* mParent;
421  RecordType* mLeftChild;
422  RecordType* mRightChild;
423  unsigned int mColor:2;
424  unsigned int mBlackDepth:30;
425  };
426 
427 public:
428  typedef FbxRedBlackConstIterator<RecordType> ConstIteratorType;
429  typedef FbxRedBlackIterator<RecordType> IteratorType;
430 
431  inline FbxRedBlackTree() : mRoot(0), mAllocator(sizeof(RecordType)), mSize(0) {}
432  inline FbxRedBlackTree(const FbxRedBlackTree& pTree) : mRoot(0), mAllocator(sizeof(RecordType)), mSize(0) { operator=(pTree); }
433  inline ~FbxRedBlackTree() { Clear(); }
434 
437  inline FbxRedBlackTree& operator=(const FbxRedBlackTree& pTree)
438  {
439  if( this != &pTree )
440  {
441  Clear();
442 
443  if( pTree.mRoot )
444  {
445  void* lBuffer = mAllocator.AllocateRecords();
446  mRoot = new(lBuffer) RecordType(*(pTree.mRoot)); //in-place new won't allocate memory, so it is safe
447  mRoot->mLeftChild = DuplicateSubTree(pTree.mRoot->mLeftChild);
448  mRoot->mRightChild = DuplicateSubTree(pTree.mRoot->mRightChild);
449 
450  if (mRoot->mLeftChild)
451  {
452  mRoot->mLeftChild->mParent = mRoot;
453  }
454 
455  if (mRoot->mRightChild)
456  {
457  mRoot->mRightChild->mParent = mRoot;
458  }
459  }
460  else
461  {
462  FBX_ASSERT( pTree.mSize == 0 );
463  FBX_ASSERT( mRoot == 0 );
464  }
465 
466  mSize = pTree.mSize;
467  }
468 
469  return *this;
470  }
471 
472  inline bool operator==(const FbxRedBlackTree& pTree) const
473  {
474  // Check a few quick shortcuts
475  if( this == &pTree )
476  return true;
477 
478  if( GetSize() != pTree.GetSize() )
479  return false;
480 
481  // Iterator through all nodes; if we reach the end of both iterators at the same
482  // time then we have two iterators that match.
483  ConstIteratorType End;
484  ConstIteratorType Iter1(Minimum());
485  ConstIteratorType Iter2(pTree.Minimum());
486 
487  while( (Iter1 != End) && (Iter2 != End) &&
488  (Iter1->GetKey() == Iter2->GetKey()) &&
489  (Iter1->GetValue() == Iter2->GetValue()) )
490  {
491  ++Iter1;
492  ++Iter2;
493  }
494 
495  return Iter1 == End && Iter2 == End;
496  }
497 
501  inline void Reserve(unsigned int pRecordCount)
502  {
503  mAllocator.Reserve(pRecordCount);
504  }
505 
509  inline int GetSize() const { return mSize; }
510 
511  inline bool Empty() const { return mSize == 0; }
512 
518  inline FbxPair<RecordType*, bool> Insert(const DataType& pData)
519  {
520  Compare lCompareKeys;
521  bool lResult = false;
522  RecordType* lParent = 0;
523  RecordType* lNode = mRoot;
524  while (lNode != 0)
525  {
526  const KeyType& lNodeKey = lNode->GetKey();
527  const KeyType& lDataKey = pData.GetKey();
528 
529  if (lCompareKeys(lNodeKey, lDataKey) < 0)
530  {
531  lParent = lNode;
532  lNode = lNode->mRightChild;
533  }
534  else if (lCompareKeys(lNodeKey, lDataKey) > 0)
535  {
536  lParent = lNode;
537  lNode = lNode->mLeftChild;
538  }
539  else
540  {
541  break;
542  }
543  }
544 
545  if (lNode == 0)
546  {
547  void* lBuffer = mAllocator.AllocateRecords();
548  lNode = new(lBuffer) RecordType(pData); //in-place new won't allocate memory, so it is safe
549  mSize++;
550 
551  FBX_ASSERT(lNode == lBuffer);
552 
553  if (lParent)
554  {
555  if (lCompareKeys(lParent->GetKey(), pData.GetKey()) < 0)
556  {
557  FBX_ASSERT(lParent->mRightChild == 0);
558  lParent->mRightChild = lNode;
559  lNode->mParent = lParent;
560  }
561  else
562  {
563  FBX_ASSERT(lParent->mLeftChild == 0);
564  lParent->mLeftChild = lNode;
565  lNode->mParent = lParent;
566  }
567  }
568  else
569  {
570  mRoot = lNode;
571  }
572 
573  // Fix red black tree property
574  FixNodesAfterInsertion(lNode);
575 
576  lResult = true;
577  }
578 
579  return FbxPair<RecordType*, bool>(lNode, lResult);
580  }
581 
585  inline bool Remove(const KeyType& pKey)
586  {
587  Compare lCompareKeys;
588  bool lResult = false;
589  RecordType* lNode = mRoot;
590  while (lNode != 0)
591  {
592  if (lCompareKeys(lNode->GetKey(), pKey) < 0)
593  {
594  lNode = lNode->mRightChild;
595  }
596  else if (lCompareKeys(lNode->GetKey(), pKey) > 0)
597  {
598  lNode = lNode->mLeftChild;
599  }
600  else
601  {
602  break;
603  }
604  }
605 
606  if (lNode)
607  {
608  RemoveNode(lNode);
609  mSize--;
610  lNode->~RecordType();
611  mAllocator.FreeMemory(lNode);
612 
613  lResult = true;
614  }
615 
616  return lResult;
617  }
618 
621  inline void Clear()
622  {
623  if (mRoot)
624  {
625  ClearSubTree(mRoot->mLeftChild);
626  ClearSubTree(mRoot->mRightChild);
627  mRoot->~RecordType();
628  mAllocator.FreeMemory(mRoot);
629  mRoot = 0;
630  mSize = 0;
631  }
632  }
633 
637  inline const RecordType* Minimum() const
638  {
639  if (0 != mRoot)
640  {
641  return mRoot->Minimum();
642  }
643  else
644  {
645  return 0;
646  }
647  }
648 
652  inline RecordType* Minimum()
653  {
654  if (0 != mRoot)
655  {
656  return mRoot->Minimum();
657  }
658  else
659  {
660  return 0;
661  }
662  }
663 
667  inline const RecordType* Maximum() const
668  {
669  if (0 != mRoot)
670  {
671  return mRoot->Maximum();
672  }
673  else
674  {
675  return 0;
676  }
677  }
678 
682  inline RecordType* Maximum()
683  {
684  if (0 != mRoot)
685  {
686  return mRoot->Maximum();
687  }
688  else
689  {
690  return 0;
691  }
692  }
693 
698  inline const RecordType* Find(const KeyType& pKey) const
699  {
700  Compare lCompareKeys;
701  const RecordType* lNode = mRoot;
702  while (lNode != 0)
703  {
704  if (lCompareKeys(lNode->GetKey(), pKey) < 0)
705  {
706  lNode = lNode->mRightChild;
707  }
708  else if (lCompareKeys(lNode->GetKey(), pKey) > 0)
709  {
710  lNode = lNode->mLeftChild;
711  }
712  else
713  {
714  break;
715  }
716  }
717 
718  return lNode;
719  }
720 
725  inline RecordType* Find(const KeyType& pKey)
726  {
727  Compare lCompareKeys;
728  RecordType* lNode = mRoot;
729  while (lNode != 0)
730  {
731  if (lCompareKeys(lNode->GetKey(), pKey) < 0)
732  {
733  lNode = lNode->mRightChild;
734  }
735  else if (lCompareKeys(lNode->GetKey(), pKey) > 0)
736  {
737  lNode = lNode->mLeftChild;
738  }
739  else
740  {
741  break;
742  }
743  }
744 
745  return lNode;
746  }
747 
752  inline const RecordType* UpperBound(const KeyType& pKey) const
753  {
754  Compare lCompareKeys;
755  const RecordType* lNode = mRoot;
756  const RecordType* lCandidate = 0;
757  while (lNode != 0)
758  {
759  if (lCompareKeys(lNode->GetKey(), pKey) <= 0)
760  {
761  lNode = lNode->mRightChild;
762  }
763  else if (lCompareKeys(lNode->GetKey(), pKey) > 0)
764  {
765  lCandidate = lNode;
766  lNode = lNode->mLeftChild;
767  }
768  }
769 
770  return lCandidate;
771  }
772 
777  inline RecordType* UpperBound(const KeyType& pKey)
778  {
779  Compare lCompareKeys;
780  RecordType* lNode = mRoot;
781  RecordType* lCandidate = 0;
782  while (lNode != 0)
783  {
784  if (lCompareKeys(lNode->GetKey(), pKey) <= 0)
785  {
786  lNode = lNode->mRightChild;
787  }
788  else if (lCompareKeys(lNode->GetKey(), pKey) > 0)
789  {
790  lCandidate = lNode;
791  lNode = lNode->mLeftChild;
792  }
793  }
794 
795  return lCandidate;
796  }
797 
798 protected:
799  RecordType* mRoot;
800  AllocatorType mAllocator;
801  int mSize;
802 
803  inline RecordType* DuplicateSubTree(const RecordType* pNode)
804  {
805  RecordType* lNewSubTree = 0;
806 
807  if (pNode)
808  {
809  void* lBuffer = mAllocator.AllocateRecords();
810  lNewSubTree = new(lBuffer) RecordType(*pNode); //in-place new won't allocate memory, so it is safe
811  lNewSubTree->mLeftChild = DuplicateSubTree(pNode->mLeftChild);
812  lNewSubTree->mRightChild = DuplicateSubTree(pNode->mRightChild);
813 
814  if (lNewSubTree->mLeftChild)
815  {
816  lNewSubTree->mLeftChild->mParent = lNewSubTree;
817  }
818 
819  if (lNewSubTree->mRightChild)
820  {
821  lNewSubTree->mRightChild->mParent = lNewSubTree;
822  }
823  }
824 
825  return lNewSubTree;
826  }
827 
828  inline void FixNodesAfterInsertion(RecordType* pNode)
829  {
830  RecordType* lNode = pNode;
831  bool lDone = false;
832 
833  while (!lDone)
834  {
835  lDone = true;
836 
837  if (lNode->mParent == 0)
838  {
839  lNode->mColor = RecordType::eBlack;
840  }
841  else if (lNode->mParent->mColor == RecordType::eRed)
842  {
843  RecordType* lUncle = 0;
844 
845  if ((lNode->mParent != NULL) && (lNode->mParent->mParent != NULL))
846  {
847  if (lNode->mParent == lNode->mParent->mParent->mLeftChild)
848  {
849  lUncle = lNode->mParent->mParent->mRightChild;
850  }
851  else if (lNode->mParent == lNode->mParent->mParent->mRightChild)
852  {
853  lUncle = lNode->mParent->mParent->mLeftChild;
854  }
855  }
856 
857  // since lNode->mParent is red, lNode->mParent->mParent exists
858 
859  if ((lNode->mParent != NULL) && (lNode->mParent->mParent != NULL))
860  {
861  if (lUncle && lUncle->mColor == RecordType::eRed)
862  {
863  lNode->mParent->mColor = RecordType::eBlack;
864  lUncle->mColor = RecordType::eBlack;
865  lNode->mParent->mParent->mColor = RecordType::eRed;
866  lNode = lNode->mParent->mParent;
867 
868  lDone = false;
869  }
870  else
871  {
872  if ((lNode == lNode->mParent->mRightChild) &&
873  (lNode->mParent == lNode->mParent->mParent->mLeftChild))
874  {
875  LeftRotate(lNode->mParent);
876  lNode = lNode->mLeftChild;
877  }
878  else if ((lNode == lNode->mParent->mLeftChild) &&
879  (lNode->mParent == lNode->mParent->mParent->mRightChild))
880  {
881  RightRotate(lNode->mParent);
882  lNode = lNode->mRightChild;
883  }
884 
885  lNode->mParent->mColor = RecordType::eBlack;
886  lNode->mParent->mParent->mColor = RecordType::eRed;
887  if ((lNode == lNode->mParent->mLeftChild) &&
888  (lNode->mParent == lNode->mParent->mParent->mLeftChild))
889  {
890  RightRotate(lNode->mParent->mParent);
891  }
892  else
893  {
894  LeftRotate(lNode->mParent->mParent);
895  }
896  }
897  }
898  }
899  }
900 
901  mRoot->mColor = RecordType::eBlack;
902  }
903 
904  inline void LeftRotate(RecordType* pNode)
905  {
906  FBX_ASSERT_RETURN(pNode);
907 
908  RecordType* lNode = pNode->mRightChild;
909  FBX_ASSERT_RETURN(lNode);
910 
911  #ifdef _DEBUG
912  RecordType* A = pNode->mLeftChild;
913  RecordType* B = lNode->mLeftChild;
914  RecordType* C = lNode->mRightChild;
915  RecordType* Z = pNode->mParent;
916  #endif
917 
918  pNode->mRightChild = lNode->mLeftChild;
919  if (pNode->mRightChild)
920  {
921  pNode->mRightChild->mParent = pNode;
922  }
923 
924  lNode->mParent = pNode->mParent;
925  if (pNode->mParent == 0)
926  {
927  FBX_ASSERT(mRoot == pNode);
928  mRoot = lNode;
929  }
930  else if (pNode == pNode->mParent->mLeftChild)
931  {
932  pNode->mParent->mLeftChild = lNode;
933  }
934  else
935  {
936  pNode->mParent->mRightChild = lNode;
937  }
938  pNode->mParent = lNode;
939  lNode->mLeftChild = pNode;
940 
941  FBX_ASSERT(pNode->mLeftChild == A);
942  FBX_ASSERT(pNode->mRightChild == B);
943  FBX_ASSERT(pNode->mParent == lNode);
944 
945  FBX_ASSERT(lNode->mLeftChild == pNode);
946  FBX_ASSERT(lNode->mRightChild == C);
947  FBX_ASSERT(lNode->mParent == Z);
948 
949  FBX_ASSERT(A == 0 || A->mParent == pNode);
950  FBX_ASSERT(B == 0 || B->mParent == pNode);
951  FBX_ASSERT(C == 0 || C->mParent == lNode);
952  FBX_ASSERT(Z == 0 || Z->mLeftChild == lNode || Z->mRightChild == lNode);
953  }
954 
955  inline void RightRotate(RecordType* pNode)
956  {
957  RecordType* lNode = pNode->mLeftChild;
958 
959  #ifdef _DEBUG
960  RecordType* A = lNode->mLeftChild;
961  RecordType* B = lNode->mRightChild;
962  RecordType* C = pNode->mRightChild;
963  RecordType* Z = pNode->mParent;
964  #endif
965 
966  pNode->mLeftChild = lNode->mRightChild;
967  if (pNode->mLeftChild)
968  {
969  pNode->mLeftChild->mParent = pNode;
970  }
971 
972  lNode->mParent = pNode->mParent;
973  if (pNode->mParent == 0)
974  {
975  FBX_ASSERT(mRoot == pNode);
976  mRoot = lNode;
977  }
978  else if (pNode == pNode->mParent->mRightChild)
979  {
980  pNode->mParent->mRightChild = lNode;
981  }
982  else
983  {
984  pNode->mParent->mLeftChild = lNode;
985  }
986  pNode->mParent = lNode;
987  lNode->mRightChild = pNode;
988 
989  FBX_ASSERT(lNode->mLeftChild == A);
990  FBX_ASSERT(lNode->mRightChild == pNode);
991  FBX_ASSERT(lNode->mParent == Z);
992 
993  FBX_ASSERT(pNode->mLeftChild == B);
994  FBX_ASSERT(pNode->mRightChild == C);
995  FBX_ASSERT(pNode->mParent == lNode);
996 
997  FBX_ASSERT(A == 0 || A->mParent == lNode);
998  FBX_ASSERT(B == 0 || B->mParent == pNode);
999  FBX_ASSERT(C == 0 || C->mParent == pNode);
1000  FBX_ASSERT(Z == 0 || Z->mLeftChild == lNode || Z->mRightChild == lNode);
1001  }
1002 
1003  inline void RemoveNode(RecordType* pNode)
1004  {
1005  if (pNode->mLeftChild == 0)
1006  {
1007  if (pNode->mRightChild == 0)
1008  {
1009  if (pNode->mParent)
1010  {
1011  if (pNode->mParent->mLeftChild == pNode)
1012  {
1013  pNode->mParent->mLeftChild = 0;
1014  }
1015  else if (pNode->mParent->mRightChild == pNode)
1016  {
1017  pNode->mParent->mRightChild = 0;
1018  }
1019  else
1020  {
1021  FBX_ASSERT_NOW("Node not found in FbxRedBlackTree");
1022  }
1023  }
1024  else
1025  {
1026  FBX_ASSERT(mRoot == pNode);
1027  mRoot = 0;
1028  }
1029 
1030  if (pNode->mColor == RecordType::eBlack)
1031  {
1032  FixNodesAfterRemoval(pNode->mParent, 0);
1033  }
1034  }
1035  else
1036  {
1037  if (pNode->mParent)
1038  {
1039  if (pNode->mParent->mLeftChild == pNode)
1040  {
1041  pNode->mParent->mLeftChild = pNode->mRightChild;
1042  pNode->mRightChild->mParent = pNode->mParent;
1043  }
1044  else if (pNode->mParent->mRightChild == pNode)
1045  {
1046  pNode->mParent->mRightChild = pNode->mRightChild;
1047  pNode->mRightChild->mParent = pNode->mParent;
1048  }
1049  else
1050  {
1051  FBX_ASSERT_NOW("Node not found in FbxRedBlackTree");
1052  }
1053  }
1054  else
1055  {
1056  FBX_ASSERT(mRoot == pNode);
1057  mRoot = pNode->mRightChild;
1058  pNode->mRightChild->mParent = 0;
1059  }
1060 
1061  if (pNode->mColor == RecordType::eBlack)
1062  {
1063  FixNodesAfterRemoval(pNode->mRightChild->mParent, pNode->mRightChild);
1064  }
1065  }
1066  }
1067  else
1068  {
1069  if (pNode->mRightChild == 0)
1070  {
1071  if (pNode->mParent)
1072  {
1073  if (pNode->mParent->mLeftChild == pNode)
1074  {
1075  pNode->mParent->mLeftChild = pNode->mLeftChild;
1076  pNode->mLeftChild->mParent = pNode->mParent;
1077  }
1078  else if (pNode->mParent->mRightChild == pNode)
1079  {
1080  pNode->mParent->mRightChild = pNode->mLeftChild;
1081  pNode->mLeftChild->mParent = pNode->mParent;
1082  }
1083  else
1084  {
1085  FBX_ASSERT_NOW("Node not found in FbxRedBlackTree");
1086  }
1087  }
1088  else
1089  {
1090  FBX_ASSERT(mRoot == pNode);
1091  mRoot = pNode->mLeftChild;
1092  pNode->mLeftChild->mParent = 0;
1093  }
1094 
1095  if (pNode->mColor == RecordType::eBlack)
1096  {
1097  FixNodesAfterRemoval(pNode->mLeftChild->mParent, pNode->mLeftChild);
1098  }
1099  }
1100  else
1101  {
1102  RecordType* lMinRightNode = pNode->mRightChild->Minimum();
1103  RemoveNode(lMinRightNode);
1104 
1105  lMinRightNode->mColor = pNode->mColor;
1106  ReplaceNode(pNode, lMinRightNode);
1107  }
1108  }
1109 
1110  pNode->mParent = 0;
1111  pNode->mLeftChild = 0;
1112  pNode->mRightChild = 0;
1113  }
1114 
1115  inline void ReplaceNode(RecordType* pNodeToReplace, RecordType* pReplacement)
1116  {
1117  pReplacement->mParent = pNodeToReplace->mParent;
1118  if (pNodeToReplace->mParent)
1119  {
1120  if (pNodeToReplace->mParent->mLeftChild == pNodeToReplace)
1121  {
1122  pNodeToReplace->mParent->mLeftChild = pReplacement;
1123  }
1124  else if (pNodeToReplace->mParent->mRightChild == pNodeToReplace)
1125  {
1126  pNodeToReplace->mParent->mRightChild = pReplacement;
1127  }
1128  }
1129  else
1130  {
1131  FBX_ASSERT(mRoot == pNodeToReplace);
1132  mRoot = pReplacement;
1133  }
1134 
1135  pReplacement->mLeftChild = pNodeToReplace->mLeftChild;
1136  if (pReplacement->mLeftChild)
1137  {
1138  pReplacement->mLeftChild->mParent = pReplacement;
1139  }
1140 
1141  pReplacement->mRightChild = pNodeToReplace->mRightChild;
1142  if (pReplacement->mRightChild)
1143  {
1144  pReplacement->mRightChild->mParent = pReplacement;
1145  }
1146  }
1147 
1148  inline RecordType* Sibling(const RecordType* pParent, const RecordType* pNode) const
1149  {
1150  if (pParent)
1151  {
1152  if (pParent->mLeftChild == pNode)
1153  {
1154  return pParent->mRightChild;
1155  }
1156  else if (pParent->mRightChild == pNode)
1157  {
1158  return pParent->mLeftChild;
1159  }
1160  }
1161 
1162  return 0;
1163  }
1164 
1165  inline bool IsBlack(const RecordType* pNode)
1166  {
1167  return ((pNode == 0) || (pNode->mColor == RecordType::eBlack));
1168  }
1169 
1170  inline void FixNodesAfterRemoval(RecordType* pParent, RecordType* pNode)
1171  {
1172  RecordType* lParent = pParent;
1173  RecordType* lNode = pNode;
1174  bool lDone = false;
1175 
1176  while (!lDone)
1177  {
1178  lDone = true;
1179 
1180  if (!IsBlack(lNode))
1181  {
1182  lNode->mColor = RecordType::eBlack;
1183  }
1184  else if (lParent != NULL)
1185  {
1186  RecordType* lSibling = Sibling(lParent, lNode);
1187 
1188  if (!IsBlack(lSibling))
1189  {
1190  lParent->mColor = RecordType::eRed;
1191  lSibling->mColor = RecordType::eBlack;
1192  if (lNode == lParent->mLeftChild)
1193  {
1194  LeftRotate(lParent);
1195  }
1196  else
1197  {
1198  RightRotate(lParent);
1199  }
1200 
1201  // update sibling: it may have change after rotation
1202  // parent was not affected by this rotation
1203  lSibling = Sibling(lParent, lNode);
1204  }
1205 
1206  /* check this for null sibling */
1207  if (lSibling &&
1208  IsBlack(lParent) &&
1209  IsBlack(lSibling) &&
1210  IsBlack(lSibling->mLeftChild) &&
1211  IsBlack(lSibling->mRightChild))
1212  {
1213  lSibling->mColor = RecordType::eRed;
1214  lNode = lParent;
1215  lParent = lParent->mParent;
1216  lDone = false;
1217  }
1218  else
1219  {
1220  if (!IsBlack(lParent) &&
1221  IsBlack(lSibling) &&
1222  ((lSibling == 0) || IsBlack(lSibling->mLeftChild)) &&
1223  ((lSibling == 0) || IsBlack(lSibling->mRightChild)))
1224  {
1225  if (lSibling)
1226  {
1227  lSibling->mColor = RecordType::eRed;
1228  }
1229  lParent->mColor = RecordType::eBlack;
1230  }
1231  else if( lSibling != 0 )
1232  {
1233  if ((lNode == lParent->mLeftChild) &&
1234  IsBlack(lSibling) &&
1235  !IsBlack(lSibling->mLeftChild) &&
1236  IsBlack(lSibling->mRightChild))
1237  {
1238  lSibling->mColor = RecordType::eRed;
1239  lSibling->mLeftChild->mColor = RecordType::eBlack;
1240  RightRotate(lSibling);
1241  }
1242  else if ((lNode == lParent->mRightChild) &&
1243  IsBlack(lSibling) &&
1244  IsBlack(lSibling->mLeftChild) &&
1245  !IsBlack(lSibling->mRightChild))
1246  {
1247  lSibling->mColor = RecordType::eRed;
1248  lSibling->mRightChild->mColor = RecordType::eBlack;
1249  LeftRotate(lSibling);
1250  }
1251 
1252  // update sibling: it may have change after rotation
1253  lSibling = Sibling(lParent, lNode);
1254  FBX_ASSERT(lSibling != 0 && lParent != 0); // lSibling is now
1255  // the former red
1256  // child of the
1257  // former sibling
1258 
1259  if( lSibling != 0 && lParent != 0 )
1260  {
1261  lSibling->mColor = lParent->mColor;
1262  lParent->mColor = RecordType::eBlack;
1263  if (lNode == lParent->mLeftChild)
1264  {
1265  if (lSibling->mRightChild)
1266  {
1267  lSibling->mRightChild->mColor = RecordType::eBlack;
1268  }
1269  LeftRotate(lParent);
1270  }
1271  else
1272  {
1273  if (lSibling->mLeftChild)
1274  {
1275  lSibling->mLeftChild->mColor = RecordType::eBlack;
1276  }
1277  RightRotate(lParent);
1278  }
1279  }
1280  }
1281  }
1282  }
1283  }
1284 
1285  if (mRoot)
1286  {
1287  mRoot->mColor = RecordType::eBlack;
1288  }
1289  }
1290 
1291  inline void ClearSubTree(RecordType* pNode)
1292  {
1293  if (pNode)
1294  {
1295  ClearSubTree(pNode->mLeftChild);
1296  ClearSubTree(pNode->mRightChild);
1297  pNode->~RecordType();
1298  mAllocator.FreeMemory(pNode);
1299  }
1300  }
1301 
1302  inline int GetSubTreeSize(RecordType* pNode) const
1303  {
1304  if (pNode)
1305  {
1306  return GetSubTreeSize(pNode->mLeftChild) + GetSubTreeSize(pNode->mRightChild) + 1;
1307  }
1308  else
1309  {
1310  return 0;
1311  }
1312  }
1313 
1314 #if 0
1315  inline void IsSane()
1316  {
1317  FBX_ASSERT((mRoot == 0) || (mRoot->mColor == RecordType::eBlack));
1318  FBX_ASSERT(((mRoot == 0) && (mSize == 0)) || (mRoot != 0) && (mSize != 0));
1319  IsSubTreeSane(mRoot);
1320 
1321  ComputeBlackDepth(mRoot, 0);
1322 
1323  RecordType* lNode = mRoot;
1324  unsigned int lLeafBlackDepth = 0;
1325  while (lNode)
1326  {
1327  if (lNode->mLeftChild == 0)
1328  {
1329  lLeafBlackDepth = lNode->mBlackDepth + ((lNode->mColor == RecordType::eBlack) ? 1 : 0);
1330  }
1331 
1332  lNode = lNode->mLeftChild;
1333  }
1334 
1335  CheckLeavesBlackDepth(mRoot, lLeafBlackDepth);
1336  }
1337 
1338  inline void IsSubTreeSane(const RecordType* pNode) const
1339  {
1340  Compare lCompareKeys;
1341 
1342  if (pNode)
1343  {
1344  FBX_ASSERT(pNode != pNode->mParent);
1345  FBX_ASSERT(pNode != pNode->mLeftChild);
1346  FBX_ASSERT(pNode != pNode->mRightChild);
1347 
1348  // Check for two consecutive red nodes
1349  FBX_ASSERT((pNode->mColor == RecordType::eBlack) ||
1350  (pNode->mLeftChild == NULL) ||
1351  (pNode->mLeftChild->mColor == RecordType::eBlack));
1352 
1353  FBX_ASSERT((pNode->mColor == RecordType::eBlack) ||
1354  (pNode->mRightChild == NULL) ||
1355  (pNode->mRightChild->mColor == RecordType::eBlack));
1356 
1357  // Check key ordering
1358  FBX_ASSERT((pNode->mLeftChild == 0 ||
1359  lCompareKeys(pNode->GetKey(), pNode->mLeftChild->GetKey()) > 0));
1360 
1361  FBX_ASSERT((pNode->mRightChild == 0 ||
1362  lCompareKeys(pNode->GetKey(), pNode->mRightChild->GetKey()) < 0));
1363 
1364  IsSubTreeSane(pNode->mLeftChild);
1365  IsSubTreeSane(pNode->mRightChild);
1366  }
1367  }
1368 
1369  inline void ComputeBlackDepth(RecordType* pNode, unsigned int pDepth)
1370  {
1371  if( pNode )
1372  {
1373  pNode->mBlackDepth = pDepth;
1374  if( pNode->mColor == RecordType::eBlack )
1375  {
1376  pDepth++;
1377  }
1378  ComputeBlackDepth(pNode->mLeftChild, pDepth);
1379  ComputeBlackDepth(pNode->mRightChild, pDepth);
1380  }
1381  }
1382 
1383  inline void CheckLeavesBlackDepth(RecordType* pNode, unsigned int pBlackDepth)
1384  {
1385  if( pNode )
1386  {
1387  if( pNode->mLeftChild == 0 || pNode->mRightChild == 0 )
1388  {
1389  FBX_ASSERT((pNode->mBlackDepth + ((pNode->mColor == RecordType::eBlack) ? 1 : 0)) == pBlackDepth);
1390  }
1391  CheckLeavesBlackDepth(pNode->mLeftChild, pBlackDepth);
1392  CheckLeavesBlackDepth(pNode->mRightChild, pBlackDepth);
1393  }
1394  }
1395 #endif
1396 };
1397 
1398 #endif /* !DOXYGEN_SHOULD_SKIP_THIS *****************************************************************************************/
1399 
1400 #include <fbxsdk/fbxsdk_nsend.h>
1401 
1402 #endif /*_FBXSDK_CORE_BASE_REDBLACKTREE_H_ */
FBX SDK environment definition.
#define NULL
Definition: fbxarch.h:213
This class template holds a pair of objects.
Definition: fbxpair.h:22