minmaxheap.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810
  1. /****************************************************************************
  2. *
  3. * MODULE: iostream
  4. *
  5. * COPYRIGHT (C) 2007 Laura Toma
  6. *
  7. *
  8. * Iostream is a library that implements streams, external memory
  9. * sorting on streams, and an external memory priority queue on
  10. * streams. These are the fundamental components used in external
  11. * memory algorithms.
  12. * Credits: The library was developed by Laura Toma. The kernel of
  13. * class STREAM is based on the similar class existent in the GPL TPIE
  14. * project developed at Duke University. The sorting and priority
  15. * queue have been developed by Laura Toma based on communications
  16. * with Rajiv Wickremesinghe. The library was developed as part of
  17. * porting Terraflow to GRASS in 2001. PEARL upgrades in 2003 by
  18. * Rajiv Wickremesinghe as part of the Terracost project.
  19. *
  20. * This program is free software; you can redistribute it and/or modify
  21. * it under the terms of the GNU General Public License as published by
  22. * the Free Software Foundation; either version 2 of the License, or
  23. * (at your option) any later version.
  24. *
  25. * This program is distributed in the hope that it will be useful,
  26. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  27. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  28. * General Public License for more details. *
  29. * **************************************************************************/
  30. #ifndef _MINMAXHEAP_H
  31. #define _MINMAXHEAP_H
  32. #include <stdio.h>
  33. #include <assert.h>
  34. #include <stdlib.h>
  35. #include <math.h>
  36. #ifdef log2
  37. #undef log2
  38. #endif
  39. #include <sstream>
  40. #include "mm_utils.h"
  41. #include "ami_config.h" //for SAVE_MEMORY flag
  42. /* this flag is set if we are stingy on memory; in that case 'reset'
  43. deletes the pq memory and the subsequent insert reallocates it; if
  44. the operation following a reset is not an insert or an operation
  45. which does not touch the array A, behaviour is unpredictable (core
  46. dump probably) */
  47. /*****************************************************************
  48. *****************************************************************
  49. *****************************************************************
  50. Priority queue templated on a single type (assumed to be a class with
  51. getPriority() and getValue() implemented);
  52. Supported operations: min, extract_min, insert, max, extract_max in
  53. O(lg n)
  54. *****************************************************************
  55. *****************************************************************
  56. *****************************************************************/
  57. #undef XXX
  58. #define XXX if(0)
  59. #define MY_LOG_DEBUG_ID(x) //inhibit debug printing
  60. //#define MY_LOG_DEBUG_ID(x) LOG_DEBUG_ID(x)
  61. typedef unsigned int HeapIndex;
  62. template <class T>
  63. class BasicMinMaxHeap {
  64. protected:
  65. HeapIndex maxsize;
  66. HeapIndex lastindex; // last used position (0 unused) (?)
  67. T *A;
  68. protected:
  69. /* couple of memory mgt functions to keep things consistent */
  70. static T *allocateHeap(HeapIndex n);
  71. static void freeHeap(T *);
  72. public:
  73. BasicMinMaxHeap(HeapIndex size) : maxsize(size) {
  74. char str[100];
  75. sprintf(str, "BasicMinMaxHeap: allocate %ld\n",
  76. (long)((size+1)*sizeof(T)));
  77. // MEMORY_LOG(str);
  78. lastindex = 0;
  79. MY_LOG_DEBUG_ID("minmaxheap: allocation");
  80. A = allocateHeap(maxsize);
  81. };
  82. virtual ~BasicMinMaxHeap(void) {
  83. MY_LOG_DEBUG_ID("minmaxheap: deallocation");
  84. freeHeap(A);
  85. };
  86. bool empty(void) const { return size() == 0; };
  87. HeapIndex size() const {
  88. assert(A || !lastindex);
  89. return lastindex;
  90. };
  91. T get(HeapIndex i) const { assert(i <= size()); return A[i]; }
  92. //build a heap from an array of elements;
  93. //if size > maxsize, insert first maxsize elements from array;
  94. //return nb of elements that did not fit;
  95. void insert(const T& elt);
  96. bool min(T& elt) const ;
  97. bool extract_min(T& elt);
  98. bool max(T& elt) const;
  99. bool extract_max(T& elt);
  100. //extract all elts with min key, add them and return their sum
  101. bool extract_all_min(T& elt);
  102. void reset();
  103. void clear(); /* mark all the data as deleted, but don't do free */
  104. void destructiveVerify();
  105. void verify();
  106. void print() const;
  107. void print_range() const;
  108. friend ostream& operator<<(ostream& s, const BasicMinMaxHeap<T> &pq) {
  109. HeapIndex i;
  110. s << "[";
  111. for(i = 1; i <= pq.size(); i++) {
  112. s << " " << pq.get(i);
  113. }
  114. s << "]";
  115. return s;
  116. }
  117. protected:
  118. virtual void grow()=0;
  119. private:
  120. long log2(long n) const;
  121. int isOnMaxLevel(HeapIndex i) const { return (log2(i) % 2); };
  122. int isOnMinLevel(HeapIndex i) const { return !isOnMaxLevel(i); };
  123. HeapIndex leftChild(HeapIndex i) const { return 2*i; };
  124. HeapIndex rightChild(HeapIndex i) const { return 2*i + 1; };
  125. int hasRightChild(HeapIndex i) const { return (rightChild(i) <= size()); };
  126. int hasRightChild(HeapIndex i, HeapIndex *c) const { return ((*c=rightChild(i)) <= size()); };
  127. HeapIndex parent(HeapIndex i) const { return (i/2); };
  128. HeapIndex grandparent(HeapIndex i) const { return (i/4); };
  129. int hasChildren(HeapIndex i) const { return (2*i) <= size(); }; // 1 or more
  130. void swap(HeapIndex a, HeapIndex b);
  131. T leftChildValue(HeapIndex i) const;
  132. T rightChildValue(HeapIndex i) const;
  133. HeapIndex smallestChild(HeapIndex i) const;
  134. HeapIndex smallestChildGrandchild(HeapIndex i) const;
  135. HeapIndex largestChild(HeapIndex i) const;
  136. HeapIndex largestChildGrandchild(HeapIndex i) const;
  137. int isGrandchildOf(HeapIndex i, HeapIndex m) const;
  138. void trickleDownMin(HeapIndex i);
  139. void trickleDownMax(HeapIndex i);
  140. void trickleDown(HeapIndex i);
  141. void bubbleUp(HeapIndex i);
  142. void bubbleUpMin(HeapIndex i);
  143. void bubbleUpMax(HeapIndex i);
  144. };
  145. // index 0 is invalid
  146. // index <= size
  147. // ----------------------------------------------------------------------
  148. template <class T>
  149. long BasicMinMaxHeap<T>::log2(long n) const {
  150. long i=-1;
  151. // let log2(0)==-1
  152. while(n) {
  153. n = n >> 1;
  154. i++;
  155. }
  156. return i;
  157. }
  158. // ----------------------------------------------------------------------
  159. template <class T>
  160. void BasicMinMaxHeap<T>::swap(HeapIndex a, HeapIndex b) {
  161. T tmp;
  162. tmp = A[a];
  163. A[a] = A[b];
  164. A[b] = tmp;
  165. }
  166. // ----------------------------------------------------------------------
  167. // child must exist
  168. template <class T>
  169. T BasicMinMaxHeap<T>::leftChildValue(HeapIndex i) const {
  170. HeapIndex p = leftChild(i);
  171. assert(p <= size());
  172. return A[p];
  173. }
  174. // ----------------------------------------------------------------------
  175. // child must exist
  176. template <class T>
  177. T BasicMinMaxHeap<T>::rightChildValue(HeapIndex i) const {
  178. HeapIndex p = rightChild(i);
  179. assert(p <= size());
  180. return A[p];
  181. }
  182. // ----------------------------------------------------------------------
  183. // returns index of the smallest of children of node
  184. // it is an error to call this function if node has no children
  185. template <class T>
  186. HeapIndex BasicMinMaxHeap<T>::smallestChild(HeapIndex i) const {
  187. assert(hasChildren(i));
  188. if(hasRightChild(i) && (leftChildValue(i) > rightChildValue(i))) {
  189. return rightChild(i);
  190. } else {
  191. return leftChild(i);
  192. }
  193. }
  194. // ----------------------------------------------------------------------
  195. template <class T>
  196. HeapIndex BasicMinMaxHeap<T>::largestChild(HeapIndex i) const {
  197. assert(hasChildren(i));
  198. if(hasRightChild(i) && (leftChildValue(i) < rightChildValue(i))) {
  199. return rightChild(i);
  200. } else {
  201. return leftChild(i);
  202. }
  203. }
  204. // ----------------------------------------------------------------------
  205. // error to call on node without children
  206. template <class T>
  207. HeapIndex BasicMinMaxHeap<T>::smallestChildGrandchild(HeapIndex i) const {
  208. HeapIndex p,q;
  209. HeapIndex minpos = 0;
  210. assert(hasChildren(i));
  211. p = leftChild(i);
  212. if(hasChildren(p)) {
  213. q = smallestChild(p);
  214. if(A[p] > A[q]) p = q;
  215. }
  216. // p is smallest of left child, its grandchildren
  217. minpos = p;
  218. if(hasRightChild(i,&p)) {
  219. //p = rightChild(i);
  220. if(hasChildren(p)) {
  221. q = smallestChild(p);
  222. if(A[p] > A[q]) p = q;
  223. }
  224. // p is smallest of right child, its grandchildren
  225. if(A[p] < A[minpos]) minpos = p;
  226. }
  227. return minpos;
  228. }
  229. // ----------------------------------------------------------------------
  230. template <class T>
  231. HeapIndex BasicMinMaxHeap<T>::largestChildGrandchild(HeapIndex i) const {
  232. HeapIndex p,q;
  233. HeapIndex maxpos = 0;
  234. assert(hasChildren(i));
  235. p = leftChild(i);
  236. if(hasChildren(p)) {
  237. q = largestChild(p);
  238. if(A[p] < A[q]) p = q;
  239. }
  240. // p is smallest of left child, its grandchildren
  241. maxpos = p;
  242. if(hasRightChild(i,&p)) {
  243. //p = rightChild(i);
  244. if(hasChildren(p)) {
  245. q = largestChild(p);
  246. if(A[p] < A[q]) p = q;
  247. }
  248. // p is smallest of right child, its grandchildren
  249. if(A[p] > A[maxpos]) maxpos = p;
  250. }
  251. return maxpos;
  252. }
  253. // ----------------------------------------------------------------------
  254. // this is pretty loose - only to differentiate between child and grandchild
  255. template <class T>
  256. int BasicMinMaxHeap<T>::isGrandchildOf(HeapIndex i, HeapIndex m) const {
  257. return (m >= i*4);
  258. }
  259. // ----------------------------------------------------------------------
  260. template <class T>
  261. void BasicMinMaxHeap<T>::trickleDownMin(HeapIndex i) {
  262. HeapIndex m;
  263. bool done = false;
  264. while (!done) {
  265. if (!hasChildren(i)) {
  266. done = true;
  267. return;
  268. }
  269. m = smallestChildGrandchild(i);
  270. if(isGrandchildOf(i, m)) {
  271. if(A[m] < A[i]) {
  272. swap(i, m);
  273. if(A[m] > A[parent(m)]) {
  274. swap(m, parent(m));
  275. }
  276. //trickleDownMin(m);
  277. i = m;
  278. } else {
  279. done = true;
  280. }
  281. } else {
  282. if(A[m] < A[i]) {
  283. swap(i, m);
  284. }
  285. done = true;
  286. }
  287. }//while
  288. }
  289. // ----------------------------------------------------------------------
  290. // unverified
  291. template <class T>
  292. void BasicMinMaxHeap<T>::trickleDownMax(HeapIndex i) {
  293. HeapIndex m;
  294. bool done = false;
  295. while (!done) {
  296. if(!hasChildren(i)) {
  297. done = true;
  298. return;
  299. }
  300. m = largestChildGrandchild(i);
  301. if(isGrandchildOf(i, m)) {
  302. if(A[m] > A[i]) {
  303. swap(i, m);
  304. if(A[m] < A[parent(m)]) {
  305. swap(m, parent(m));
  306. }
  307. //trickleDownMax(m);
  308. i = m;
  309. } else {
  310. done = true;
  311. }
  312. } else {
  313. if(A[m] > A[i]) {
  314. swap(i, m);
  315. }
  316. done = true;
  317. }
  318. } //while
  319. }
  320. // ----------------------------------------------------------------------
  321. template <class T>
  322. void BasicMinMaxHeap<T>::trickleDown(HeapIndex i) {
  323. if(isOnMinLevel(i)) {
  324. trickleDownMin(i);
  325. } else {
  326. trickleDownMax(i);
  327. }
  328. }
  329. // ----------------------------------------------------------------------
  330. template <class T>
  331. void BasicMinMaxHeap<T>::bubbleUp(HeapIndex i) {
  332. HeapIndex m;
  333. m = parent(i);
  334. if(isOnMinLevel(i)) {
  335. if (m && (A[i] > A[m])) {
  336. swap(i, m);
  337. bubbleUpMax(m);
  338. } else {
  339. bubbleUpMin(i);
  340. }
  341. } else {
  342. if (m && (A[i] < A[m])) {
  343. swap(i, m);
  344. bubbleUpMin(m);
  345. } else {
  346. bubbleUpMax(i);
  347. }
  348. }
  349. }
  350. // ----------------------------------------------------------------------
  351. template <class T>
  352. void BasicMinMaxHeap<T>::bubbleUpMin(HeapIndex i) {
  353. HeapIndex m;
  354. m = grandparent(i);
  355. while (m && (A[i] < A[m])) {
  356. swap(i,m);
  357. //bubbleUpMin(m);
  358. i = m;
  359. m = grandparent(i);
  360. }
  361. }
  362. // ----------------------------------------------------------------------
  363. template <class T>
  364. void BasicMinMaxHeap<T>::bubbleUpMax(HeapIndex i) {
  365. HeapIndex m;
  366. m = grandparent(i);
  367. while(m && (A[i] > A[m])) {
  368. swap(i,m);
  369. //bubbleUpMax(m);
  370. i=m;
  371. m = grandparent(i);
  372. }
  373. }
  374. #if(0)
  375. // ----------------------------------------------------------------------
  376. template <class T>
  377. void BasicMinMaxHeap<T>::print_rajiv() const {
  378. HeapIndex i;
  379. ostrstream *ostr = new ostrstream();
  380. *ostr << "[1]";
  381. for(i=1; i<=size(); i++) {
  382. *ostr << " " << A[i];
  383. if(ostr->pcount() > 70) {
  384. cout << ostr->str() << endl;
  385. delete ostr;
  386. ostr = new ostrstream();
  387. *ostr << "[" << i << "]";
  388. }
  389. }
  390. cout << ostr->str() << endl;
  391. }
  392. #endif
  393. // ----------------------------------------------------------------------
  394. template <class T>
  395. void BasicMinMaxHeap<T>::print() const {
  396. cout << "[";
  397. for (unsigned int i=1; i<=size(); i++) {
  398. cout << A[i].getPriority() <<",";
  399. }
  400. cout << "]" << endl;
  401. }
  402. // ----------------------------------------------------------------------
  403. template <class T>
  404. void BasicMinMaxHeap<T>::print_range() const {
  405. cout << "[";
  406. T a, b;
  407. min(a);
  408. max(b);
  409. if (size()) {
  410. cout << a.getPriority() << ".."
  411. << b.getPriority();
  412. }
  413. cout << " (" << size() << ")]";
  414. }
  415. // ----------------------------------------------------------------------
  416. template <class T>
  417. void BasicMinMaxHeap<T>::insert(const T& elt) {
  418. #ifdef SAVE_MEMORY
  419. if (!A) {
  420. MY_LOG_DEBUG_ID("minmaxheap: re-allocation");
  421. A = allocateHeap(maxsize);
  422. }
  423. #endif
  424. if(lastindex == maxsize) grow();
  425. XXX cerr << "insert: " << elt << endl;
  426. lastindex++;
  427. A[lastindex] = elt;
  428. bubbleUp(lastindex);
  429. }
  430. // ----------------------------------------------------------------------
  431. template <class T>
  432. bool BasicMinMaxHeap<T>::extract_min(T& elt) {
  433. assert(A);
  434. if(lastindex == 0) return false;
  435. elt = A[1];
  436. A[1] = A[lastindex];
  437. lastindex--;
  438. trickleDown(1);
  439. return true;
  440. }
  441. // ----------------------------------------------------------------------
  442. //extract all elts with min key, add them and return their sum
  443. template <class T>
  444. bool BasicMinMaxHeap<T>::extract_all_min(T& elt) {
  445. T next_elt;
  446. bool done = false;
  447. //extract first elt
  448. if (!extract_min(elt)) {
  449. return false;
  450. } else {
  451. while (!done) {
  452. //peek at the next min elt to see if matches
  453. if ((!min(next_elt)) ||
  454. !(next_elt.getPriority() == elt.getPriority())) {
  455. done = true;
  456. } else {
  457. extract_min(next_elt);
  458. elt = elt + next_elt;
  459. }
  460. }
  461. }
  462. return true;
  463. }
  464. // ----------------------------------------------------------------------
  465. template <class T>
  466. bool BasicMinMaxHeap<T>::extract_max(T& elt) {
  467. assert(A);
  468. HeapIndex p; // max
  469. if(lastindex == 0) return false;
  470. if(hasChildren(1)) {
  471. p = largestChild(1);
  472. } else {
  473. p = 1;
  474. }
  475. elt = A[p];
  476. A[p] = A[lastindex];
  477. lastindex--;
  478. trickleDown(p);
  479. return true;
  480. }
  481. // ----------------------------------------------------------------------
  482. template <class T>
  483. bool BasicMinMaxHeap<T>::min(T& elt) const {
  484. assert(A);
  485. if(lastindex == 0) return false;
  486. elt = A[1];
  487. return true;
  488. }
  489. // ----------------------------------------------------------------------
  490. template <class T>
  491. bool BasicMinMaxHeap<T>::max(T& elt) const {
  492. assert(A);
  493. HeapIndex p; // max
  494. if(lastindex == 0) return false;
  495. if(hasChildren(1)) {
  496. p = largestChild(1);
  497. } else {
  498. p = 1;
  499. }
  500. elt = A[p];
  501. return true;
  502. }
  503. // ----------------------------------------------------------------------
  504. //free memory if SAVE_MEMORY is set
  505. template <class T>
  506. void BasicMinMaxHeap<T>::reset() {
  507. #ifdef SAVE_MEMORY
  508. assert(empty());
  509. MY_LOG_DEBUG_ID("minmaxheap: deallocation");
  510. freeHeap(A);
  511. A = NULL;
  512. #endif
  513. }
  514. // ----------------------------------------------------------------------
  515. template <class T>
  516. void
  517. BasicMinMaxHeap<T>::clear() {
  518. lastindex = 0;
  519. }
  520. // ----------------------------------------------------------------------
  521. template <class T>
  522. T *
  523. BasicMinMaxHeap<T>::allocateHeap(HeapIndex n) {
  524. T *p;
  525. #ifdef USE_LARGEMEM
  526. p = (T*)LargeMemory::alloc(sizeof(T) * (n+1));
  527. #else
  528. p = new T[n+1];
  529. #endif
  530. return p;
  531. }
  532. // ----------------------------------------------------------------------
  533. template <class T>
  534. void
  535. BasicMinMaxHeap<T>::freeHeap(T *p) {
  536. if (p) {
  537. #ifdef USE_LARGEMEM
  538. LargeMemory::free(p);
  539. #else
  540. delete [] p;
  541. #endif
  542. }
  543. }
  544. // ----------------------------------------------------------------------
  545. template <class T>
  546. void
  547. BasicMinMaxHeap<T>::destructiveVerify() {
  548. HeapIndex n = size();
  549. T val, prev;
  550. bool ok;
  551. if(!n) return;
  552. XXX print();
  553. /* make sure that min works */
  554. extract_min(prev);
  555. for(HeapIndex i=1; i<n; i++) {
  556. ok = min(val);
  557. assert(ok);
  558. XXX cerr << i << ": " << val << endl;
  559. if(val.getPriority() < prev.getPriority()) { // oops!
  560. print();
  561. cerr << "n=" << n << endl;
  562. cerr << "val=" << val << endl;
  563. cerr << "prev=" << prev << endl;
  564. cerr << "looks like minmaxheap.min is broken!!" << endl;
  565. assert(0);
  566. return;
  567. }
  568. prev = val;
  569. ok = extract_min(val);
  570. assert(ok);
  571. assert(prev == val);
  572. }
  573. }
  574. // ----------------------------------------------------------------------
  575. template <class T>
  576. void
  577. BasicMinMaxHeap<T>::verify() {
  578. long n = size();
  579. T *dup;
  580. if(!n) return;
  581. dup = allocateHeap(maxsize);
  582. for(HeapIndex i=0; i<n+1; i++) {
  583. dup[i] = A[i];
  584. }
  585. destructiveVerify();
  586. freeHeap(A);
  587. /* restore the heap */
  588. A = dup;
  589. lastindex = n;
  590. }
  591. // ----------------------------------------------------------------------
  592. // ----------------------------------------------------------------------
  593. template <class T>
  594. class MinMaxHeap : public BasicMinMaxHeap<T> {
  595. public:
  596. MinMaxHeap(HeapIndex size) : BasicMinMaxHeap<T>(size) {};
  597. virtual ~MinMaxHeap() {};
  598. bool full(void) const { return this->size() >= this->maxsize; };
  599. HeapIndex get_maxsize() const { return this->maxsize; };
  600. HeapIndex fill(T* arr, HeapIndex n);
  601. protected:
  602. virtual void grow() { fprintf(stderr, "MinMaxHeap::grow: not implemented\n"); assert(0); exit(1); };
  603. };
  604. // ----------------------------------------------------------------------
  605. //build a heap from an array of elements;
  606. //if size > maxsize, insert first maxsize elements from array;
  607. //return nb of elements that did not fit;
  608. template <class T>
  609. HeapIndex MinMaxHeap<T>::fill(T* arr, HeapIndex n) {
  610. HeapIndex i;
  611. //heap must be empty
  612. assert(this->size()==0);
  613. for (i = 0; !full() && i<n; i++) {
  614. this->insert(arr[i]);
  615. }
  616. if (i < n) {
  617. assert(i == this->maxsize);
  618. return n - i;
  619. } else {
  620. return 0;
  621. }
  622. }
  623. #define MMHEAP_INITIAL_SIZE 1024
  624. template <class T>
  625. class UnboundedMinMaxHeap : public BasicMinMaxHeap<T> {
  626. public:
  627. UnboundedMinMaxHeap() : BasicMinMaxHeap<T>(MMHEAP_INITIAL_SIZE) {};
  628. UnboundedMinMaxHeap(HeapIndex size) : BasicMinMaxHeap<T>(size) {};
  629. virtual ~UnboundedMinMaxHeap() {};
  630. protected:
  631. virtual void grow();
  632. };
  633. template <class T>
  634. void UnboundedMinMaxHeap<T>::grow() {
  635. T *old = this->A;
  636. this->maxsize *= 2;
  637. assert(this->maxsize > 0);
  638. if(old) {
  639. HeapIndex n = this->size();
  640. this->A = this->allocateHeap(this->maxsize); /* allocate a new array */
  641. /* copy over the old values */
  642. assert(this->maxsize > n);
  643. for(HeapIndex i=0; i<=n; i++) { /* why extra value? -RW */
  644. this->A[i] = old[i];
  645. }
  646. this->freeHeap(old); /* free up old storage */
  647. }
  648. }
  649. #endif