123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567 |
- /****************************************************************************
- *
- * MODULE: iostream
- *
- * COPYRIGHT (C) 2007 Laura Toma
- *
- *
- * Iostream is a library that implements streams, external memory
- * sorting on streams, and an external memory priority queue on
- * streams. These are the fundamental components used in external
- * memory algorithms.
- * Credits: The library was developed by Laura Toma. The kernel of
- * class STREAM is based on the similar class existent in the GPL TPIE
- * project developed at Duke University. The sorting and priority
- * queue have been developed by Laura Toma based on communications
- * with Rajiv Wickremesinghe. The library was developed as part of
- * porting Terraflow to GRASS in 2001. PEARL upgrades in 2003 by
- * Rajiv Wickremesinghe as part of the Terracost project.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details. *
- * **************************************************************************/
- #ifndef _PQHEAP_H
- #define _PQHEAP_H
- #include <assert.h>
- #include <stdlib.h>
- #define PQHEAP_MEM_DEBUG if(0)
- //HEAPSTATUS can be defined at compile time
- //this flag is currently off; we used it at some point for checking
- //how many times is each element in the heap accessed or something
- //like that
- #ifdef HEAPSTATUS
- static const int PAGESIZE = 1024;
- #endif
- // Helper functions for navigating through a binary heap.
- /* for simplicity the heap structure is slightly modified as:
- 0
- |
- 1
- /\
- 2 3
- /\ /\
- 4 5 6 7
- */
- // The children of an element of the heap.
- static inline unsigned int heap_lchild(unsigned int index) {
- return 2 * index;
- }
- static inline unsigned int heap_rchild(unsigned int index) {
- return 2 * index + 1;
- }
- // The parent of an element.
- static inline unsigned int heap_parent(unsigned int index) {
- return index >> 1;
- }
- // return minimum of two integers
- static unsigned int mymin(unsigned int a, unsigned int b) {
- return (a<=b)? a:b;
- }
- /**************************************************************
- ***************************************************************
- ***************************************************************
- Priority queue templated on a single type
- assume T to be a class with getPriority() and getValue() implemented;
- Supported operations: min, extract_min, insert in O(lg n)
- ***************************************************************
- ***************************************************************
- ***************************************************************/
- template <class T>
- class pqheap_t1 {
- // A pointer to an array of elements
- T* elements;
-
- // The number of elements currently in the queue.
- unsigned int cur_elts;
-
- // The maximum number the queue can hold.
- unsigned int max_elts;
- private:
- void heapify(unsigned int root);
- public:
- inline pqheap_t1(unsigned int size);
-
- //build heap from an array of elements; array a is REUSED, and NOT
- //COPIED, for efficiency; it'd better not be used after this
- //outside!!!
- inline pqheap_t1(T* a, unsigned int size);
- inline ~pqheap_t1(void);
- //build a heap from an array of elements;
- //if size > max_elts, insert first maxsize elements from array;
- //return nb of elements that did not fit;
- unsigned int fill(T* a, unsigned int size);
- // Is it full?
- inline bool full(void);
- //Is it empty?
- inline bool empty(void);
- inline bool is_empty() { return empty(); };
- // How many elements?
- inline unsigned int num_elts(void);
-
- // How many elements? sorry - i could never remember num_elts
- inline unsigned int size(void) const { return cur_elts; };
-
- // Min
- inline bool min(T& elt);
- T min();
- // Extract min and set elt = min
- inline bool extract_min(T& elt);
- //extract all elts with min key, add them and return their sum
- inline bool extract_all_min(T& elt);
- //delete min; same as extract_min, but ignore the value extracted
- inline bool delete_min();
- // Insert
- inline bool insert(const T& elt);
- //Delete the current minimum and insert the new item x;
- //the minimum item is lost (i.e. not returned to user);
- //needed to optimize merge
- inline void delete_min_and_insert(const T &x);
- //this function is a dirty way to allow building faster the heap
- //in case we build it from a sorted array; in that case we dont need
- //to 'insert' and then 'heapify', but it is enough to 'set'
- void set(long i, T& elt);
- //print
- inline friend ostream& operator<<(ostream& s, const pqheap_t1<T> &pq) {
- s << "PQ: "; s.flush();
- for (unsigned int i=0; i< mymin(10, pq.cur_elts); i++) {
- s << "["
- //<< pq.elements[i].getPriority() << ","
- //<< pq.elements[i].getValue()
- << pq.elements[i]
- << "]";
- }
- return s;
- }
- //print
- void print();
- //print
- void print_range();
- #ifdef HEAPSTATUS
- inline void heapstatus(int d);
- inline void heaptouch(unsigned int pos);
- unsigned int *numtouch;
- #endif
- };
- //************************************************************/
- template <class T>
- inline
- pqheap_t1<T>::pqheap_t1(unsigned int size) {
- elements = new T [size];
- cout << "pqheap_t1: register memory\n";
- cout.flush();
- PQHEAP_MEM_DEBUG cout << "pqheap_t1::pq_heap_t1: allocate\n";
- // PQHEAP_MEM_DEBUG MMmanager.print();
-
- if (!elements) {
- cerr << "could not allocate priority queue: insufficient memory..\n";
- exit(1);
- }
- assert(elements);
-
- max_elts = size;
- cur_elts = 0;
-
- #ifdef HEAPSTATUS
- numtouch = new unsigned int[size/PAGESIZE];
- assert(numtouch);
- for(int i=0; i<size/PAGESIZE; i++) {
- numtouch[i] = 0;
- }
- #endif
- }
- //************************************************************/
- /* (this constructor is a bit nasty) Build heap from an array of
- elements; array a is reused, and not copied, for efficiency; it'd
- better not be used after this outside!!! */
- template <class T>
- inline
- pqheap_t1<T>::pqheap_t1(T* a, unsigned int size) {
- {
- static int flag = 0;
- if(!flag) {
- cerr << "Using slow build in pqheap_t1" << endl;
- flag = 1;
- }
- }
- elements = a;
- max_elts = size;
- cur_elts = size;
- if (max_elts) {
- for (int i = heap_parent(max_elts-1); i>=0; i--) {
- //cout << "heapify i=" << i<<"\n";
- heapify(i);
- }
- }
- }
- //************************************************************/
- template <class T>
- inline
- pqheap_t1<T>::~pqheap_t1() {
- #ifdef HEAPSTATUS
- cout << endl << "pagesize = " << PAGESIZE << endl;
- cout << "max_elts = " << max_elts << endl;
- unsigned int n = max_elts / PAGESIZE;
- for(unsigned int i=0; i<n; i++) {
- cout << form("PQTEMP %d\t%d", i, numtouch[i]) << endl;
- }
- delete [] numtouch;
- #endif
-
- delete [] elements;
- cur_elts = 0;
- max_elts = 0;
- return;
- }
-
- //************************************************************/
- //build a heap from an array of elements;
- //if size > max_elts, insert first maxsize elements from array;
- //return nb of elements that did not fit;
- template <class T>
- inline unsigned int
- pqheap_t1<T>::fill(T* a, unsigned int size) {
- unsigned int i;
- assert(cur_elts == 0);
- for (i = 0; i<size; i++) {
- if (!insert(a[i])) {
- break;
- }
- }
- if (i < size) {
- assert(i == max_elts);
- return size - i;
- } else {
- return 0;
- }
- }
- //************************************************************/
- template <class T>
- inline bool
- pqheap_t1<T>::full(void) {
- return cur_elts == max_elts;
- }
- //************************************************************/
- template <class T>
- inline bool
- pqheap_t1<T>::empty(void) {
- return cur_elts == 0;
- }
- //************************************************************/
- template <class T>
- inline unsigned int
- pqheap_t1<T>::num_elts(void) {
- return cur_elts;
- }
- //************************************************************/
- template <class T>
- inline bool
- pqheap_t1<T>::min(T& elt) {
- if (!cur_elts) {
- return false;
- }
- elt = elements[0];
- return true;
- }
- //************************************************************/
- template <class T>
- T
- pqheap_t1<T>::min() {
- T elt;
- if(min(elt)) {
- return elt;
- } else {
- cerr << "unguarded min failed" << endl;
- assert(0);
- exit(1);
- }
- return elt;
- }
- //************************************************************/
- //this function is a dirty hack to allow building faster the heap
- //in case we build it from a sorted array; in thiat case we dont need
- //to 'insert' and then 'heapify', but it is enough to 'set'
- template <class T>
- inline void
- pqheap_t1<T>::set(long i, T& elt) {
- //must always set precisely the next element
- assert(i == cur_elts);
- elements[i] = elt;
- cur_elts++;
- }
- //************************************************************/
- #ifdef HEAPSTATUS
- template <class T>
- inline void pqheap_t1<T>::heaptouch(unsigned int pos) {
- numtouch[pos/PAGESIZE]++;
- assert(numtouch[pos/PAGESIZE] > 0);
- }
- #endif
- #ifdef HEAPSTATUS
- template <class T>
- inline void pqheap_t1<T>::heapstatus(int d) {
- static int count = 0;
- static int delta = 0;
-
- delta += d;
- count++;
-
- if((count % 10000) == 0) {
- cout << endl << form("PQHEAP %d\t%d", cur_elts, delta) << endl;
- count = 0;
- delta = 0;
- }
- }
- #endif
- //************************************************************/
- template <class T>
- inline bool
- pqheap_t1<T>::extract_min(T& elt) {
- if (!cur_elts) {
- return false;
- }
- elt = elements[0];
- elements[0] = elements[--cur_elts];
- heapify(0);
-
- #ifdef HEAPSTATUS
- heaptouch(cur_elts);
- heaptouch(0);
- heapstatus(-1);
- #endif
-
- return true;
- }
- //************************************************************/
- //extract all elts with min key, add them and return their sum
- template <class T>
- inline bool
- pqheap_t1<T>::extract_all_min(T& elt) {
-
- T next_elt;
- bool done = false;
-
- //extract first elt
- if (!extract_min(elt)) {
- return false;
- } else {
- while (!done) {
- //peek at the next min elt to see if matches
- if ((!min(next_elt)) ||
- !(next_elt.getPriority() == elt.getPriority())) {
- done = true;
- } else {
- extract_min(next_elt);
- elt = elt + next_elt;
- }
- }
- }
- return true;
- }
- //************************************************************/
- template <class T>
- inline bool
- pqheap_t1<T>::delete_min() {
- T dummy;
- return extract_min(dummy);
- }
- //************************************************************/
- template <class T>
- inline bool
- pqheap_t1<T>::insert(const T& elt) {
- unsigned int ii;
-
- if (full()) {
- return false;
- }
-
- for (ii = cur_elts++;
- ii && (elements[heap_parent(ii)].getPriority() > elt.getPriority());
- ii = heap_parent(ii)) {
- elements[ii] = elements[heap_parent(ii)];
- }
- elements[ii] = elt;
-
- #ifdef HEAPSTATUS
- heaptouch(ii);
- heapstatus(+1);
- #endif
-
- return true;
- }
- //************************************************************/
- template <class T>
- inline void
- pqheap_t1<T>::heapify(unsigned int root) {
- unsigned int min_index = root;
- unsigned int lc = heap_lchild(root);
- unsigned int rc = heap_rchild(root);
-
- #ifdef HEAPSTATUS
- // already did the root, so dont do it again
- if(lc < cur_elts) {
- heaptouch(lc);
- }
- if(rc < cur_elts) {
- heaptouch(rc);
- }
- #endif
- if ((lc < cur_elts) &&
- ((elements[lc].getPriority()) < elements[min_index].getPriority())) {
- min_index = lc;
- }
- if ((rc < cur_elts) &&
- ((elements[rc].getPriority()) < elements[min_index].getPriority())) {
- min_index = rc;
- }
-
- if (min_index != root) {
- T tmp_q = elements[min_index];
-
- elements[min_index] = elements[root];
- elements[root] = tmp_q;
-
- heapify(min_index);
- }
- }
- //************************************************************/
- //Delete the current minimum and insert the new item;
- //the minimum item is lost (i.e. not returned to user);
- //needed to optimize merge
- template <class T>
- inline void
- pqheap_t1<T>::delete_min_and_insert(const T &x) {
- assert(cur_elts);
- elements[0] = x;
- heapify(0);
- }
- /************************************************************/
- template <class T>
- void pqheap_t1<T>::print() {
- cout << "[";
- for (unsigned int i=0; i<cur_elts; i++) {
- cout << elements[i].getPriority().field1() <<",";
- }
- cout << "]";
- }
- /************************************************************/
- template <class T>
- void pqheap_t1<T>::print_range() {
- cout << "[";
- T a, b;
- min(a);
- max(b);
- if (cur_elts) {
- cout << a.getPriority().field1() << ".."
- << b.getPriority().field1();
- }
- cout << " (" << cur_elts << ")]";
- }
- #endif // _PQUEUE_HEAP_H
|