Source code of Windows XP (NT5)
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.

390 lines
15 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 2001.
  5. //
  6. // File: HEAP.HXX
  7. //
  8. // Contents: heap
  9. //
  10. // Classes: CHeap
  11. //
  12. // History: 08-May-91 BartoszM Created
  13. //
  14. //----------------------------------------------------------------------------
  15. #pragma once
  16. #ifdef DISPLAY_INCLUDES
  17. #pragma message( "#include <" __FILE__ ">..." )
  18. #endif
  19. //+---------------------------------------------------------------------------
  20. //
  21. // Class: CHeap
  22. //
  23. // Purpose: Heap of items: parametrized class
  24. //
  25. // Interface:
  26. // CHeap( int count, CItem * array[] )
  27. // CHeap( int count )
  28. // CHeap ()
  29. // BOOL IsEmpty()
  30. // int Count()
  31. // CItem* GetVector()
  32. // CItem * Top()
  33. // CItem * RemoveTop()
  34. // CItem * RemoveBottom()
  35. // void Add ( CItem * item )
  36. // void Reheap ()
  37. // void MakeHeap ()
  38. // void MakeHeap ( int count, CItem * array[] )
  39. //
  40. // Notes: This heap can be used for any class of elements
  41. // provided there is a function that compares two elements.
  42. // This function can be defined inline. It takes two pointers
  43. // to elements to be compared and returns true if the first
  44. // element is less than the second one. The name of the
  45. // function is passed to the IMP_HEAP macro.
  46. // Both DEF_HEAP and IMP_HEAP take the name of the
  47. // heap class and the name of the element class as parameters.
  48. // All methods preserve the heap property (partial order).
  49. // Top element is accessible for manipulation. If its
  50. // value changes, Reheap should be called explicitly.
  51. //
  52. // Example:
  53. // class CFoo;
  54. // // comparison function
  55. // BOOL LessFoo ( CFoo * f1, CFoo * f2 );
  56. // // Define class CFooHeap
  57. // DEF_HEAP ( CFooHeap, CFoo )
  58. // // Implement methods of CFooHeap
  59. // IMP_HEAP ( CFooHeap, CFoo, LessFoo )
  60. //
  61. // CFoo aFoo [10];
  62. // // initialize the array
  63. // CFooHeap MyHeap ( 10, aFoo );
  64. // CFoo* pFoo = MyHeap.Top(); // smallest element
  65. // pFoo->ChangeValue ( 13 );
  66. // MyHeap.Reheap(); // reorder after manipulation
  67. //
  68. // History: 08-May-91 BartoszM Created.
  69. //
  70. //----------------------------------------------------------------------------
  71. #define DEF_HEAP( CHeap, CItem ) \
  72. class CHeap \
  73. { \
  74. public: \
  75. CHeap():_end(-1), _item(0) {} \
  76. CHeap( int count, CItem ** array ) \
  77. : _end(count-1), _item(array) \
  78. { MakeHeap(); } \
  79. CHeap( int count ):_end(-1) \
  80. { _item = new CItem* [count]; } \
  81. ~CHeap(); \
  82. BOOL IsEmpty() {return _end < 0;} \
  83. CItem * Top() { return _item[0]; } \
  84. CItem * RemoveTop(); \
  85. CItem * RemoveTopKey(); \
  86. __forceinline CItem * RemoveBottom() \
  87. { \
  88. if ( _end >= 0 ) \
  89. return _item [_end--]; \
  90. else \
  91. return 0; \
  92. } \
  93. int Count() const { return _end+1;} \
  94. CItem ** GetVector() { return _item;} \
  95. void Add ( CItem * item ); \
  96. void AddKey ( CItem * item, ULONG key ); \
  97. void Reheap (); \
  98. void ReheapKey (); \
  99. void MakeHeap (); \
  100. void MakeHeap ( int count, CItem ** array ) \
  101. { _end=count-1; _item = array; MakeHeap(); } \
  102. void CiExtDump(void *ciExtSelf); \
  103. private: \
  104. int _end; \
  105. CItem ** _item; \
  106. };
  107. //+---------------------------------------------------------------------------
  108. //
  109. // Member: CHeap::CHeap, public
  110. //
  111. // Synopsis: Make a heap from an array
  112. //
  113. // Arguments: [count] -- size of an array
  114. // [array] -- array of pointers to elements
  115. //
  116. // Notes: The size of the heap is fixed. No bound checking is done.
  117. //
  118. // History: 08-May-91 BartoszM Created.
  119. //
  120. //----------------------------------------------------------------------------
  121. //+---------------------------------------------------------------------------
  122. //
  123. // Member: CHeap::CHeap, public
  124. //
  125. // Synopsis: Create an empty heap of maximum size defined by count
  126. //
  127. // Arguments: [count] -- size of an array
  128. //
  129. // Notes: The size of the heap is fixed. No bound checking is done.
  130. //
  131. // History: 08-May-91 BartoszM Created.
  132. //
  133. //----------------------------------------------------------------------------
  134. //+---------------------------------------------------------------------------
  135. //
  136. // Member: CHeap::CHeap, public
  137. //
  138. // Synopsis: Create an empty heap
  139. //
  140. // Notes: To be used only in two-step construction -- see: MakeHeap
  141. //
  142. // History: 08-May-91 BartoszM Created.
  143. //
  144. //----------------------------------------------------------------------------
  145. //+---------------------------------------------------------------------------
  146. //
  147. // Member: CHeap::~CHeap, public
  148. //
  149. // Synopsis: Destroy the heap, delete all the elements.
  150. //
  151. // History: 08-May-91 BartoszM Created.
  152. //
  153. //----------------------------------------------------------------------------
  154. //+---------------------------------------------------------------------------
  155. //
  156. // Member: CHeap::IsEmpty, public
  157. //
  158. // Returns: TRUE if empty, FALSE otherwise
  159. //
  160. // History: 08-May-91 BartoszM Created.
  161. //
  162. //----------------------------------------------------------------------------
  163. //+---------------------------------------------------------------------------
  164. //
  165. // Member: CHeap::Top, public
  166. //
  167. // Returns: Top element or NULL if heap empty
  168. //
  169. // History: 08-May-91 BartoszM Created.
  170. //
  171. //----------------------------------------------------------------------------
  172. //+---------------------------------------------------------------------------
  173. //
  174. // Member: CHeap::RemoveBottom, public
  175. //
  176. // Synopsis: Remove last element.
  177. //
  178. // Returns: Bottom element of NULL if heap empty
  179. //
  180. // Notes: Used as destructive iterator.
  181. //
  182. // History: 08-May-91 BartoszM Created.
  183. //
  184. //----------------------------------------------------------------------------
  185. //+---------------------------------------------------------------------------
  186. //
  187. // Member: CHeap::RemoveTop, public
  188. //
  189. // Synopsis: Removes and returns top element
  190. //
  191. // History: 08-May-91 BartoszM Created.
  192. //
  193. //----------------------------------------------------------------------------
  194. //+---------------------------------------------------------------------------
  195. //
  196. // Member: CHeap::Add, public
  197. //
  198. // Synopsis: Add an element to the heap
  199. //
  200. // Arguments: [item] -- item to be added
  201. //
  202. // History: 08-May-91 BartoszM Created.
  203. //
  204. //----------------------------------------------------------------------------
  205. //+---------------------------------------------------------------------------
  206. //
  207. // Member: CHeap::Reheap, public
  208. //
  209. // Synopsis: Reheap after changing the top element (sifts down)
  210. //
  211. // History: 08-May-91 BartoszM Created.
  212. //
  213. //----------------------------------------------------------------------------
  214. //+---------------------------------------------------------------------------
  215. //
  216. // Member: CHeap::MakeHeap, public
  217. //
  218. // Synopsis: Make an ordered heap out of random array.
  219. //
  220. // History: 08-May-91 BartoszM Created.
  221. //
  222. //----------------------------------------------------------------------------
  223. //+---------------------------------------------------------------------------
  224. //
  225. // Member: CHeap::MakeHeap, public
  226. //
  227. // Synopsis: Make an ordered heap from array.
  228. //
  229. // Arguments: [count] -- size of an array
  230. // [array] -- array of pointers to elements
  231. //
  232. // Notes: Use only in two-step construction!
  233. //
  234. // History: 08-May-91 BartoszM Created.
  235. //
  236. //----------------------------------------------------------------------------
  237. // Macro used by Reheap and MakeHeap (for speed)
  238. #define REHEAP(CHeap, CItem, LessThan, iroot) \
  239. \
  240. CItem * root_item = _item[iroot]; \
  241. int parent, child; \
  242. for ( parent = iroot, child = 2 * iroot + 1; \
  243. child <= _end; \
  244. parent = child, child = 2 * child + 1 ) \
  245. { \
  246. if ( child < _end \
  247. && LessThan ( _item[child+1], _item[child] ) ) \
  248. child++; \
  249. \
  250. if ( ! LessThan ( _item[child], root_item ) ) \
  251. break; \
  252. \
  253. _item [parent] = _item [child]; \
  254. } \
  255. _item [parent] = root_item;
  256. #define REHEAPKEY(CHeap, CItem, LessThan, iroot, GetKey, KeyType) \
  257. \
  258. CItem * root_item = _item[iroot]; \
  259. KeyType root_key; \
  260. if ( -1 != _end ) \
  261. root_key = GetKey( root_item ); \
  262. int parent, child; \
  263. for ( parent = iroot, child = 2 * iroot + 1; \
  264. child <= _end; \
  265. parent = child, child = 2 * child + 1 ) \
  266. { \
  267. if ( child < _end \
  268. && LessThan ( _item[child+1], _item[child] ) ) \
  269. child++; \
  270. \
  271. if ( ! LessThan ( _item[child], root_key ) ) \
  272. break; \
  273. \
  274. _item [parent] = _item [child]; \
  275. } \
  276. _item [parent] = root_item;
  277. //
  278. // Implementation
  279. //
  280. #define IMP_HEAP( CHeap, CItem, LessThan ) \
  281. \
  282. CHeap::~CHeap() \
  283. { \
  284. for ( int i = 0; i <= _end; i++ ) \
  285. delete _item[i]; \
  286. delete _item; \
  287. } \
  288. \
  289. CItem * CHeap::RemoveTop () \
  290. { \
  291. if ( IsEmpty() ) \
  292. return 0; \
  293. CItem * ret = Top(); \
  294. if ( _end >= 0 ) \
  295. { \
  296. _item [0] = _item [_end]; \
  297. _item[_end--] = 0; \
  298. Reheap(); \
  299. } \
  300. return ret; \
  301. } \
  302. \
  303. void CHeap::Add ( CItem * item ) \
  304. { \
  305. _end++; \
  306. int child, parent; \
  307. for ( child = _end, parent = (_end-1)/2; \
  308. child > 0; \
  309. child=parent, parent = (parent-1)/2) \
  310. { \
  311. if ( !LessThan( item, _item[parent] )) \
  312. break; \
  313. _item[child] = _item[parent]; \
  314. } \
  315. _item[child] = item; \
  316. } \
  317. \
  318. void CHeap::Reheap () \
  319. { \
  320. REHEAP (CHeap, CItem, LessThan, 0) \
  321. } \
  322. \
  323. void CHeap::MakeHeap() \
  324. { \
  325. for ( int iroot = ((_end+1)/2) - 1; \
  326. iroot >= 0; iroot-- ) \
  327. { \
  328. REHEAP ( CHeap, CItem, LessThan, iroot)\
  329. } \
  330. }
  331. #define IMP_HEAP_KEY( CHeap, CItem, LessThan, GetKey, KeyType ) \
  332. \
  333. void CHeap::AddKey ( CItem * item, KeyType key ) \
  334. { \
  335. _end++; \
  336. int child, parent; \
  337. for ( child = _end, parent = (_end-1)/2; \
  338. child > 0; \
  339. child=parent, parent = (parent-1)/2) \
  340. { \
  341. if ( !LessThan( key, _item[parent] )) \
  342. break; \
  343. _item[child] = _item[parent]; \
  344. } \
  345. _item[child] = item; \
  346. } \
  347. \
  348. __forceinline void CHeap::ReheapKey () \
  349. { \
  350. REHEAPKEY (CHeap, CItem, LessThan, 0, GetKey, KeyType ) \
  351. } \
  352. \
  353. CItem * CHeap::RemoveTopKey () \
  354. { \
  355. if ( IsEmpty() ) \
  356. return 0; \
  357. CItem * ret = Top(); \
  358. if ( _end >= 0 ) \
  359. { \
  360. _item [0] = _item [_end]; \
  361. _item[_end--] = 0; \
  362. ReheapKey(); \
  363. } \
  364. return ret; \
  365. } \
  366. \