Leaked source code of windows server 2003
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.

277 lines
6.8 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1997, Microsoft Corporation
  4. //
  5. // File: tsort.hxx
  6. //
  7. // Contents: container template for arrays that can be sorted and searched
  8. //
  9. // Classes: CSortable
  10. //
  11. // History: 8-Dec-97 dlee created
  12. //
  13. //----------------------------------------------------------------------------
  14. #pragma once
  15. template<class T, class K> class CSortable
  16. {
  17. public:
  18. CSortable( T *p, ULONG c ) :
  19. _pElems(p),
  20. _cElems(c) {}
  21. CSortable( CDynArrayInPlace<T> & array ) :
  22. _pElems( (T *) array.GetPointer() ),
  23. _cElems( array.Count() ) {}
  24. CSortable( XArray<T> & array ) :
  25. _pElems( array.GetPointer() ),
  26. _cElems( array.Count() ) {}
  27. // sort the array using a heap sort
  28. void Sort()
  29. {
  30. if ( _cElems < 2 )
  31. return;
  32. for ( long i = ( ( (long) _cElems + 1 ) / 2 ) - 1; i >= 0; i-- )
  33. {
  34. AddRoot( i, _cElems );
  35. }
  36. for ( i = _cElems - 1; 0 != i; i-- )
  37. {
  38. Swap( _pElems, _pElems + i );
  39. AddRoot( 0, i );
  40. }
  41. } //Sort
  42. // return the element matching the key or 0 if not found
  43. T * Search( const T * pKey ) const
  44. {
  45. ULONG cElem = _cElems;
  46. T * pLo = _pElems;
  47. T * pHi = _pElems + cElem - 1;
  48. do
  49. {
  50. unsigned cHalf = cElem / 2;
  51. if ( 0 != cHalf )
  52. {
  53. unsigned cTmp = cHalf - 1 + ( cElem & 1 );
  54. T * pMid = pLo + cTmp;
  55. if ( pMid->IsEQ( pKey ) )
  56. return pMid;
  57. else if ( pMid->IsGE( pKey ) )
  58. {
  59. pHi = pMid - 1;
  60. cElem = cTmp;
  61. }
  62. else
  63. {
  64. pLo = pMid + 1;
  65. cElem = cHalf;
  66. }
  67. }
  68. else if ( 0 != cElem )
  69. return pKey->IsEQ( pLo ) ? pLo : 0;
  70. else
  71. break;
  72. }
  73. while ( pLo <= pHi );
  74. return 0;
  75. } //Search
  76. // return the index if the smallest key >= key, or the index beyond
  77. // the last element in the array if key > all keys in the array
  78. T * Search( const K key ) const
  79. {
  80. ULONG cElem = _cElems;
  81. T * pLo = _pElems;
  82. T * pHi = _pElems + cElem - 1;
  83. do
  84. {
  85. unsigned cHalf = cElem / 2;
  86. if ( 0 != cHalf )
  87. {
  88. unsigned cTmp = cHalf - 1 + ( cElem & 1 );
  89. T * pMid = pLo + cTmp;
  90. if ( pMid->IsEQ( key ) )
  91. return pMid;
  92. else if ( pMid->IsGE( key ) )
  93. {
  94. pHi = pMid - 1;
  95. cElem = cTmp;
  96. }
  97. else
  98. {
  99. pLo = pMid + 1;
  100. cElem = cHalf;
  101. }
  102. }
  103. else if ( 0 != cElem )
  104. return pLo->IsEQ( key ) ? pLo : 0;
  105. else
  106. break;
  107. }
  108. while ( pLo <= pHi );
  109. return 0;
  110. } //Search
  111. // return the index if the smallest key >= pKey
  112. ULONG FindInsertionPoint( const T * pKey ) const
  113. {
  114. ULONG cElems = _cElems;
  115. ULONG iLo = 0;
  116. ULONG iHi = cElems - 1;
  117. do
  118. {
  119. ULONG cHalf = cElems / 2;
  120. if ( 0 != cHalf )
  121. {
  122. unsigned cTmp = cHalf - 1 + ( cElems & 1 );
  123. ULONG iMid = iLo + cTmp;
  124. const T * pElem = _pElems + iMid;
  125. if ( pElem->IsEQ( pKey ) )
  126. {
  127. return iMid;
  128. }
  129. else if ( pElem->IsGE( pKey ) )
  130. {
  131. iHi = iMid - 1;
  132. cElems = cTmp;
  133. }
  134. else
  135. {
  136. iLo = iMid + 1;
  137. cElems = cHalf;
  138. }
  139. }
  140. else if ( 0 != cElems )
  141. {
  142. if ( ( _pElems + iLo )->IsGT( pKey ) )
  143. return iLo;
  144. else
  145. return iLo + 1;
  146. }
  147. else return iLo;
  148. }
  149. while (TRUE);
  150. Win4Assert( FALSE );
  151. return 0;
  152. } //FindInsertionPoint
  153. // return the index if the smallest key >= key, or the index beyond
  154. // the last element in the array if key > all keys in the array
  155. ULONG FindInsertionPoint( const K key ) const
  156. {
  157. ULONG cElems = _cElems;
  158. ULONG iLo = 0;
  159. ULONG iHi = cElems - 1;
  160. do
  161. {
  162. ULONG cHalf = cElems / 2;
  163. if ( 0 != cHalf )
  164. {
  165. unsigned cTmp = cHalf - 1 + ( cElems & 1 );
  166. ULONG iMid = iLo + cTmp;
  167. const T * pElem = _pElems + iMid;
  168. if ( pElem->IsEQ( key ) )
  169. {
  170. return iMid;
  171. }
  172. else if ( pElem->IsGE( key ) )
  173. {
  174. iHi = iMid - 1;
  175. cElems = cTmp;
  176. }
  177. else
  178. {
  179. iLo = iMid + 1;
  180. cElems = cHalf;
  181. }
  182. }
  183. else if ( 0 != cElems )
  184. {
  185. if ( ( _pElems + iLo )->IsGT( key ) )
  186. return iLo;
  187. else
  188. return iLo + 1;
  189. }
  190. else return iLo;
  191. }
  192. while (TRUE);
  193. Win4Assert( FALSE );
  194. return 0;
  195. } //FindInsertionPoint
  196. // return TRUE if the array is sorted
  197. BOOL IsSorted()
  198. {
  199. for ( ULONG i = 1; i < _cElems; i++ )
  200. {
  201. if ( ( _pElems + i )->Compare( _pElems + i - 1 ) < 0 )
  202. return FALSE;
  203. }
  204. return TRUE;
  205. } //IsSorted
  206. private:
  207. void Swap( T * p1, T * p2 )
  208. {
  209. T tmp = *p1;
  210. *p1 = *p2;
  211. *p2 = tmp;
  212. }
  213. void AddRoot( ULONG x, ULONG cItems )
  214. {
  215. ULONG y = ( 2 * ( x + 1 ) ) - 1;
  216. while ( y < cItems )
  217. {
  218. if ( ( ( y + 1 ) < cItems ) &&
  219. ( ( _pElems + y )->IsLT( _pElems + y + 1 ) ) )
  220. y++;
  221. if ( ( _pElems + x )->IsLT( _pElems + y ) )
  222. {
  223. Swap( _pElems + x, _pElems + y );
  224. x = y;
  225. y = ( 2 * ( y + 1 ) ) - 1;
  226. }
  227. else
  228. break;
  229. }
  230. } //AddRoot
  231. T * _pElems;
  232. const ULONG _cElems;
  233. };