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.

198 lines
4.6 KiB

  1. //========= Copyright 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 "utlvector.h"
  13. // T is the type stored in the queue, it must include the priority
  14. // The head of the list contains the element with GREATEST priority
  15. // configure the LessFunc_t to get the desired queue order
  16. template< class T >
  17. class CUtlPriorityQueue
  18. {
  19. public:
  20. // Less func typedef
  21. // Returns true if the first parameter is "less priority" than the second
  22. // Items that are "less priority" sort toward the tail of the queue
  23. typedef bool (*LessFunc_t)( T const&, T const& );
  24. typedef T ElemType_t;
  25. // constructor: lessfunc is required, but may be set after the constructor with
  26. // SetLessFunc
  27. CUtlPriorityQueue( int growSize = 0, int initSize = 0, LessFunc_t lessfunc = 0 );
  28. CUtlPriorityQueue( T *pMemory, int numElements, LessFunc_t lessfunc = 0 );
  29. // gets particular elements
  30. inline T const& ElementAtHead() const { return m_heap.Element(0); }
  31. inline bool IsValidIndex(int index) { return m_heap.IsValidIndex(index); }
  32. // O(lgn) to rebalance the heap
  33. void RemoveAtHead();
  34. void RemoveAt( int index );
  35. // O(lgn) to rebalance heap
  36. void Insert( T const &element );
  37. // Sets the less func
  38. void SetLessFunc( LessFunc_t func );
  39. // Returns the count of elements in the queue
  40. inline int Count() const { return m_heap.Count(); }
  41. // doesn't deallocate memory
  42. void RemoveAll() { m_heap.RemoveAll(); }
  43. // Memory deallocation
  44. void Purge() { m_heap.Purge(); }
  45. inline const T & Element( int index ) const { return m_heap.Element(index); }
  46. protected:
  47. CUtlVector<T> m_heap;
  48. void Swap( int index1, int index2 );
  49. // Used for sorting.
  50. LessFunc_t m_LessFunc;
  51. };
  52. template< class T >
  53. inline CUtlPriorityQueue<T>::CUtlPriorityQueue( int growSize, int initSize, LessFunc_t lessfunc ) :
  54. m_heap(growSize, initSize), m_LessFunc(lessfunc)
  55. {
  56. }
  57. template< class T >
  58. inline CUtlPriorityQueue<T>::CUtlPriorityQueue( T *pMemory, int numElements, LessFunc_t lessfunc ) :
  59. m_heap(pMemory, numElements), m_LessFunc(lessfunc)
  60. {
  61. }
  62. template <class T>
  63. void CUtlPriorityQueue<T>::RemoveAtHead()
  64. {
  65. m_heap.FastRemove( 0 );
  66. int index = 0;
  67. int count = Count();
  68. if ( !count )
  69. return;
  70. int half = count/2;
  71. int larger = index;
  72. while ( index < half )
  73. {
  74. int child = ((index+1) * 2) - 1; // if we wasted an element, this math would be more compact (1 based array)
  75. if ( child < count )
  76. {
  77. // Item has been filtered down to its proper place, terminate.
  78. if ( m_LessFunc( m_heap[index], m_heap[child] ) )
  79. {
  80. // mark the potential swap and check the other child
  81. larger = child;
  82. }
  83. }
  84. // go to sibling
  85. child++;
  86. if ( child < count )
  87. {
  88. // If this child is larger, swap it instead
  89. if ( m_LessFunc( m_heap[larger], m_heap[child] ) )
  90. larger = child;
  91. }
  92. if ( larger == index )
  93. break;
  94. // swap with the larger child
  95. Swap( index, larger );
  96. index = larger;
  97. }
  98. }
  99. template <class T>
  100. void CUtlPriorityQueue<T>::RemoveAt( int index )
  101. {
  102. Assert(m_heap.IsValidIndex(index));
  103. m_heap.FastRemove( index );
  104. int count = Count();
  105. if ( !count )
  106. return;
  107. int half = count/2;
  108. int larger = index;
  109. while ( index < half )
  110. {
  111. int child = ((index+1) * 2) - 1; // if we wasted an element, this math would be more compact (1 based array)
  112. if ( child < count )
  113. {
  114. // Item has been filtered down to its proper place, terminate.
  115. if ( m_LessFunc( m_heap[index], m_heap[child] ) )
  116. {
  117. // mark the potential swap and check the other child
  118. larger = child;
  119. }
  120. }
  121. // go to sibling
  122. child++;
  123. if ( child < count )
  124. {
  125. // If this child is larger, swap it instead
  126. if ( m_LessFunc( m_heap[larger], m_heap[child] ) )
  127. larger = child;
  128. }
  129. if ( larger == index )
  130. break;
  131. // swap with the larger child
  132. Swap( index, larger );
  133. index = larger;
  134. }
  135. }
  136. template <class T>
  137. void CUtlPriorityQueue<T>::Insert( T const &element )
  138. {
  139. int index = m_heap.AddToTail();
  140. m_heap[index] = element;
  141. while ( index != 0 )
  142. {
  143. int parent = ((index+1) / 2) - 1;
  144. if ( m_LessFunc( m_heap[index], m_heap[parent] ) )
  145. break;
  146. // swap with parent and repeat
  147. Swap( parent, index );
  148. index = parent;
  149. }
  150. }
  151. template <class T>
  152. void CUtlPriorityQueue<T>::Swap( int index1, int index2 )
  153. {
  154. T tmp = m_heap[index1];
  155. m_heap[index1] = m_heap[index2];
  156. m_heap[index2] = tmp;
  157. }
  158. template <class T>
  159. void CUtlPriorityQueue<T>::SetLessFunc( LessFunc_t lessfunc )
  160. {
  161. m_LessFunc = lessfunc;
  162. }
  163. #endif // UTLPRIORITYQUEUE_H