Open
Graph Drawing
Framework

 v.2012.05
 

BinaryHeap.h
Go to the documentation of this file.
00001 /*
00002  * $Revision: 2299 $
00003  * 
00004  * last checkin:
00005  *   $Author: gutwenger $ 
00006  *   $Date: 2012-05-07 15:57:08 +0200 (Mon, 07 May 2012) $ 
00007  ***************************************************************/
00008  
00041 #ifdef _MSC_VER
00042 #pragma once
00043 #endif
00044 
00045 #ifndef OGDF_BINARY_HEAP_H
00046 #define OGDF_BINARY_HEAP_H
00047 
00048 #include<ogdf/basic/Array.h>
00049 
00050 namespace ogdf {
00051 
00052     
00053 
00054 // using min heaps 
00055 template <class X, class Priority=double, class INDEX=int>
00056 class OGDF_EXPORT BinaryHeap {
00057     
00058 public:
00059 
00060     class Element {
00061 
00062         friend class BinaryHeap<X, Priority, INDEX>;
00063 
00064         private:    
00065             Priority priority;
00066             X elem;
00067             INDEX backIdx ; // the position in element array
00068 
00069             // empty constructor
00070             Element() { }
00071             
00072             // construct element with object and priority
00073             Element(X x, Priority prior) : priority(prior), elem(x) { }
00074 
00075             //copy constructor
00076             Element(const Element &origElem): priority(origElem.priority), elem(origElem.elem), backIdx(origElem.backIdx) { }               
00077 
00078         public: 
00079                 
00080             //return the priority
00081             Priority getPriority() const { return priority; }
00082                 
00083             // return reference to elem
00084             const X &getElement() const { return elem; }            
00085 
00086             // return the position of this element in the heap array
00087             INDEX getPos() const { return backIdx; }
00088     };
00089 
00090     
00092     BinaryHeap(INDEX c) : data(1, c, 0), s(0) { }
00093 
00095     ~BinaryHeap() {
00096         for (INDEX i = 1; i <= s; ++i) {            
00097             delete data[i];
00098             data[i] = 0;
00099         }       
00100     }
00101 
00103     bool empty() const { return s == 0; }
00104     
00106     INDEX size() const { return s; }    
00107     
00108     
00109     
00111     void decPriority(const Element &elem, // handle to the element
00112                             Priority prior // new priority, must be smaller then the old value
00113                             ) {
00114         INDEX i = elem.backIdx;
00115 
00116         OGDF_ASSERT(i <= s);
00117 
00118         if (data[i]->getPriority() < prior)
00119             throw "New key is greater than current key.";
00120         
00121         data[i]->priority = prior; 
00122         while (i > 1 && (data[getParent(i)]->getPriority() > data[i]->getPriority()) ) {
00123             swap(i, getParent(i));
00124             i = getParent(i);
00125         }       
00126     }
00127 
00129     const Element & insert(X obj, Priority prior) {     
00130         Element *h_elem = new Element (obj, prior); 
00131         ++s;        
00132         if (s == capacity())
00133             data.grow(capacity(), 0); // double the size
00134         h_elem->backIdx = s; // store the position      
00135         data[s] = h_elem;       
00136         INDEX i = s;
00137         while ( (i > 1) && ( data[getParent(i)]->getPriority() > data[i]->getPriority()) ) {
00138             swap(i, getParent(i));
00139             i = getParent(i);
00140         }       
00141         return *h_elem;
00142     }   
00143 
00145     const Element & push(X obj, Priority prior) {
00146         return insert(obj, prior);
00147     }
00148 
00150     const X & getMin() const {              
00151         return data[1]->getElement();
00152     } 
00153 
00155     const X & top() const {
00156         return getMin();
00157     }
00158 
00160     X extractMin() {
00161         if (empty())
00162             throw "Heap underflow error!";  
00163 
00164         Element copy = *data[1];    
00165         Element *p = data[1];
00166         swap(1, s);     
00167         --s;
00168         delete p;
00169         minHeapify(1);      
00170         data[s+1] = 0;
00171         return copy.getElement();
00172     }
00173         
00175     X pop() {
00176         return extractMin();
00177     }
00178 
00180     void clear() {
00181         for (INDEX i = 1; i <= s; ++i) {            
00182             delete data[i];
00183             data[i] = 0;
00184         }
00185         s = 0;
00186     }
00187 
00189     const X & operator[](INDEX idx) const {
00190         return data[idx+1]->getElement();
00191     }
00192 
00193 
00194     private :
00195 
00196     Array<Element *, INDEX> data; // heap array starts at index 1               
00197     INDEX s; // current number of elements 
00198     
00200     INDEX capacity() const { return data.size(); }
00201     
00202     void swap(INDEX pos1, INDEX pos2) {
00203         Element *tmp = data[pos1];
00204         data[pos1] = data[pos2];
00205         data[pos2] = tmp;
00206         // update the position
00207         data[pos2]->backIdx = pos2;
00208         data[pos1]->backIdx = pos1;
00209     } 
00210     
00211 
00212     
00213     void minHeapify(INDEX pos) {
00214         INDEX l = getLeft(pos);
00215         INDEX r = getRight(pos);
00216         INDEX smallest;
00217         if (l <= size() && data[l]->getPriority() < data[pos]->getPriority() )
00218             smallest = l;
00219         else
00220             smallest = pos;
00221         if (r <= size() && data[r]->getPriority() < data[smallest]->getPriority())
00222             smallest = r;
00223         if (smallest != pos) {
00224             swap(pos, smallest);
00225             minHeapify(smallest);
00226         } 
00227     }
00228     
00229 
00230     INDEX getParent(INDEX pos) const {return pos/2;}
00231 
00232     INDEX getLeft(INDEX pos) const {return pos*2;}
00233 
00234     INDEX getRight(INDEX pos) const {return pos*2+1;}   
00235 
00236 };
00237 
00238 }//namespace ogdf
00239 
00240 #endif