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.

1593 lines
40 KiB

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