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

249 lines
7.0 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #ifndef UTLPRIORITYQUEUE_H
  8. #define UTLPRIORITYQUEUE_H
  9. #ifdef _WIN32
  10. #pragma once
  11. #endif
  12. #include "tier1/utlvector.h"
  13. template < typename T >
  14. class CDefUtlPriorityQueueLessFunc
  15. {
  16. public:
  17. bool operator()( const T &lhs, const T &rhs, bool (*lessFuncPtr)( T const&, T const& ) )
  18. {
  19. return lessFuncPtr( lhs, rhs );
  20. }
  21. };
  22. template < typename T >
  23. class CDefUtlPriorityQueueSetIndexFunc
  24. {
  25. public:
  26. inline static void SetIndex( T &heapElement, int nNewIndex ) { }
  27. };
  28. // T is the type stored in the queue, it must include the priority
  29. // The head of the list contains the element with GREATEST priority
  30. // configure the LessFunc_t to get the desired queue order
  31. template< class T, class LessFunc = CDefUtlPriorityQueueLessFunc< T >, class A = CUtlMemory<T>, class SetIndexFunc = CDefUtlPriorityQueueSetIndexFunc< T > >
  32. class CUtlPriorityQueue
  33. {
  34. public:
  35. // Less func typedef
  36. // Returns true if the first parameter is "less priority" than the second
  37. // Items that are "less priority" sort toward the tail of the queue
  38. typedef bool (*LessFunc_t)( T const&, T const& );
  39. typedef T ElemType_t;
  40. // constructor: lessfunc is required, but may be set after the constructor with
  41. // SetLessFunc
  42. CUtlPriorityQueue( int growSize = 0, int initSize = 0, LessFunc_t lessfunc = 0 );
  43. CUtlPriorityQueue( T *pMemory, int numElements, LessFunc_t lessfunc = 0 );
  44. // gets particular elements
  45. inline T const& ElementAtHead() const { return m_heap.Element(0); }
  46. inline bool IsValidIndex(int index) { return m_heap.IsValidIndex(index); }
  47. // O(lgn) to rebalance the heap
  48. void RemoveAtHead();
  49. void RemoveAt( int index );
  50. // Update the position of the specified element in the tree for it current value O(lgn)
  51. void RevaluateElement( const int index );
  52. // O(lgn) to rebalance heap
  53. void Insert( T const &element );
  54. // Sets the less func
  55. void SetLessFunc( LessFunc_t func );
  56. // Returns the count of elements in the queue
  57. inline int Count() const { return m_heap.Count(); }
  58. // doesn't deallocate memory
  59. void RemoveAll() { m_heap.RemoveAll(); }
  60. // Memory deallocation
  61. void Purge() { m_heap.Purge(); }
  62. inline const T & Element( int index ) const { return m_heap.Element(index); }
  63. inline T & Element( int index ) { return m_heap.Element(index); }
  64. bool IsHeapified();
  65. protected:
  66. CUtlVector<T, A> m_heap;
  67. void Swap( int index1, int index2 );
  68. int PercolateDown( int nIndex );
  69. int PercolateUp( int nIndex );
  70. // Used for sorting.
  71. LessFunc_t m_LessFunc;
  72. };
  73. template< class T, class LessFunc, class A, class SetIndexFunc >
  74. inline CUtlPriorityQueue<T, LessFunc, A, SetIndexFunc >::CUtlPriorityQueue( int growSize, int initSize, LessFunc_t lessfunc ) :
  75. m_heap(growSize, initSize), m_LessFunc(lessfunc)
  76. {
  77. }
  78. template< class T, class LessFunc, class A, class SetIndexFunc >
  79. inline CUtlPriorityQueue<T, LessFunc, A, SetIndexFunc >::CUtlPriorityQueue( T *pMemory, int allocationCount, LessFunc_t lessfunc ) :
  80. m_heap(pMemory, allocationCount), m_LessFunc(lessfunc)
  81. {
  82. }
  83. template< class T, class LessFunc, class A, class SetIndexFunc >
  84. inline void CUtlPriorityQueue<T, LessFunc, A, SetIndexFunc >::RemoveAtHead()
  85. {
  86. m_heap.FastRemove( 0 );
  87. if ( Count() > 0 )
  88. {
  89. SetIndexFunc::SetIndex( m_heap[ 0 ], 0 );
  90. }
  91. PercolateDown( 0 );
  92. }
  93. template< class T, class LessFunc, class A, class SetIndexFunc >
  94. inline void CUtlPriorityQueue<T, LessFunc, A, SetIndexFunc >::RemoveAt( int index )
  95. {
  96. Assert(m_heap.IsValidIndex(index));
  97. m_heap.FastRemove( index );
  98. if ( index < Count() )
  99. {
  100. SetIndexFunc::SetIndex( m_heap[ index ], index );
  101. }
  102. RevaluateElement( index );
  103. }
  104. template< class T, class LessFunc, class A, class SetIndexFunc >
  105. inline void CUtlPriorityQueue<T, LessFunc, A, SetIndexFunc >::RevaluateElement( const int nStartingIndex )
  106. {
  107. int index = PercolateDown( nStartingIndex );
  108. // If index is still the same as the starting index, then the specified element was larger than
  109. // its children, so it could be larger than its parent, so treat this like an insertion and swap
  110. // the node with its parent until it is no longer larger than its parent.
  111. if ( index == nStartingIndex )
  112. {
  113. PercolateUp( index );
  114. }
  115. }
  116. template< class T, class LessFunc, class A, class SetIndexFunc >
  117. inline bool CUtlPriorityQueue<T, LessFunc, A, SetIndexFunc >::IsHeapified()
  118. {
  119. LessFunc lessFunc;
  120. for ( int child = Count(); child-- > 1; ) // no need to check the element [0] , it's the parent of all and has no parent itself
  121. {
  122. int parent = ( ( child + 1 ) / 2 ) - 1;
  123. if ( lessFunc( m_heap[ parent ], m_heap[ child ], m_LessFunc ) )
  124. {
  125. return false; // this priority queue is not properly heapified, needs reordering
  126. }
  127. }
  128. return true; // the priority queue is heapified correctly, needs no reordering
  129. }
  130. template< class T, class LessFunc, class A, class SetIndexFunc >
  131. inline int CUtlPriorityQueue<T, LessFunc, A, SetIndexFunc >::PercolateDown( int index )
  132. {
  133. int count = Count();
  134. LessFunc lessFunc;
  135. int half = count/2;
  136. int larger = index;
  137. while ( index < half )
  138. {
  139. int child = ((index+1) * 2) - 1; // if we wasted an element, this math would be more compact (1 based array)
  140. if ( child < count )
  141. {
  142. // Item has been filtered down to its proper place, terminate.
  143. if ( lessFunc( m_heap[index], m_heap[child], m_LessFunc ) )
  144. {
  145. // mark the potential swap and check the other child
  146. larger = child;
  147. }
  148. }
  149. // go to sibling
  150. child++;
  151. if ( child < count )
  152. {
  153. // If this child is larger, swap it instead
  154. if ( lessFunc( m_heap[larger], m_heap[child], m_LessFunc ) )
  155. larger = child;
  156. }
  157. if ( larger == index )
  158. break;
  159. // swap with the larger child
  160. Swap( index, larger );
  161. index = larger;
  162. }
  163. return index;
  164. }
  165. template< class T, class LessFunc, class A, class SetIndexFunc >
  166. inline int CUtlPriorityQueue<T, LessFunc, A, SetIndexFunc >::PercolateUp( int index )
  167. {
  168. if ( index >= Count() )
  169. return index;
  170. LessFunc lessFunc;
  171. while ( index != 0 )
  172. {
  173. int parent = ((index+1) / 2) - 1;
  174. if ( lessFunc( m_heap[index], m_heap[parent], m_LessFunc ) )
  175. break;
  176. // swap with parent and repeat
  177. Swap( parent, index );
  178. index = parent;
  179. }
  180. return index;
  181. }
  182. template< class T, class LessFunc, class A, class SetIndexFunc >
  183. inline void CUtlPriorityQueue<T, LessFunc, A, SetIndexFunc >::Insert( T const &element )
  184. {
  185. int index = m_heap.AddToTail();
  186. m_heap[index] = element;
  187. SetIndexFunc::SetIndex( m_heap[ index ], index );
  188. PercolateUp( index );
  189. }
  190. template< class T, class LessFunc, class A, class SetIndexFunc >
  191. inline void CUtlPriorityQueue<T, LessFunc, A, SetIndexFunc >::Swap( int index1, int index2 )
  192. {
  193. T tmp = m_heap[index1];
  194. m_heap[index1] = m_heap[index2];
  195. m_heap[index2] = tmp;
  196. SetIndexFunc::SetIndex( m_heap[ index1 ], index1 );
  197. SetIndexFunc::SetIndex( m_heap[ index2 ], index2 );
  198. }
  199. template< class T, class LessFunc, class A, class SetIndexFunc >
  200. inline void CUtlPriorityQueue<T, LessFunc, A, SetIndexFunc >::SetLessFunc( LessFunc_t lessfunc )
  201. {
  202. m_LessFunc = lessfunc;
  203. }
  204. #endif // UTLPRIORITYQUEUE_H