Open
Graph Drawing
Framework

 v.2012.05
 

BinaryHeap2.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  
00043 #ifdef _MSC_VER
00044 #pragma once
00045 #endif
00046 
00047 #ifndef OREAS_BINARY_HEAP2_H
00048 #define OREAS_BINARY_HEAP2_H
00049 
00050 #include <ogdf/basic/HeapBase.h>
00051 
00052 namespace ogdf {
00053 
00098 //to allow directobject adress, a pointer to an integer storage
00099 //can be provided, where the array index is updated by the 
00100 //heap class
00101     
00102 
00103 template <class key, class HeapObject>
00104 class BinaryHeap2 : public HeapBase<key, HeapObject>
00105 {
00106 public:
00108     BinaryHeap2(int startSize = 128);
00109 
00110     //copy Constructor, todo
00111     //BinaryHeap2(const BinaryHeap2& source);
00112 
00113     // Destructor, deletes the heap array.
00114     virtual ~BinaryHeap2() {
00115         if (m_heapArray) delete[] m_heapArray;
00116     }//destructor
00117 
00118 
00120     const BinaryHeap2& operator=(const BinaryHeap2<key, HeapObject>& rhs);
00121 
00122     //------------------------------------------------------------
00123     //modification: 
00124 
00126     void insert(HeapObject& obj, key& p, int* keyUpdate = 0);
00127     
00129     virtual void makeHeap();
00130     //delete
00131     //it is not clear how a delete without explicit
00132     //given heapentry pointer  should behave, e.g. if equal values
00133     //for objects are allowed 
00134 
00136     // arraySize is decreased if size < 1/3arraySize (amortized runtime O(1))
00137     HeapObject extractMin();
00138 
00140     // use updated m_foreign position index to address entry for decreasekey
00141     virtual void decreaseKey(int index, key priority);
00142     //TODO: version mit Aenderungswert statt absolutem Wert
00143 
00144     //--------------------------------------------------------------
00145     //const access functions
00146 
00148     HeapObject minRet() const {return m_heapArray[1].m_object;}
00149 
00150     key getPriority(int index) const
00151     {
00152         OGDF_ASSERT( (index > 0) && (index <= HeapBase<key,HeapObject>::m_size) );
00153         return m_heapArray[index].m_priority;
00154     }//getPriority
00155 
00157     int capacity() const { return m_arraySize; }
00158 
00160     int size() const { return HeapBase<key,HeapObject>::m_size; }
00161 
00163     int empty() const { return HeapBase<key,HeapObject>::empty(); }
00164 
00166 
00170     void clear();
00171 
00172 protected:
00174     void siftUp(int pos);
00175 
00177     void siftDown(int pos);
00178 
00179     //----------------------------------------------------------
00180     //modelling the binary tree structure on the data array
00181     //array position 0 is left empty, positions are from 1..m_size
00183     int parentIndex(int num)
00184     {
00185         OGDF_ASSERT(num>0);
00186         return num/2;
00187     }//parent
00188 
00190     int leftChildIndex(int num)
00191     {
00192         OGDF_ASSERT(num>0);
00193         return 2*num;
00194     }//leftChild
00195 
00197     int rightChildIndex(int num)
00198     {
00199         OGDF_ASSERT(num>0);
00200         return 2*num+1;
00201     }//rightChild
00202 
00204     bool hasLeft(int num)
00205     {
00206         OGDF_ASSERT(num>0);
00207         return (leftChildIndex(num) <= HeapBase<key,HeapObject>::m_size);
00208     }
00209 
00211     bool hasRight(int num)
00212     {
00213         OGDF_ASSERT(num>0);
00214         return (rightChildIndex(num) <= HeapBase<key,HeapObject>::m_size);
00215     }
00216 
00217     //----------------------------------------------------------
00218     //helper functions for internal maintainance
00219     int arrayBound(int arraySize) {return arraySize+1;}
00220     int higherArrayBound(int arraySize) {return 2*arraySize+1;}
00221     int higherArraySize(int arraySize) {return 2*arraySize;}
00222     int lowerArrayBound(int arraySize) {return arraySize/2+1;}
00223     int lowerArraySize(int arraySize) {return arraySize/2;}
00224     
00225     void init(int initSize);
00226 
00227 private:
00228     //holding object and priority key
00229     struct HeapEntry
00230     {
00231       key m_priority;
00232       HeapObject m_object;
00233 
00234       //we maintain positions during operations
00235       int m_pos; 
00236       int* m_foreignPos; //storage structure given by user
00237 
00239       HeapEntry() {m_priority = 0; 
00240                    m_pos = 0;
00241                    m_foreignPos = 0;
00242       }
00243 
00245 
00249       HeapEntry(key k, const HeapObject& ob) {m_priority = k; m_object = ob;
00250         m_foreignPos = 0;
00251         //m_pos = ob.m_pos;
00252       }
00253 
00255 
00261       HeapEntry(key k, const HeapObject& ob, int pos, int* fp) 
00262       {
00263           m_priority = k; 
00264           m_object = ob;
00265           if (fp == 0) m_foreignPos = 0;
00266           else m_foreignPos = fp;
00267           m_pos = pos;
00268       }
00269     };
00270 
00271     HeapEntry* m_heapArray; //dynamically maintained array of heapentries
00272 
00273     //in addition to m_size, the inherited number of objects from class HeapBase,
00274     //we store the actual size of the array, valid array object positions
00275     //are from 1 to m_size
00276     int m_arraySize; //current size of the heap
00277 
00278     int m_startSize; //(decide: optionally??) used to check reallocation bound
00279 
00280 };//BinaryHeap2
00281 
00282 
00283 
00284 } //namespace oreas
00285 
00286 //**************************************************************
00287 //implementation
00288 //**************************************************************
00289 
00290 #include <ogdf/basic/basic.h>
00291 
00292 namespace ogdf {
00293 
00294 //**************************************************************
00295 //constructor and initialization
00296 template <class key, class HeapObject>
00297 BinaryHeap2<key, HeapObject>::BinaryHeap2(int startSize)
00298 : HeapBase<key, HeapObject>()
00299 {
00300     init(startSize);
00301 }//constructor
00302 
00303 template <class key, class HeapObject>
00304 void BinaryHeap2<key, HeapObject>::init(int initSize)
00305 {
00306     //create an array of HeapEntry Elements
00307     m_arraySize = initSize;
00308     m_heapArray = new HeapEntry[arrayBound(m_arraySize)]; //start at 1
00309 
00310     m_startSize = initSize;
00311 
00312     HeapBase<key,HeapObject>::m_size = 0;
00313 }
00314 
00315 template <class key, class HeapObject>
00316 void BinaryHeap2<key, HeapObject>::clear()
00317 {
00318     if (m_heapArray) delete[] m_heapArray;
00319     init(m_startSize);
00320 }
00321 
00322 //**************************************************************
00323 //element shifting operations
00324 //restore heap property by finding correct position for object
00325 //at position pos on higher levels, pos is given as array index (1..m_size)
00326 //updates array index values
00327 template <class key, class HeapObject>
00328 void BinaryHeap2<key, HeapObject>::siftUp(int pos)
00329 {
00330     OGDF_ASSERT( (pos > 0) && (pos <= HeapBase<key,HeapObject>::m_size) )
00331 
00332     if (pos == 1) 
00333     {
00334         m_heapArray[1].m_pos = 1;
00335         if (m_heapArray[1].m_foreignPos != 0) //address is defined
00336             *(m_heapArray[1].m_foreignPos) = 1;
00337         return;//nothing to do
00338     }
00339 
00340     HeapEntry tempEntry = m_heapArray[pos];
00341     int run = pos;
00342     while ( (parentIndex(run) >= 1) && 
00343             (m_heapArray[parentIndex(run)].m_priority > tempEntry.m_priority) )
00344     {
00345         m_heapArray[run] = m_heapArray[parentIndex(run)];
00346         if (m_heapArray[run].m_foreignPos != 0) *(m_heapArray[run].m_foreignPos) = run;
00347         run = parentIndex(run);
00348     }//while
00349 
00350     m_heapArray[run] = tempEntry;
00351     m_heapArray[run].m_pos = run;
00352     if (m_heapArray[run].m_foreignPos != 0) *(m_heapArray[run].m_foreignPos) = run;
00353 
00354 
00355 }//siftup
00356 
00357 //restore heap property by finding correct position for object
00358 //at position pos on lower levels, updates array index values
00359 template <class key, class HeapObject>
00360 void BinaryHeap2<key, HeapObject>::siftDown(int pos)
00361 {
00362     OGDF_ASSERT( (pos > 0) && (pos <= HeapBase<key,HeapObject>::m_size) );
00363 
00364     if (pos >= int(HeapBase<key,HeapObject>::m_size/2)+1) 
00365     {
00366         m_heapArray[pos].m_pos = pos;
00367         if (m_heapArray[pos].m_foreignPos != 0) *(m_heapArray[pos].m_foreignPos) = pos;
00368         return; //leafs cant move down
00369     }//if leaf
00370 
00371     key sPrio = getPriority(pos);
00372     int sIndex = pos;
00373     
00374     if (hasLeft(pos) && (getPriority(leftChildIndex(pos)) < sPrio) )
00375     {
00376         sIndex = leftChildIndex(pos);
00377         sPrio = getPriority(leftChildIndex(pos));
00378     }//if left child smaller
00379     if (hasRight(pos) && (getPriority(rightChildIndex(pos)) < sPrio) )
00380     {
00381         sIndex = rightChildIndex(pos);
00382         sPrio = getPriority(rightChildIndex(pos));
00383     }//if right child smaller
00384       
00385     if (sIndex != pos)
00386     {
00387         HeapEntry tempEntry = m_heapArray[pos]; 
00388         m_heapArray[pos] = m_heapArray[sIndex];
00389         m_heapArray[sIndex] = tempEntry;
00390 
00391         //update both index entries
00392         m_heapArray[pos].m_pos = pos;
00393         if (m_heapArray[pos].m_foreignPos != 0) *(m_heapArray[pos].m_foreignPos) = pos;
00394         m_heapArray[sIndex].m_pos = sIndex;
00395         if (m_heapArray[sIndex].m_foreignPos != 0) *(m_heapArray[sIndex].m_foreignPos) = sIndex;
00396 
00397         siftDown(sIndex); //TODO: dont use recursion
00398     }//if sift necessary
00399     else  //update in case of new elements (non-insert)
00400     {
00401         m_heapArray[pos].m_pos = pos;
00402         if (m_heapArray[pos].m_foreignPos != 0) *(m_heapArray[pos].m_foreignPos) = pos;
00403     }//else
00404     
00405 
00406 }//siftdown
00407 
00408 
00409 template <class key, class HeapObject>
00410 void BinaryHeap2<key, HeapObject>::makeHeap()
00411 {
00412   //only needed if insertion is not done over insert 
00413   //(if we allow array parameter in constructor)
00414   for (int i=HeapBase<key,HeapObject>::m_size/2; i > 0; i--)
00415       siftDown(i);
00416 }//makeheap
00417 
00418 template <class key, class HeapObject>
00419 void BinaryHeap2<key, HeapObject>::decreaseKey(int index, key priority)
00420 {
00421   HeapEntry& he = m_heapArray[index];
00422 
00423   //check if error value
00424   if (he.m_priority < priority) OGDF_THROW_PARAM(AlgorithmFailureException, afcIllegalParameter);
00425 
00426   he.m_priority = priority;
00427   siftUp(index);
00428 
00429 }//decreaseKey
00430 
00431 //extract the minimum priority object and reallocate array if size < 1/3 arraysize
00432 template <class key, class HeapObject>
00433 HeapObject BinaryHeap2<key, HeapObject>::extractMin()
00434 {
00435     OGDF_ASSERT((!HeapBase<key,HeapObject>::empty()));
00436 
00437     HeapEntry tempEntry = m_heapArray[1]; //save minimum object
00438 
00439     HeapBase<key,HeapObject>::m_size--;
00440 
00441     if (HeapBase<key,HeapObject>::m_size > 0)
00442     {
00443         m_heapArray[1] = m_heapArray[HeapBase<key,HeapObject>::m_size+1]; //old last leaf
00444 
00445         //check if reallocation is possible
00446         if ((HeapBase<key,HeapObject>::m_size < (m_arraySize/3)) && (m_arraySize > 2*m_startSize-1))
00447         {
00448             HeapEntry* tempHeap = new HeapEntry[lowerArrayBound(m_arraySize)];
00449             for (int i = 1; i <= HeapBase<key,HeapObject>::m_size ; i++)
00450                 tempHeap[i] = m_heapArray[i];
00451             delete[] m_heapArray;
00452             m_heapArray = tempHeap; 
00453             m_arraySize = lowerArraySize(m_arraySize);
00454 
00455         }//if small enough
00456 
00457         //restore tree by sifting down old leaf
00458         siftDown(1);
00459     }//if not empty
00460 
00461     return tempEntry.m_object;
00462 
00463 }//extractMin
00464 
00465 
00466 //place a copy of the given input element in the queue, doubles 
00467 //array size if necessary
00468 template <class key, class HeapObject>
00469 void BinaryHeap2<key, HeapObject>::insert(HeapObject& ho, key& priority, int* keyUpdate)
00470 {
00471     OGDF_ASSERT((HeapBase<key,HeapObject>::m_size) < m_arraySize);
00472     HeapBase<key,HeapObject>::m_size++;
00473     //check if the array size has to be adjusted
00474     if (HeapBase<key,HeapObject>::m_size == m_arraySize)
00475     {
00476         HeapEntry* tempHeap = new HeapEntry[higherArrayBound(m_arraySize)];
00477         for (int i = 1; i <= m_arraySize ; i++) //last one is not occupied yet
00478             tempHeap[i] = m_heapArray[i];
00479         delete[] m_heapArray;
00480         m_heapArray = tempHeap; 
00481         m_arraySize = higherArraySize(m_arraySize);
00482     
00483     }//if array full
00484 
00485     //now insert object and reestablish heap property
00486     m_heapArray[HeapBase<key,HeapObject>::m_size] = HeapEntry(priority, ho, HeapBase<key,HeapObject>::m_size, keyUpdate);
00487 
00488     siftUp(HeapBase<key,HeapObject>::m_size);
00489 
00490 }//insert
00491 
00492 
00493 
00494 template <class key, class HeapObject>
00495 const BinaryHeap2<key, HeapObject>& BinaryHeap2<key, HeapObject>::operator=(const BinaryHeap2<key, HeapObject>& rhs)
00496 {
00497     if (this != &rhs)
00498     {
00499         if (m_heapArray && !(m_arraySize == rhs.m_arraySize))
00500         { 
00501             delete[] m_heapArray;
00502             m_heapArray = 0;
00503         }//if
00504 
00505         if (!m_heapArray)
00506             m_heapArray = new HeapEntry[arrayBound(rhs.m_arraySize)]; //start at 1
00507         
00508         OGDF_ASSERT(m_heapArray);
00509 
00510         HeapBase<key,HeapObject>::m_size = rhs.m_size;
00511 
00512         m_startSize = rhs.m_startSize;
00513 
00514         m_arraySize = rhs.m_arraySize;
00515 
00516         for (int i = 1; i <= HeapBase<key,HeapObject>::m_size ; i++)
00517                 m_heapArray[i] = rhs.m_heapArray[i];
00518 
00519     }//if not self
00520     return *this;
00521 }
00522 
00523 
00524 
00525 }//namespace oreas
00526 
00527 #endif