Open
Graph Drawing
Framework

 v.2007.11
 

BinaryHeap.h

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


© 1999-2007 by oreas GmbH, © 2005-2007 by University Dortmund and University Cologne.

Generated on Thu Nov 22 19:40:00 2007 by doxygen 1.5.4.