Team Fortress 2 Source Code as on 22/4/2020
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.

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