minmaxheap.h 18 KB

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