Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1700 lines
44 KiB

  1. //========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $Header: $
  6. // $NoKeywords: $
  7. //=============================================================================//
  8. #ifndef UTLRBTREE_H
  9. #define UTLRBTREE_H
  10. #include "tier1/utlmemory.h"
  11. #include "tier1/utlfixedmemory.h"
  12. #include "tier1/utlblockmemory.h"
  13. // This is a useful macro to iterate from start to end in order in a map
  14. #define FOR_EACH_UTLRBTREE( treeName, iteratorName ) \
  15. for ( int iteratorName = treeName.FirstInorder(); (treeName).IsUtlRBTree && iteratorName != treeName.InvalidIndex(); iteratorName = treeName.NextInorder( iteratorName ) )
  16. //-----------------------------------------------------------------------------
  17. // Tool to generate a default compare function for any type that implements
  18. // operator<, including all simple types
  19. //-----------------------------------------------------------------------------
  20. template <typename T >
  21. class CDefOps
  22. {
  23. public:
  24. static bool LessFunc( const T &lhs, const T &rhs ) { return ( lhs < rhs ); }
  25. };
  26. #define DefLessFunc( type ) CDefOps< type >::LessFunc
  27. //-------------------------------------
  28. template <typename T>
  29. class CDefLess
  30. {
  31. public:
  32. CDefLess() {}
  33. CDefLess( int i ) {}
  34. inline bool operator()( const T &lhs, const T &rhs ) const { return ( lhs < rhs ); }
  35. inline bool operator!() const { return false; }
  36. };
  37. //-------------------------------------
  38. inline bool StringLessThan( const char * const &lhs, const char * const &rhs) {
  39. if ( !lhs ) return false;
  40. if ( !rhs ) return true;
  41. return ( strcmp( lhs, rhs) < 0 );
  42. }
  43. inline bool CaselessStringLessThan( const char * const &lhs, const char * const &rhs ) {
  44. if ( !lhs ) return false;
  45. if ( !rhs ) return true;
  46. return ( stricmp( lhs, rhs) < 0 );
  47. }
  48. // Same as CaselessStringLessThan, but it ignores differences in / and \.
  49. inline bool CaselessStringLessThanIgnoreSlashes( const char * const &lhs, const char * const &rhs )
  50. {
  51. const char *pa = lhs;
  52. const char *pb = rhs;
  53. while ( *pa && *pb )
  54. {
  55. char a = *pa;
  56. char b = *pb;
  57. // Check for dir slashes.
  58. if ( a == '/' || a == '\\' )
  59. {
  60. if ( b != '/' && b != '\\' )
  61. return ('/' < b);
  62. }
  63. else
  64. {
  65. if ( a >= 'a' && a <= 'z' )
  66. a = 'A' + (a - 'a');
  67. if ( b >= 'a' && b <= 'z' )
  68. b = 'A' + (b - 'a');
  69. if ( a > b )
  70. return false;
  71. else if ( a < b )
  72. return true;
  73. }
  74. ++pa;
  75. ++pb;
  76. }
  77. // Filenames also must be the same length.
  78. if ( *pa != *pb )
  79. {
  80. // If pa shorter than pb then it's "less"
  81. return ( !*pa );
  82. }
  83. return false;
  84. }
  85. //-------------------------------------
  86. // inline these two templates to stop multiple definitions of the same code
  87. template <> inline bool CDefOps<const char *>::LessFunc( const char * const &lhs, const char * const &rhs ) { return StringLessThan( lhs, rhs ); }
  88. template <> inline bool CDefOps<char *>::LessFunc( char * const &lhs, char * const &rhs ) { return StringLessThan( lhs, rhs ); }
  89. //-------------------------------------
  90. template <typename RBTREE_T>
  91. void SetDefLessFunc( RBTREE_T &RBTree )
  92. {
  93. RBTree.SetLessFunc( DefLessFunc( typename RBTREE_T::KeyType_t ) );
  94. }
  95. // For use with FindClosest
  96. // Move these to a common area if anyone else ever uses them
  97. enum CompareOperands_t
  98. {
  99. k_EEqual = 0x1,
  100. k_EGreaterThan = 0x2,
  101. k_ELessThan = 0x4,
  102. k_EGreaterThanOrEqualTo = k_EGreaterThan | k_EEqual,
  103. k_ELessThanOrEqualTo = k_ELessThan | k_EEqual,
  104. };
  105. //-----------------------------------------------------------------------------
  106. // A red-black binary search tree
  107. //-----------------------------------------------------------------------------
  108. template < class I >
  109. struct UtlRBTreeLinks_t
  110. {
  111. I m_Left;
  112. I m_Right;
  113. I m_Parent;
  114. I m_Tag;
  115. };
  116. template < class T, class I >
  117. struct UtlRBTreeNode_t : public UtlRBTreeLinks_t< I >
  118. {
  119. T m_Data;
  120. };
  121. template < class T, class I = unsigned short, typename L = bool (*)( const T &, const T & ), class M = CUtlMemory< UtlRBTreeNode_t< T, I >, I > >
  122. class CUtlRBTree
  123. {
  124. public:
  125. typedef T KeyType_t;
  126. typedef T ElemType_t;
  127. typedef I IndexType_t;
  128. enum { IsUtlRBTree = true }; // Used to match this at compiletime
  129. // Less func typedef
  130. // Returns true if the first parameter is "less" than the second
  131. typedef L LessFunc_t;
  132. // constructor, destructor
  133. // Left at growSize = 0, the memory will first allocate 1 element and double in size
  134. // at each increment.
  135. // LessFunc_t is required, but may be set after the constructor using SetLessFunc() below
  136. explicit CUtlRBTree( int growSize = 0, int initSize = 0, const LessFunc_t &lessfunc = 0 );
  137. explicit CUtlRBTree( const LessFunc_t &lessfunc );
  138. ~CUtlRBTree( );
  139. void EnsureCapacity( int num );
  140. void CopyFrom( const CUtlRBTree<T, I, L, M> &other );
  141. // gets particular elements
  142. T& Element( I i );
  143. T const &Element( I i ) const;
  144. T& operator[]( I i );
  145. T const &operator[]( I i ) const;
  146. // Gets the root
  147. I Root() const;
  148. // Num elements
  149. unsigned int Count() const;
  150. // Max "size" of the vector
  151. // it's not generally safe to iterate from index 0 to MaxElement()-1 (you could do this as a potential
  152. // iteration optimization, IF CUtlMemory is the allocator, and IF IsValidIndex() is tested for each element...
  153. // but this should be implemented inside the CUtlRBTree iteration API, if anywhere)
  154. I MaxElement() const;
  155. // Gets the children
  156. I Parent( I i ) const;
  157. I LeftChild( I i ) const;
  158. I RightChild( I i ) const;
  159. // Tests if a node is a left or right child
  160. bool IsLeftChild( I i ) const;
  161. bool IsRightChild( I i ) const;
  162. // Tests if root or leaf
  163. bool IsRoot( I i ) const;
  164. bool IsLeaf( I i ) const;
  165. // Checks if a node is valid and in the tree
  166. bool IsValidIndex( I i ) const;
  167. // Checks if the tree as a whole is valid
  168. bool IsValid() const;
  169. // Invalid index
  170. static I InvalidIndex();
  171. // returns the tree depth (not a very fast operation)
  172. int Depth( I node ) const;
  173. int Depth() const;
  174. // Sets the less func
  175. void SetLessFunc( const LessFunc_t &func );
  176. // Allocation method
  177. I NewNode();
  178. // Insert method (inserts in order)
  179. // NOTE: the returned 'index' will be valid as long as the element remains in the tree
  180. // (other elements being added/removed will not affect it)
  181. I Insert( T const &insert );
  182. void Insert( const T *pArray, int nItems );
  183. I InsertIfNotFound( T const &insert );
  184. // Find method
  185. I Find( T const &search ) const;
  186. // FindFirst method ( finds first inorder if there are duplicates )
  187. I FindFirst( T const &search ) const;
  188. // First element >= key
  189. I FindClosest( T const &search, CompareOperands_t eFindCriteria ) const;
  190. // Remove methods
  191. void RemoveAt( I i );
  192. bool Remove( T const &remove );
  193. void RemoveAll( );
  194. void Purge();
  195. // Allocation, deletion
  196. void FreeNode( I i );
  197. // Iteration
  198. I FirstInorder() const;
  199. I NextInorder( I i ) const;
  200. I PrevInorder( I i ) const;
  201. I LastInorder() const;
  202. I FirstPreorder() const;
  203. I NextPreorder( I i ) const;
  204. I PrevPreorder( I i ) const;
  205. I LastPreorder( ) const;
  206. I FirstPostorder() const;
  207. I NextPostorder( I i ) const;
  208. // If you change the search key, this can be used to reinsert the
  209. // element into the tree.
  210. void Reinsert( I elem );
  211. // swap in place
  212. void Swap( CUtlRBTree< T, I, L > &that );
  213. private:
  214. // Can't copy the tree this way!
  215. CUtlRBTree<T, I, L, M>& operator=( const CUtlRBTree<T, I, L, M> &other );
  216. protected:
  217. enum NodeColor_t
  218. {
  219. RED = 0,
  220. BLACK
  221. };
  222. typedef UtlRBTreeNode_t< T, I > Node_t;
  223. typedef UtlRBTreeLinks_t< I > Links_t;
  224. // Sets the children
  225. void SetParent( I i, I parent );
  226. void SetLeftChild( I i, I child );
  227. void SetRightChild( I i, I child );
  228. void LinkToParent( I i, I parent, bool isLeft );
  229. // Gets at the links
  230. Links_t const &Links( I i ) const;
  231. Links_t &Links( I i );
  232. // Checks if a link is red or black
  233. bool IsRed( I i ) const;
  234. bool IsBlack( I i ) const;
  235. // Sets/gets node color
  236. NodeColor_t Color( I i ) const;
  237. void SetColor( I i, NodeColor_t c );
  238. // operations required to preserve tree balance
  239. void RotateLeft(I i);
  240. void RotateRight(I i);
  241. void InsertRebalance(I i);
  242. void RemoveRebalance(I i);
  243. // Insertion, removal
  244. I InsertAt( I parent, bool leftchild );
  245. // copy constructors not allowed
  246. CUtlRBTree( CUtlRBTree<T, I, L, M> const &tree );
  247. // Inserts a node into the tree, doesn't copy the data in.
  248. void FindInsertionPosition( T const &insert, I &parent, bool &leftchild );
  249. // Remove and add back an element in the tree.
  250. void Unlink( I elem );
  251. void Link( I elem );
  252. // Used for sorting.
  253. LessFunc_t m_LessFunc;
  254. M m_Elements;
  255. I m_Root;
  256. I m_NumElements;
  257. I m_FirstFree;
  258. typename M::Iterator_t m_LastAlloc; // the last index allocated
  259. Node_t* m_pElements;
  260. FORCEINLINE M const &Elements( void ) const
  261. {
  262. return m_Elements;
  263. }
  264. void ResetDbgInfo()
  265. {
  266. m_pElements = (Node_t*)m_Elements.Base();
  267. }
  268. };
  269. // this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice
  270. template < class T, class I = int, typename L = bool (*)( const T &, const T & ) >
  271. class CUtlFixedRBTree : public CUtlRBTree< T, I, L, CUtlFixedMemory< UtlRBTreeNode_t< T, I > > >
  272. {
  273. public:
  274. typedef L LessFunc_t;
  275. CUtlFixedRBTree( int growSize = 0, int initSize = 0, const LessFunc_t &lessfunc = 0 )
  276. : CUtlRBTree< T, I, L, CUtlFixedMemory< UtlRBTreeNode_t< T, I > > >( growSize, initSize, lessfunc ) {}
  277. CUtlFixedRBTree( const LessFunc_t &lessfunc )
  278. : CUtlRBTree< T, I, L, CUtlFixedMemory< UtlRBTreeNode_t< T, I > > >( lessfunc ) {}
  279. typedef CUtlRBTree< T, I, L, CUtlFixedMemory< UtlRBTreeNode_t< T, I > > > BaseClass;
  280. bool IsValidIndex( I i ) const
  281. {
  282. if ( !BaseClass::Elements().IsIdxValid( i ) )
  283. return false;
  284. #ifdef _DEBUG // it's safe to skip this here, since the only way to get indices after m_LastAlloc is to use MaxElement()
  285. if ( BaseClass::Elements().IsIdxAfter( i, this->m_LastAlloc ) )
  286. {
  287. Assert( 0 );
  288. return false; // don't read values that have been allocated, but not constructed
  289. }
  290. #endif
  291. return LeftChild(i) != i;
  292. }
  293. protected:
  294. void ResetDbgInfo() {}
  295. private:
  296. // this doesn't make sense for fixed rbtrees, since there's no useful max pointer, and the index space isn't contiguous anyways
  297. I MaxElement() const;
  298. };
  299. // this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice
  300. template < class T, class I = unsigned short, typename L = bool (*)( const T &, const T & ) >
  301. class CUtlBlockRBTree : public CUtlRBTree< T, I, L, CUtlBlockMemory< UtlRBTreeNode_t< T, I >, I > >
  302. {
  303. public:
  304. typedef L LessFunc_t;
  305. CUtlBlockRBTree( int growSize = 0, int initSize = 0, const LessFunc_t &lessfunc = 0 )
  306. : CUtlRBTree< T, I, L, CUtlBlockMemory< UtlRBTreeNode_t< T, I >, I > >( growSize, initSize, lessfunc ) {}
  307. CUtlBlockRBTree( const LessFunc_t &lessfunc )
  308. : CUtlRBTree< T, I, L, CUtlBlockMemory< UtlRBTreeNode_t< T, I >, I > >( lessfunc ) {}
  309. protected:
  310. void ResetDbgInfo() {}
  311. };
  312. //-----------------------------------------------------------------------------
  313. // constructor, destructor
  314. //-----------------------------------------------------------------------------
  315. template < class T, class I, typename L, class M >
  316. inline CUtlRBTree<T, I, L, M>::CUtlRBTree( int growSize, int initSize, const LessFunc_t &lessfunc ) :
  317. m_LessFunc( lessfunc ),
  318. m_Elements( growSize, initSize ),
  319. m_Root( InvalidIndex() ),
  320. m_NumElements( 0 ),
  321. m_FirstFree( InvalidIndex() ),
  322. m_LastAlloc( m_Elements.InvalidIterator() )
  323. {
  324. ResetDbgInfo();
  325. }
  326. template < class T, class I, typename L, class M >
  327. inline CUtlRBTree<T, I, L, M>::CUtlRBTree( const LessFunc_t &lessfunc ) :
  328. m_Elements( 0, 0 ),
  329. m_LessFunc( lessfunc ),
  330. m_Root( InvalidIndex() ),
  331. m_NumElements( 0 ),
  332. m_FirstFree( InvalidIndex() ),
  333. m_LastAlloc( m_Elements.InvalidIterator() )
  334. {
  335. ResetDbgInfo();
  336. }
  337. template < class T, class I, typename L, class M >
  338. inline CUtlRBTree<T, I, L, M>::~CUtlRBTree()
  339. {
  340. Purge();
  341. }
  342. template < class T, class I, typename L, class M >
  343. inline void CUtlRBTree<T, I, L, M>::EnsureCapacity( int num )
  344. {
  345. m_Elements.EnsureCapacity( num );
  346. }
  347. template < class T, class I, typename L, class M >
  348. inline void CUtlRBTree<T, I, L, M>::CopyFrom( const CUtlRBTree<T, I, L, M> &other )
  349. {
  350. Purge();
  351. m_Elements.EnsureCapacity( other.m_Elements.Count() );
  352. memcpy( m_Elements.Base(), other.m_Elements.Base(), other.m_Elements.Count() * sizeof( UtlRBTreeNode_t< T, I > ) );
  353. m_LessFunc = other.m_LessFunc;
  354. m_Root = other.m_Root;
  355. m_NumElements = other.m_NumElements;
  356. m_FirstFree = other.m_FirstFree;
  357. m_LastAlloc = other.m_LastAlloc;
  358. ResetDbgInfo();
  359. }
  360. //-----------------------------------------------------------------------------
  361. // gets particular elements
  362. //-----------------------------------------------------------------------------
  363. template < class T, class I, typename L, class M >
  364. inline T &CUtlRBTree<T, I, L, M>::Element( I i )
  365. {
  366. Assert( IsValidIndex( i ) );
  367. return m_Elements[i].m_Data;
  368. }
  369. template < class T, class I, typename L, class M >
  370. inline T const &CUtlRBTree<T, I, L, M>::Element( I i ) const
  371. {
  372. Assert( IsValidIndex( i ) );
  373. return m_Elements[i].m_Data;
  374. }
  375. template < class T, class I, typename L, class M >
  376. inline T &CUtlRBTree<T, I, L, M>::operator[]( I i )
  377. {
  378. return Element(i);
  379. }
  380. template < class T, class I, typename L, class M >
  381. inline T const &CUtlRBTree<T, I, L, M>::operator[]( I i ) const
  382. {
  383. return Element(i);
  384. }
  385. //-----------------------------------------------------------------------------
  386. //
  387. // various accessors
  388. //
  389. //-----------------------------------------------------------------------------
  390. //-----------------------------------------------------------------------------
  391. // Gets the root
  392. //-----------------------------------------------------------------------------
  393. template < class T, class I, typename L, class M >
  394. inline I CUtlRBTree<T, I, L, M>::Root() const
  395. {
  396. return m_Root;
  397. }
  398. //-----------------------------------------------------------------------------
  399. // Num elements
  400. //-----------------------------------------------------------------------------
  401. template < class T, class I, typename L, class M >
  402. inline unsigned int CUtlRBTree<T, I, L, M>::Count() const
  403. {
  404. return (unsigned int)m_NumElements;
  405. }
  406. //-----------------------------------------------------------------------------
  407. // Max "size" of the vector
  408. //-----------------------------------------------------------------------------
  409. template < class T, class I, typename L, class M >
  410. inline I CUtlRBTree<T, I, L, M>::MaxElement() const
  411. {
  412. return ( I )m_Elements.NumAllocated();
  413. }
  414. //-----------------------------------------------------------------------------
  415. // Gets the children
  416. //-----------------------------------------------------------------------------
  417. template < class T, class I, typename L, class M >
  418. inline I CUtlRBTree<T, I, L, M>::Parent( I i ) const
  419. {
  420. return i != InvalidIndex() ? m_Elements[i].m_Parent : InvalidIndex();
  421. }
  422. template < class T, class I, typename L, class M >
  423. inline I CUtlRBTree<T, I, L, M>::LeftChild( I i ) const
  424. {
  425. return i != InvalidIndex() ? m_Elements[i].m_Left : InvalidIndex();
  426. }
  427. template < class T, class I, typename L, class M >
  428. inline I CUtlRBTree<T, I, L, M>::RightChild( I i ) const
  429. {
  430. return i != InvalidIndex() ? m_Elements[i].m_Right : InvalidIndex();
  431. }
  432. //-----------------------------------------------------------------------------
  433. // Tests if a node is a left or right child
  434. //-----------------------------------------------------------------------------
  435. template < class T, class I, typename L, class M >
  436. inline bool CUtlRBTree<T, I, L, M>::IsLeftChild( I i ) const
  437. {
  438. return LeftChild(Parent(i)) == i;
  439. }
  440. template < class T, class I, typename L, class M >
  441. inline bool CUtlRBTree<T, I, L, M>::IsRightChild( I i ) const
  442. {
  443. return RightChild(Parent(i)) == i;
  444. }
  445. //-----------------------------------------------------------------------------
  446. // Tests if root or leaf
  447. //-----------------------------------------------------------------------------
  448. template < class T, class I, typename L, class M >
  449. inline bool CUtlRBTree<T, I, L, M>::IsRoot( I i ) const
  450. {
  451. return i == m_Root;
  452. }
  453. template < class T, class I, typename L, class M >
  454. inline bool CUtlRBTree<T, I, L, M>::IsLeaf( I i ) const
  455. {
  456. return (LeftChild(i) == InvalidIndex()) && (RightChild(i) == InvalidIndex());
  457. }
  458. //-----------------------------------------------------------------------------
  459. // Checks if a node is valid and in the tree
  460. //-----------------------------------------------------------------------------
  461. template < class T, class I, typename L, class M >
  462. inline bool CUtlRBTree<T, I, L, M>::IsValidIndex( I i ) const
  463. {
  464. if ( !m_Elements.IsIdxValid( i ) )
  465. return false;
  466. if ( m_Elements.IsIdxAfter( i, m_LastAlloc ) )
  467. return false; // don't read values that have been allocated, but not constructed
  468. return LeftChild(i) != i;
  469. }
  470. //-----------------------------------------------------------------------------
  471. // Invalid index
  472. //-----------------------------------------------------------------------------
  473. template < class T, class I, typename L, class M >
  474. inline I CUtlRBTree<T, I, L, M>::InvalidIndex()
  475. {
  476. return ( I )M::InvalidIndex();
  477. }
  478. //-----------------------------------------------------------------------------
  479. // returns the tree depth (not a very fast operation)
  480. //-----------------------------------------------------------------------------
  481. template < class T, class I, typename L, class M >
  482. inline int CUtlRBTree<T, I, L, M>::Depth() const
  483. {
  484. return Depth(Root());
  485. }
  486. //-----------------------------------------------------------------------------
  487. // Sets the children
  488. //-----------------------------------------------------------------------------
  489. template < class T, class I, typename L, class M >
  490. inline void CUtlRBTree<T, I, L, M>::SetParent( I i, I parent )
  491. {
  492. Links(i).m_Parent = parent;
  493. }
  494. template < class T, class I, typename L, class M >
  495. inline void CUtlRBTree<T, I, L, M>::SetLeftChild( I i, I child )
  496. {
  497. Links(i).m_Left = child;
  498. }
  499. template < class T, class I, typename L, class M >
  500. inline void CUtlRBTree<T, I, L, M>::SetRightChild( I i, I child )
  501. {
  502. Links(i).m_Right = child;
  503. }
  504. //-----------------------------------------------------------------------------
  505. // Gets at the links
  506. //-----------------------------------------------------------------------------
  507. template < class T, class I, typename L, class M >
  508. inline typename CUtlRBTree<T, I, L, M>::Links_t const &CUtlRBTree<T, I, L, M>::Links( I i ) const
  509. {
  510. // Sentinel node, makes life easier
  511. static const Links_t s_Sentinel =
  512. {
  513. // Use M::INVALID_INDEX instead of InvalidIndex() so that this is
  514. // a compile-time constant -- otherwise it is constructed on the first
  515. // call!
  516. M::INVALID_INDEX, M::INVALID_INDEX, M::INVALID_INDEX, CUtlRBTree<T, I, L, M>::BLACK
  517. };
  518. return (i != InvalidIndex()) ? m_Elements[i] : s_Sentinel;
  519. }
  520. template < class T, class I, typename L, class M >
  521. inline typename CUtlRBTree<T, I, L, M>::Links_t &CUtlRBTree<T, I, L, M>::Links( I i )
  522. {
  523. Assert(i != InvalidIndex());
  524. return m_Elements[i];
  525. }
  526. //-----------------------------------------------------------------------------
  527. // Checks if a link is red or black
  528. //-----------------------------------------------------------------------------
  529. template < class T, class I, typename L, class M >
  530. inline bool CUtlRBTree<T, I, L, M>::IsRed( I i ) const
  531. {
  532. return Color( i ) == RED;
  533. }
  534. template < class T, class I, typename L, class M >
  535. inline bool CUtlRBTree<T, I, L, M>::IsBlack( I i ) const
  536. {
  537. return Color( i ) == BLACK;
  538. }
  539. //-----------------------------------------------------------------------------
  540. // Sets/gets node color
  541. //-----------------------------------------------------------------------------
  542. template < class T, class I, typename L, class M >
  543. inline typename CUtlRBTree<T, I, L, M>::NodeColor_t CUtlRBTree<T, I, L, M>::Color( I i ) const
  544. {
  545. return (NodeColor_t)(i != InvalidIndex() ? m_Elements[i].m_Tag : BLACK);
  546. }
  547. template < class T, class I, typename L, class M >
  548. inline void CUtlRBTree<T, I, L, M>::SetColor( I i, typename CUtlRBTree<T, I, L, M>::NodeColor_t c )
  549. {
  550. Links(i).m_Tag = (I)c;
  551. }
  552. //-----------------------------------------------------------------------------
  553. // Allocates/ deallocates nodes
  554. //-----------------------------------------------------------------------------
  555. #pragma warning(push)
  556. #pragma warning(disable:4389) // '==' : signed/unsigned mismatch
  557. template < class T, class I, typename L, class M >
  558. I CUtlRBTree<T, I, L, M>::NewNode()
  559. {
  560. I elem;
  561. // Nothing in the free list; add.
  562. if ( m_FirstFree == InvalidIndex() )
  563. {
  564. Assert( m_Elements.IsValidIterator( m_LastAlloc ) || m_NumElements == 0 );
  565. typename M::Iterator_t it = m_Elements.IsValidIterator( m_LastAlloc ) ? m_Elements.Next( m_LastAlloc ) : m_Elements.First();
  566. if ( !m_Elements.IsValidIterator( it ) )
  567. {
  568. MEM_ALLOC_CREDIT_CLASS();
  569. m_Elements.Grow();
  570. it = m_Elements.IsValidIterator( m_LastAlloc ) ? m_Elements.Next( m_LastAlloc ) : m_Elements.First();
  571. Assert( m_Elements.IsValidIterator( it ) );
  572. if ( !m_Elements.IsValidIterator( it ) )
  573. {
  574. Error( "CUtlRBTree overflow!\n" );
  575. }
  576. }
  577. m_LastAlloc = it;
  578. elem = m_Elements.GetIndex( m_LastAlloc );
  579. Assert( m_Elements.IsValidIterator( m_LastAlloc ) );
  580. }
  581. else
  582. {
  583. elem = m_FirstFree;
  584. m_FirstFree = RightChild( m_FirstFree );
  585. }
  586. #ifdef _DEBUG
  587. // reset links to invalid....
  588. Links_t &node = Links( elem );
  589. node.m_Left = node.m_Right = node.m_Parent = InvalidIndex();
  590. #endif
  591. Construct( &Element( elem ) );
  592. ResetDbgInfo();
  593. return elem;
  594. }
  595. #pragma warning(pop)
  596. template < class T, class I, typename L, class M >
  597. void CUtlRBTree<T, I, L, M>::FreeNode( I i )
  598. {
  599. Assert( IsValidIndex(i) && (i != InvalidIndex()) );
  600. Destruct( &Element(i) );
  601. SetLeftChild( i, i ); // indicates it's in not in the tree
  602. SetRightChild( i, m_FirstFree );
  603. m_FirstFree = i;
  604. }
  605. //-----------------------------------------------------------------------------
  606. // Rotates node i to the left
  607. //-----------------------------------------------------------------------------
  608. template < class T, class I, typename L, class M >
  609. void CUtlRBTree<T, I, L, M>::RotateLeft(I elem)
  610. {
  611. I rightchild = RightChild(elem);
  612. SetRightChild( elem, LeftChild(rightchild) );
  613. if (LeftChild(rightchild) != InvalidIndex())
  614. SetParent( LeftChild(rightchild), elem );
  615. if (rightchild != InvalidIndex())
  616. SetParent( rightchild, Parent(elem) );
  617. if (!IsRoot(elem))
  618. {
  619. if (IsLeftChild(elem))
  620. SetLeftChild( Parent(elem), rightchild );
  621. else
  622. SetRightChild( Parent(elem), rightchild );
  623. }
  624. else
  625. m_Root = rightchild;
  626. SetLeftChild( rightchild, elem );
  627. if (elem != InvalidIndex())
  628. SetParent( elem, rightchild );
  629. }
  630. //-----------------------------------------------------------------------------
  631. // Rotates node i to the right
  632. //-----------------------------------------------------------------------------
  633. template < class T, class I, typename L, class M >
  634. void CUtlRBTree<T, I, L, M>::RotateRight(I elem)
  635. {
  636. I leftchild = LeftChild(elem);
  637. SetLeftChild( elem, RightChild(leftchild) );
  638. if (RightChild(leftchild) != InvalidIndex())
  639. SetParent( RightChild(leftchild), elem );
  640. if (leftchild != InvalidIndex())
  641. SetParent( leftchild, Parent(elem) );
  642. if (!IsRoot(elem))
  643. {
  644. if (IsRightChild(elem))
  645. SetRightChild( Parent(elem), leftchild );
  646. else
  647. SetLeftChild( Parent(elem), leftchild );
  648. }
  649. else
  650. m_Root = leftchild;
  651. SetRightChild( leftchild, elem );
  652. if (elem != InvalidIndex())
  653. SetParent( elem, leftchild );
  654. }
  655. //-----------------------------------------------------------------------------
  656. // Rebalances the tree after an insertion
  657. //-----------------------------------------------------------------------------
  658. template < class T, class I, typename L, class M >
  659. void CUtlRBTree<T, I, L, M>::InsertRebalance(I elem)
  660. {
  661. while ( !IsRoot(elem) && (Color(Parent(elem)) == RED) )
  662. {
  663. I parent = Parent(elem);
  664. I grandparent = Parent(parent);
  665. /* we have a violation */
  666. if (IsLeftChild(parent))
  667. {
  668. I uncle = RightChild(grandparent);
  669. if (IsRed(uncle))
  670. {
  671. /* uncle is RED */
  672. SetColor(parent, BLACK);
  673. SetColor(uncle, BLACK);
  674. SetColor(grandparent, RED);
  675. elem = grandparent;
  676. }
  677. else
  678. {
  679. /* uncle is BLACK */
  680. if (IsRightChild(elem))
  681. {
  682. /* make x a left child, will change parent and grandparent */
  683. elem = parent;
  684. RotateLeft(elem);
  685. parent = Parent(elem);
  686. grandparent = Parent(parent);
  687. }
  688. /* recolor and rotate */
  689. SetColor(parent, BLACK);
  690. SetColor(grandparent, RED);
  691. RotateRight(grandparent);
  692. }
  693. }
  694. else
  695. {
  696. /* mirror image of above code */
  697. I uncle = LeftChild(grandparent);
  698. if (IsRed(uncle))
  699. {
  700. /* uncle is RED */
  701. SetColor(parent, BLACK);
  702. SetColor(uncle, BLACK);
  703. SetColor(grandparent, RED);
  704. elem = grandparent;
  705. }
  706. else
  707. {
  708. /* uncle is BLACK */
  709. if (IsLeftChild(elem))
  710. {
  711. /* make x a right child, will change parent and grandparent */
  712. elem = parent;
  713. RotateRight(parent);
  714. parent = Parent(elem);
  715. grandparent = Parent(parent);
  716. }
  717. /* recolor and rotate */
  718. SetColor(parent, BLACK);
  719. SetColor(grandparent, RED);
  720. RotateLeft(grandparent);
  721. }
  722. }
  723. }
  724. SetColor( m_Root, BLACK );
  725. }
  726. //-----------------------------------------------------------------------------
  727. // Insert a node into the tree
  728. //-----------------------------------------------------------------------------
  729. template < class T, class I, typename L, class M >
  730. I CUtlRBTree<T, I, L, M>::InsertAt( I parent, bool leftchild )
  731. {
  732. I i = NewNode();
  733. LinkToParent( i, parent, leftchild );
  734. ++m_NumElements;
  735. Assert(IsValid());
  736. return i;
  737. }
  738. template < class T, class I, typename L, class M >
  739. void CUtlRBTree<T, I, L, M>::LinkToParent( I i, I parent, bool isLeft )
  740. {
  741. Links_t &elem = Links(i);
  742. elem.m_Parent = parent;
  743. elem.m_Left = elem.m_Right = InvalidIndex();
  744. elem.m_Tag = RED;
  745. /* insert node in tree */
  746. if (parent != InvalidIndex())
  747. {
  748. if (isLeft)
  749. Links(parent).m_Left = i;
  750. else
  751. Links(parent).m_Right = i;
  752. }
  753. else
  754. {
  755. m_Root = i;
  756. }
  757. InsertRebalance(i);
  758. }
  759. //-----------------------------------------------------------------------------
  760. // Rebalance the tree after a deletion
  761. //-----------------------------------------------------------------------------
  762. template < class T, class I, typename L, class M >
  763. void CUtlRBTree<T, I, L, M>::RemoveRebalance(I elem)
  764. {
  765. while (elem != m_Root && IsBlack(elem))
  766. {
  767. I parent = Parent(elem);
  768. // If elem is the left child of the parent
  769. if (elem == LeftChild(parent))
  770. {
  771. // Get our sibling
  772. I sibling = RightChild(parent);
  773. if (IsRed(sibling))
  774. {
  775. SetColor(sibling, BLACK);
  776. SetColor(parent, RED);
  777. RotateLeft(parent);
  778. // We may have a new parent now
  779. parent = Parent(elem);
  780. sibling = RightChild(parent);
  781. }
  782. if ( (IsBlack(LeftChild(sibling))) && (IsBlack(RightChild(sibling))) )
  783. {
  784. if (sibling != InvalidIndex())
  785. SetColor(sibling, RED);
  786. elem = parent;
  787. }
  788. else
  789. {
  790. if (IsBlack(RightChild(sibling)))
  791. {
  792. SetColor(LeftChild(sibling), BLACK);
  793. SetColor(sibling, RED);
  794. RotateRight(sibling);
  795. // rotation may have changed this
  796. parent = Parent(elem);
  797. sibling = RightChild(parent);
  798. }
  799. SetColor( sibling, Color(parent) );
  800. SetColor( parent, BLACK );
  801. SetColor( RightChild(sibling), BLACK );
  802. RotateLeft( parent );
  803. elem = m_Root;
  804. }
  805. }
  806. else
  807. {
  808. // Elem is the right child of the parent
  809. I sibling = LeftChild(parent);
  810. if (IsRed(sibling))
  811. {
  812. SetColor(sibling, BLACK);
  813. SetColor(parent, RED);
  814. RotateRight(parent);
  815. // We may have a new parent now
  816. parent = Parent(elem);
  817. sibling = LeftChild(parent);
  818. }
  819. if ( (IsBlack(RightChild(sibling))) && (IsBlack(LeftChild(sibling))) )
  820. {
  821. if (sibling != InvalidIndex())
  822. SetColor( sibling, RED );
  823. elem = parent;
  824. }
  825. else
  826. {
  827. if (IsBlack(LeftChild(sibling)))
  828. {
  829. SetColor( RightChild(sibling), BLACK );
  830. SetColor( sibling, RED );
  831. RotateLeft( sibling );
  832. // rotation may have changed this
  833. parent = Parent(elem);
  834. sibling = LeftChild(parent);
  835. }
  836. SetColor( sibling, Color(parent) );
  837. SetColor( parent, BLACK );
  838. SetColor( LeftChild(sibling), BLACK );
  839. RotateRight( parent );
  840. elem = m_Root;
  841. }
  842. }
  843. }
  844. SetColor( elem, BLACK );
  845. }
  846. template < class T, class I, typename L, class M >
  847. void CUtlRBTree<T, I, L, M>::Unlink( I elem )
  848. {
  849. if ( elem != InvalidIndex() )
  850. {
  851. I x, y;
  852. if ((LeftChild(elem) == InvalidIndex()) ||
  853. (RightChild(elem) == InvalidIndex()))
  854. {
  855. /* y has a NIL node as a child */
  856. y = elem;
  857. }
  858. else
  859. {
  860. /* find tree successor with a NIL node as a child */
  861. y = RightChild(elem);
  862. while (LeftChild(y) != InvalidIndex())
  863. y = LeftChild(y);
  864. }
  865. /* x is y's only child */
  866. if (LeftChild(y) != InvalidIndex())
  867. x = LeftChild(y);
  868. else
  869. x = RightChild(y);
  870. /* remove y from the parent chain */
  871. if (x != InvalidIndex())
  872. SetParent( x, Parent(y) );
  873. if (!IsRoot(y))
  874. {
  875. if (IsLeftChild(y))
  876. SetLeftChild( Parent(y), x );
  877. else
  878. SetRightChild( Parent(y), x );
  879. }
  880. else
  881. m_Root = x;
  882. // need to store this off now, we'll be resetting y's color
  883. NodeColor_t ycolor = Color(y);
  884. if (y != elem)
  885. {
  886. // Standard implementations copy the data around, we cannot here.
  887. // Hook in y to link to the same stuff elem used to.
  888. SetParent( y, Parent(elem) );
  889. SetRightChild( y, RightChild(elem) );
  890. SetLeftChild( y, LeftChild(elem) );
  891. if (!IsRoot(elem))
  892. if (IsLeftChild(elem))
  893. SetLeftChild( Parent(elem), y );
  894. else
  895. SetRightChild( Parent(elem), y );
  896. else
  897. m_Root = y;
  898. if (LeftChild(y) != InvalidIndex())
  899. SetParent( LeftChild(y), y );
  900. if (RightChild(y) != InvalidIndex())
  901. SetParent( RightChild(y), y );
  902. SetColor( y, Color(elem) );
  903. }
  904. if ((x != InvalidIndex()) && (ycolor == BLACK))
  905. RemoveRebalance(x);
  906. }
  907. }
  908. template < class T, class I, typename L, class M >
  909. void CUtlRBTree<T, I, L, M>::Link( I elem )
  910. {
  911. if ( elem != InvalidIndex() )
  912. {
  913. I parent = InvalidIndex();
  914. bool leftchild = false;
  915. FindInsertionPosition( Element( elem ), parent, leftchild );
  916. LinkToParent( elem, parent, leftchild );
  917. Assert(IsValid());
  918. }
  919. }
  920. //-----------------------------------------------------------------------------
  921. // Delete a node from the tree
  922. //-----------------------------------------------------------------------------
  923. template < class T, class I, typename L, class M >
  924. void CUtlRBTree<T, I, L, M>::RemoveAt(I elem)
  925. {
  926. if ( elem != InvalidIndex() )
  927. {
  928. Unlink( elem );
  929. FreeNode(elem);
  930. --m_NumElements;
  931. Assert(IsValid());
  932. }
  933. }
  934. //-----------------------------------------------------------------------------
  935. // remove a node in the tree
  936. //-----------------------------------------------------------------------------
  937. template < class T, class I, typename L, class M > bool CUtlRBTree<T, I, L, M>::Remove( T const &search )
  938. {
  939. I node = Find( search );
  940. if (node != InvalidIndex())
  941. {
  942. RemoveAt(node);
  943. return true;
  944. }
  945. return false;
  946. }
  947. //-----------------------------------------------------------------------------
  948. // Removes all nodes from the tree
  949. //-----------------------------------------------------------------------------
  950. template < class T, class I, typename L, class M >
  951. void CUtlRBTree<T, I, L, M>::RemoveAll()
  952. {
  953. // Have to do some convoluted stuff to invoke the destructor on all
  954. // valid elements for the multilist case (since we don't have all elements
  955. // connected to each other in a list).
  956. if ( m_LastAlloc == m_Elements.InvalidIterator() )
  957. {
  958. Assert( m_Root == InvalidIndex() );
  959. Assert( m_FirstFree == InvalidIndex() );
  960. Assert( m_NumElements == 0 );
  961. return;
  962. }
  963. for ( typename M::Iterator_t it = m_Elements.First(); it != m_Elements.InvalidIterator(); it = m_Elements.Next( it ) )
  964. {
  965. I i = m_Elements.GetIndex( it );
  966. if ( IsValidIndex( i ) ) // skip elements in the free list
  967. {
  968. Destruct( &Element( i ) );
  969. SetRightChild( i, m_FirstFree );
  970. SetLeftChild( i, i );
  971. m_FirstFree = i;
  972. }
  973. if ( it == m_LastAlloc )
  974. break; // don't destruct elements that haven't ever been constucted
  975. }
  976. // Clear everything else out
  977. m_Root = InvalidIndex();
  978. m_NumElements = 0;
  979. Assert( IsValid() );
  980. }
  981. //-----------------------------------------------------------------------------
  982. // Removes all nodes from the tree and purges memory
  983. //-----------------------------------------------------------------------------
  984. template < class T, class I, typename L, class M >
  985. void CUtlRBTree<T, I, L, M>::Purge()
  986. {
  987. RemoveAll();
  988. m_FirstFree = InvalidIndex();
  989. m_Elements.Purge();
  990. m_LastAlloc = m_Elements.InvalidIterator();
  991. }
  992. //-----------------------------------------------------------------------------
  993. // iteration
  994. //-----------------------------------------------------------------------------
  995. template < class T, class I, typename L, class M >
  996. I CUtlRBTree<T, I, L, M>::FirstInorder() const
  997. {
  998. I i = m_Root;
  999. I left;
  1000. while ((left = LeftChild(i)) != InvalidIndex())
  1001. i = left;
  1002. return i;
  1003. }
  1004. template < class T, class I, typename L, class M >
  1005. I CUtlRBTree<T, I, L, M>::NextInorder( I i ) const
  1006. {
  1007. Assert(IsValidIndex(i));
  1008. I right;
  1009. if ((right = RightChild(i)) != InvalidIndex())
  1010. {
  1011. i = right;
  1012. I left;
  1013. while ((left = LeftChild(i)) != InvalidIndex())
  1014. i = left;
  1015. return i;
  1016. }
  1017. I parent = Parent(i);
  1018. while (IsRightChild(i))
  1019. {
  1020. i = parent;
  1021. if (i == InvalidIndex()) break;
  1022. parent = Parent(i);
  1023. }
  1024. return parent;
  1025. }
  1026. template < class T, class I, typename L, class M >
  1027. I CUtlRBTree<T, I, L, M>::PrevInorder( I i ) const
  1028. {
  1029. Assert(IsValidIndex(i));
  1030. I left, right;
  1031. if ((left = LeftChild(i)) != InvalidIndex())
  1032. {
  1033. i = left;
  1034. while ((right = RightChild(i)) != InvalidIndex())
  1035. i = right;
  1036. return i;
  1037. }
  1038. I parent = Parent(i);
  1039. while (IsLeftChild(i))
  1040. {
  1041. i = parent;
  1042. if (i == InvalidIndex()) break;
  1043. parent = Parent(i);
  1044. }
  1045. return parent;
  1046. }
  1047. template < class T, class I, typename L, class M >
  1048. I CUtlRBTree<T, I, L, M>::LastInorder() const
  1049. {
  1050. I i = m_Root;
  1051. I right;
  1052. while ((right = RightChild(i)) != InvalidIndex())
  1053. i = right;
  1054. return i;
  1055. }
  1056. template < class T, class I, typename L, class M >
  1057. I CUtlRBTree<T, I, L, M>::FirstPreorder() const
  1058. {
  1059. return m_Root;
  1060. }
  1061. template < class T, class I, typename L, class M >
  1062. I CUtlRBTree<T, I, L, M>::NextPreorder( I i ) const
  1063. {
  1064. I left, right;
  1065. if ((left = LeftChild(i)) != InvalidIndex())
  1066. return left;
  1067. if ((right = RightChild(i)) != InvalidIndex())
  1068. return right;
  1069. I parent = Parent(i);
  1070. while( parent != InvalidIndex())
  1071. {
  1072. if (IsLeftChild(i) && (RightChild(parent) != InvalidIndex()))
  1073. return RightChild(parent);
  1074. i = parent;
  1075. parent = Parent(parent);
  1076. }
  1077. return InvalidIndex();
  1078. }
  1079. template < class T, class I, typename L, class M >
  1080. I CUtlRBTree<T, I, L, M>::PrevPreorder( I i ) const
  1081. {
  1082. Assert(0); // not implemented yet
  1083. return InvalidIndex();
  1084. }
  1085. template < class T, class I, typename L, class M >
  1086. I CUtlRBTree<T, I, L, M>::LastPreorder() const
  1087. {
  1088. I i = m_Root;
  1089. while (1)
  1090. {
  1091. I left, right;
  1092. while ((right = RightChild(i)) != InvalidIndex())
  1093. i = right;
  1094. if ((left = LeftChild(i)) != InvalidIndex())
  1095. i = left;
  1096. else
  1097. break;
  1098. }
  1099. return i;
  1100. }
  1101. template < class T, class I, typename L, class M >
  1102. I CUtlRBTree<T, I, L, M>::FirstPostorder() const
  1103. {
  1104. I i = m_Root;
  1105. while (!IsLeaf(i))
  1106. {
  1107. I left;
  1108. if ((left = LeftChild(i)) != InvalidIndex())
  1109. i = left;
  1110. else
  1111. i = RightChild(i);
  1112. }
  1113. return i;
  1114. }
  1115. template < class T, class I, typename L, class M >
  1116. I CUtlRBTree<T, I, L, M>::NextPostorder( I i ) const
  1117. {
  1118. I parent = Parent(i);
  1119. if (parent == InvalidIndex())
  1120. return InvalidIndex();
  1121. if (IsRightChild(i))
  1122. return parent;
  1123. if (RightChild(parent) == InvalidIndex())
  1124. return parent;
  1125. i = RightChild(parent);
  1126. while (!IsLeaf(i))
  1127. {
  1128. I left;
  1129. if ((left = LeftChild(i)) != InvalidIndex())
  1130. i = left;
  1131. else
  1132. i = RightChild(i);
  1133. }
  1134. return i;
  1135. }
  1136. template < class T, class I, typename L, class M >
  1137. void CUtlRBTree<T, I, L, M>::Reinsert( I elem )
  1138. {
  1139. Unlink( elem );
  1140. Link( elem );
  1141. }
  1142. //-----------------------------------------------------------------------------
  1143. // returns the tree depth (not a very fast operation)
  1144. //-----------------------------------------------------------------------------
  1145. template < class T, class I, typename L, class M >
  1146. int CUtlRBTree<T, I, L, M>::Depth( I node ) const
  1147. {
  1148. if (node == InvalidIndex())
  1149. return 0;
  1150. int depthright = Depth( RightChild(node) );
  1151. int depthleft = Depth( LeftChild(node) );
  1152. return MAX( depthright, depthleft ) + 1;
  1153. }
  1154. //#define UTLTREE_PARANOID
  1155. //-----------------------------------------------------------------------------
  1156. // Makes sure the tree is valid after every operation
  1157. //-----------------------------------------------------------------------------
  1158. template < class T, class I, typename L, class M >
  1159. bool CUtlRBTree<T, I, L, M>::IsValid() const
  1160. {
  1161. if ( !Count() )
  1162. return true;
  1163. if ( m_LastAlloc == m_Elements.InvalidIterator() )
  1164. return false;
  1165. if ( !m_Elements.IsIdxValid( Root() ) )
  1166. return false;
  1167. if ( Parent( Root() ) != InvalidIndex() )
  1168. return false;
  1169. #ifdef UTLTREE_PARANOID
  1170. // First check to see that mNumEntries matches reality.
  1171. // count items on the free list
  1172. int numFree = 0;
  1173. for ( int i = m_FirstFree; i != InvalidIndex(); i = RightChild( i ) )
  1174. {
  1175. ++numFree;
  1176. if ( !m_Elements.IsIdxValid( i ) )
  1177. return false;
  1178. }
  1179. // iterate over all elements, looking for validity
  1180. // based on the self pointers
  1181. int nElements = 0;
  1182. int numFree2 = 0;
  1183. for ( M::Iterator_t it = m_Elements.First(); it != m_Elements.InvalidIterator(); it = m_Elements.Next( it ) )
  1184. {
  1185. I i = m_Elements.GetIndex( it );
  1186. if ( !IsValidIndex( i ) )
  1187. {
  1188. ++numFree2;
  1189. }
  1190. else
  1191. {
  1192. ++nElements;
  1193. int right = RightChild( i );
  1194. int left = LeftChild( i );
  1195. if ( ( right == left ) && ( right != InvalidIndex() ) )
  1196. return false;
  1197. if ( right != InvalidIndex() )
  1198. {
  1199. if ( !IsValidIndex( right ) )
  1200. return false;
  1201. if ( Parent( right ) != i )
  1202. return false;
  1203. if ( IsRed( i ) && IsRed( right ) )
  1204. return false;
  1205. }
  1206. if ( left != InvalidIndex() )
  1207. {
  1208. if ( !IsValidIndex( left ) )
  1209. return false;
  1210. if ( Parent( left ) != i )
  1211. return false;
  1212. if ( IsRed( i ) && IsRed( left ) )
  1213. return false;
  1214. }
  1215. }
  1216. if ( it == m_LastAlloc )
  1217. break;
  1218. }
  1219. if ( numFree2 != numFree )
  1220. return false;
  1221. if ( nElements != m_NumElements )
  1222. return false;
  1223. #endif // UTLTREE_PARANOID
  1224. return true;
  1225. }
  1226. //-----------------------------------------------------------------------------
  1227. // Sets the less func
  1228. //-----------------------------------------------------------------------------
  1229. template < class T, class I, typename L, class M >
  1230. void CUtlRBTree<T, I, L, M>::SetLessFunc( const typename CUtlRBTree<T, I, L, M>::LessFunc_t &func )
  1231. {
  1232. if (!m_LessFunc)
  1233. {
  1234. m_LessFunc = func;
  1235. }
  1236. else if ( Count() > 0 )
  1237. {
  1238. // need to re-sort the tree here....
  1239. Assert(0);
  1240. }
  1241. }
  1242. //-----------------------------------------------------------------------------
  1243. // inserts a node into the tree
  1244. //-----------------------------------------------------------------------------
  1245. // Inserts a node into the tree, doesn't copy the data in.
  1246. template < class T, class I, typename L, class M >
  1247. void CUtlRBTree<T, I, L, M>::FindInsertionPosition( T const &insert, I &parent, bool &leftchild )
  1248. {
  1249. Assert( !!m_LessFunc );
  1250. /* find where node belongs */
  1251. I current = m_Root;
  1252. parent = InvalidIndex();
  1253. leftchild = false;
  1254. while (current != InvalidIndex())
  1255. {
  1256. parent = current;
  1257. if (m_LessFunc( insert, Element(current) ))
  1258. {
  1259. leftchild = true; current = LeftChild(current);
  1260. }
  1261. else
  1262. {
  1263. leftchild = false; current = RightChild(current);
  1264. }
  1265. }
  1266. }
  1267. template < class T, class I, typename L, class M >
  1268. I CUtlRBTree<T, I, L, M>::Insert( T const &insert )
  1269. {
  1270. // use copy constructor to copy it in
  1271. I parent = InvalidIndex();
  1272. bool leftchild = false;
  1273. FindInsertionPosition( insert, parent, leftchild );
  1274. I newNode = InsertAt( parent, leftchild );
  1275. CopyConstruct( &Element( newNode ), insert );
  1276. return newNode;
  1277. }
  1278. template < class T, class I, typename L, class M >
  1279. void CUtlRBTree<T, I, L, M>::Insert( const T *pArray, int nItems )
  1280. {
  1281. while ( nItems-- )
  1282. {
  1283. Insert( *pArray++ );
  1284. }
  1285. }
  1286. template < class T, class I, typename L, class M >
  1287. I CUtlRBTree<T, I, L, M>::InsertIfNotFound( T const &insert )
  1288. {
  1289. // use copy constructor to copy it in
  1290. I parent;
  1291. bool leftchild;
  1292. I current = m_Root;
  1293. parent = InvalidIndex();
  1294. leftchild = false;
  1295. while (current != InvalidIndex())
  1296. {
  1297. parent = current;
  1298. if (m_LessFunc( insert, Element(current) ))
  1299. {
  1300. leftchild = true; current = LeftChild(current);
  1301. }
  1302. else if (m_LessFunc( Element(current), insert ))
  1303. {
  1304. leftchild = false; current = RightChild(current);
  1305. }
  1306. else
  1307. // Match found, no insertion
  1308. return InvalidIndex();
  1309. }
  1310. I newNode = InsertAt( parent, leftchild );
  1311. CopyConstruct( &Element( newNode ), insert );
  1312. return newNode;
  1313. }
  1314. //-----------------------------------------------------------------------------
  1315. // finds a node in the tree
  1316. //-----------------------------------------------------------------------------
  1317. template < class T, class I, typename L, class M >
  1318. I CUtlRBTree<T, I, L, M>::Find( T const &search ) const
  1319. {
  1320. Assert( !!m_LessFunc );
  1321. I current = m_Root;
  1322. while (current != InvalidIndex())
  1323. {
  1324. if (m_LessFunc( search, Element(current) ))
  1325. current = LeftChild(current);
  1326. else if (m_LessFunc( Element(current), search ))
  1327. current = RightChild(current);
  1328. else
  1329. break;
  1330. }
  1331. return current;
  1332. }
  1333. //-----------------------------------------------------------------------------
  1334. // finds a the first node (inorder) with this key in the tree
  1335. //-----------------------------------------------------------------------------
  1336. template <class T, class I, typename L, class E>
  1337. I CUtlRBTree<T, I, L, E>::FindFirst( T const &search ) const
  1338. {
  1339. Assert( !!m_LessFunc );
  1340. I current = m_Root;
  1341. I best = InvalidIndex();
  1342. while ( current != InvalidIndex() )
  1343. {
  1344. if ( m_LessFunc( search, Element( current ) ) )
  1345. current = LeftChild( current );
  1346. else if ( m_LessFunc( Element( current ), search ) )
  1347. current = RightChild( current );
  1348. else
  1349. {
  1350. best = current;
  1351. current = LeftChild( current );
  1352. }
  1353. }
  1354. return best;
  1355. }
  1356. //-----------------------------------------------------------------------------
  1357. // finds the closest node to the key supplied
  1358. //-----------------------------------------------------------------------------
  1359. template <class T, class I, typename L, class E>
  1360. I CUtlRBTree<T, I, L, E>::FindClosest( T const &search, CompareOperands_t eFindCriteria ) const
  1361. {
  1362. Assert( !!m_LessFunc );
  1363. Assert( ( eFindCriteria & ( k_EGreaterThan | k_ELessThan ) ) ^ ( k_EGreaterThan | k_ELessThan ) );
  1364. I current = m_Root;
  1365. I best = InvalidIndex();
  1366. while ( current != InvalidIndex() )
  1367. {
  1368. if ( m_LessFunc( search, Element( current ) ) )
  1369. {
  1370. // current node is > key
  1371. if ( eFindCriteria & k_EGreaterThan )
  1372. best = current;
  1373. current = LeftChild( current );
  1374. }
  1375. else if ( m_LessFunc( Element( current ), search ) )
  1376. {
  1377. // current node is < key
  1378. if ( eFindCriteria & k_ELessThan )
  1379. best = current;
  1380. current = RightChild( current );
  1381. }
  1382. else
  1383. {
  1384. // exact match
  1385. if ( eFindCriteria & k_EEqual )
  1386. {
  1387. best = current;
  1388. break;
  1389. }
  1390. else if ( eFindCriteria & k_EGreaterThan )
  1391. {
  1392. current = RightChild( current );
  1393. }
  1394. else if ( eFindCriteria & k_ELessThan )
  1395. {
  1396. current = LeftChild( current );
  1397. }
  1398. }
  1399. }
  1400. return best;
  1401. }
  1402. //-----------------------------------------------------------------------------
  1403. // swap in place
  1404. //-----------------------------------------------------------------------------
  1405. template < class T, class I, typename L, class M >
  1406. void CUtlRBTree<T, I, L, M>::Swap( CUtlRBTree< T, I, L > &that )
  1407. {
  1408. m_Elements.Swap( that.m_Elements );
  1409. V_swap( m_LessFunc, that.m_LessFunc );
  1410. V_swap( m_Root, that.m_Root );
  1411. V_swap( m_NumElements, that.m_NumElements );
  1412. V_swap( m_FirstFree, that.m_FirstFree );
  1413. V_swap( m_pElements, that.m_pElements );
  1414. V_swap( m_LastAlloc, that.m_LastAlloc );
  1415. Assert( IsValid() );
  1416. Assert( m_Elements.IsValidIterator( m_LastAlloc ) || ( m_NumElements == 0 && m_FirstFree == InvalidIndex() ) );
  1417. }
  1418. #endif // UTLRBTREE_H