Open
Graph Drawing
Framework

 v.2012.07
 

BinaryHeap2.h
Go to the documentation of this file.
1 /*
2  * $Revision: 2564 $
3  *
4  * last checkin:
5  * $Author: gutwenger $
6  * $Date: 2012-07-07 00:03:48 +0200 (Sa, 07. Jul 2012) $
7  ***************************************************************/
8 
44 #ifdef _MSC_VER
45 #pragma once
46 #endif
47 
48 #ifndef OGDF_BINARY_HEAP2_H
49 #define OGDF_BINARY_HEAP2_H
50 
51 #include <ogdf/basic/HeapBase.h>
52 
53 namespace ogdf {
54 
99 //to allow directobject adress, a pointer to an integer storage
100 //can be provided, where the array index is updated by the
101 //heap class
102 
103 
104 template <class key, class HeapObject>
105 class BinaryHeap2 : public HeapBase<key, HeapObject>
106 {
107 public:
109  BinaryHeap2(int startSize = 128);
110 
111  //copy Constructor, todo
112  //BinaryHeap2(const BinaryHeap2& source);
113 
114  // Destructor, deletes the heap array.
115  virtual ~BinaryHeap2() {
116  if (m_heapArray) delete[] m_heapArray;
117  }//destructor
118 
119 
122 
123  //------------------------------------------------------------
124  //modification:
125 
127  void insert(HeapObject& obj, key& p, int* keyUpdate = 0);
128 
130  virtual void makeHeap();
131  //delete
132  //it is not clear how a delete without explicit
133  //given heapentry pointer should behave, e.g. if equal values
134  //for objects are allowed
135 
137  // arraySize is decreased if size < 1/3arraySize (amortized runtime O(1))
138  HeapObject extractMin();
139 
141  // use updated m_foreign position index to address entry for decreasekey
142  virtual void decreaseKey(int index, key priority);
143  //TODO: version mit Aenderungswert statt absolutem Wert
144 
145  //--------------------------------------------------------------
146  //const access functions
147 
149  HeapObject minRet() const {return m_heapArray[1].m_object;}
150 
151  key getPriority(int index) const
152  {
153  OGDF_ASSERT( (index > 0) && (index <= HeapBase<key,HeapObject>::m_size) );
154  return m_heapArray[index].m_priority;
155  }//getPriority
156 
158  int capacity() const { return m_arraySize; }
159 
161  int size() const { return HeapBase<key,HeapObject>::m_size; }
162 
164  int empty() const { return HeapBase<key,HeapObject>::empty(); }
165 
167 
171  void clear();
172 
173 protected:
175  void siftUp(int pos);
176 
178  void siftDown(int pos);
179 
180  //----------------------------------------------------------
181  //modelling the binary tree structure on the data array
182  //array position 0 is left empty, positions are from 1..m_size
184  int parentIndex(int num)
185  {
186  OGDF_ASSERT(num>0);
187  return num/2;
188  }//parent
189 
191  int leftChildIndex(int num)
192  {
193  OGDF_ASSERT(num>0);
194  return 2*num;
195  }//leftChild
196 
198  int rightChildIndex(int num)
199  {
200  OGDF_ASSERT(num>0);
201  return 2*num+1;
202  }//rightChild
203 
205  bool hasLeft(int num)
206  {
207  OGDF_ASSERT(num>0);
209  }
210 
212  bool hasRight(int num)
213  {
214  OGDF_ASSERT(num>0);
216  }
217 
218  //----------------------------------------------------------
219  //helper functions for internal maintainance
220  int arrayBound(int arraySize) {return arraySize+1;}
221  int higherArrayBound(int arraySize) {return 2*arraySize+1;}
222  int higherArraySize(int arraySize) {return 2*arraySize;}
223  int lowerArrayBound(int arraySize) {return arraySize/2+1;}
224  int lowerArraySize(int arraySize) {return arraySize/2;}
225 
226  void init(int initSize);
227 
228 private:
229  //holding object and priority key
230  struct HeapEntry
231  {
233  HeapObject m_object;
234 
235  //we maintain positions during operations
236  int m_pos;
237  int* m_foreignPos; //storage structure given by user
238 
241  m_pos = 0;
242  m_foreignPos = 0;
243  }
244 
246 
250  HeapEntry(key k, const HeapObject& ob) {m_priority = k; m_object = ob;
251  m_foreignPos = 0;
252  //m_pos = ob.m_pos;
253  }
254 
256 
262  HeapEntry(key k, const HeapObject& ob, int pos, int* fp)
263  {
264  m_priority = k;
265  m_object = ob;
266  if (fp == 0) m_foreignPos = 0;
267  else m_foreignPos = fp;
268  m_pos = pos;
269  }
270  };
271 
272  HeapEntry* m_heapArray; //dynamically maintained array of heapentries
273 
274  //in addition to m_size, the inherited number of objects from class HeapBase,
275  //we store the actual size of the array, valid array object positions
276  //are from 1 to m_size
277  int m_arraySize; //current size of the heap
278 
279  int m_startSize; //(decide: optionally??) used to check reallocation bound
280 
281 };//BinaryHeap2
282 
283 
284 
285 //**************************************************************
286 //implementation
287 //**************************************************************
288 
289 
290 //**************************************************************
291 //constructor and initialization
292 template <class key, class HeapObject>
294 : HeapBase<key, HeapObject>()
295 {
296  init(startSize);
297 }//constructor
298 
299 
300 template <class key, class HeapObject>
302 {
303  //create an array of HeapEntry Elements
304  m_arraySize = initSize;
305  m_heapArray = new HeapEntry[arrayBound(m_arraySize)]; //start at 1
306 
307  m_startSize = initSize;
308 
310 }
311 
312 
313 template <class key, class HeapObject>
315 {
316  if (m_heapArray) delete[] m_heapArray;
317  init(m_startSize);
318 }
319 
320 
321 //**************************************************************
322 //element shifting operations
323 //restore heap property by finding correct position for object
324 //at position pos on higher levels, pos is given as array index (1..m_size)
325 //updates array index values
326 template <class key, class HeapObject>
328 {
329  OGDF_ASSERT( (pos > 0) && (pos <= HeapBase<key,HeapObject>::m_size) )
330 
331  if (pos == 1)
332  {
333  m_heapArray[1].m_pos = 1;
334  if (m_heapArray[1].m_foreignPos != 0) //address is defined
335  *(m_heapArray[1].m_foreignPos) = 1;
336  return;//nothing to do
337  }
338 
339  HeapEntry tempEntry = m_heapArray[pos];
340  int run = pos;
341  while ( (parentIndex(run) >= 1) &&
342  (m_heapArray[parentIndex(run)].m_priority > tempEntry.m_priority) )
343  {
344  m_heapArray[run] = m_heapArray[parentIndex(run)];
345  if (m_heapArray[run].m_foreignPos != 0) *(m_heapArray[run].m_foreignPos) = run;
346  run = parentIndex(run);
347  }//while
348 
349  m_heapArray[run] = tempEntry;
350  m_heapArray[run].m_pos = run;
351  if (m_heapArray[run].m_foreignPos != 0) *(m_heapArray[run].m_foreignPos) = run;
352 
353 
354 }//siftup
355 
356 
357 //restore heap property by finding correct position for object
358 //at position pos on lower levels, updates array index values
359 template <class key, class HeapObject>
361 {
362  OGDF_ASSERT( (pos > 0) && (pos <= HeapBase<key,HeapObject>::m_size) );
363 
364  if (pos >= int(HeapBase<key,HeapObject>::m_size/2)+1)
365  {
366  m_heapArray[pos].m_pos = pos;
367  if (m_heapArray[pos].m_foreignPos != 0) *(m_heapArray[pos].m_foreignPos) = pos;
368  return; //leafs cant move down
369  }//if leaf
370 
371  key sPrio = getPriority(pos);
372  int sIndex = pos;
373 
374  if (hasLeft(pos) && (getPriority(leftChildIndex(pos)) < sPrio) )
375  {
376  sIndex = leftChildIndex(pos);
377  sPrio = getPriority(leftChildIndex(pos));
378  }//if left child smaller
379  if (hasRight(pos) && (getPriority(rightChildIndex(pos)) < sPrio) )
380  {
381  sIndex = rightChildIndex(pos);
382  sPrio = getPriority(rightChildIndex(pos));
383  }//if right child smaller
384 
385  if (sIndex != pos)
386  {
387  HeapEntry tempEntry = m_heapArray[pos];
388  m_heapArray[pos] = m_heapArray[sIndex];
389  m_heapArray[sIndex] = tempEntry;
390 
391  //update both index entries
392  m_heapArray[pos].m_pos = pos;
393  if (m_heapArray[pos].m_foreignPos != 0) *(m_heapArray[pos].m_foreignPos) = pos;
394  m_heapArray[sIndex].m_pos = sIndex;
395  if (m_heapArray[sIndex].m_foreignPos != 0) *(m_heapArray[sIndex].m_foreignPos) = sIndex;
396 
397  siftDown(sIndex); //TODO: dont use recursion
398  }//if sift necessary
399  else //update in case of new elements (non-insert)
400  {
401  m_heapArray[pos].m_pos = pos;
402  if (m_heapArray[pos].m_foreignPos != 0) *(m_heapArray[pos].m_foreignPos) = pos;
403  }//else
404 }//siftdown
405 
406 
407 template <class key, class HeapObject>
409 {
410  //only needed if insertion is not done over insert
411  //(if we allow array parameter in constructor)
412  for (int i=HeapBase<key,HeapObject>::m_size/2; i > 0; i--)
413  siftDown(i);
414 }//makeheap
415 
416 
417 template <class key, class HeapObject>
418 void BinaryHeap2<key, HeapObject>::decreaseKey(int index, key priority)
419 {
420  HeapEntry& he = m_heapArray[index];
421 
422  //check if error value
424 
425  he.m_priority = priority;
426  siftUp(index);
427 
428 }//decreaseKey
429 
430 
431 //extract the minimum priority object and reallocate array if size < 1/3 arraysize
432 template <class key, class HeapObject>
434 {
436 
437  HeapEntry tempEntry = m_heapArray[1]; //save minimum object
438 
440 
442  {
443  m_heapArray[1] = m_heapArray[HeapBase<key,HeapObject>::m_size+1]; //old last leaf
444 
445  //check if reallocation is possible
446  if ((HeapBase<key,HeapObject>::m_size < (m_arraySize/3)) && (m_arraySize > 2*m_startSize-1))
447  {
448  HeapEntry* tempHeap = new HeapEntry[lowerArrayBound(m_arraySize)];
449  for (int i = 1; i <= HeapBase<key,HeapObject>::m_size ; i++)
450  tempHeap[i] = m_heapArray[i];
451  delete[] m_heapArray;
452  m_heapArray = tempHeap;
453  m_arraySize = lowerArraySize(m_arraySize);
454 
455  }//if small enough
456 
457  //restore tree by sifting down old leaf
458  siftDown(1);
459  }//if not empty
460 
461  return tempEntry.m_object;
462 
463 }//extractMin
464 
465 
466 //place a copy of the given input element in the queue, doubles
467 //array size if necessary
468 template <class key, class HeapObject>
469 void BinaryHeap2<key, HeapObject>::insert(HeapObject& ho, key& priority, int* keyUpdate)
470 {
473  //check if the array size has to be adjusted
474  if (HeapBase<key,HeapObject>::m_size == m_arraySize)
475  {
476  HeapEntry* tempHeap = new HeapEntry[higherArrayBound(m_arraySize)];
477  for (int i = 1; i <= m_arraySize ; i++) //last one is not occupied yet
478  tempHeap[i] = m_heapArray[i];
479  delete[] m_heapArray;
480  m_heapArray = tempHeap;
481  m_arraySize = higherArraySize(m_arraySize);
482 
483  }//if array full
484 
485  //now insert object and reestablish heap property
486  m_heapArray[HeapBase<key,HeapObject>::m_size] = HeapEntry(priority, ho, HeapBase<key,HeapObject>::m_size, keyUpdate);
487 
489 
490 }//insert
491 
492 
493 
494 template <class key, class HeapObject>
496 {
497  if (this != &rhs)
498  {
499  if (m_heapArray && !(m_arraySize == rhs.m_arraySize))
500  {
501  delete[] m_heapArray;
502  m_heapArray = 0;
503  }//if
504 
505  if (!m_heapArray)
506  m_heapArray = new HeapEntry[arrayBound(rhs.m_arraySize)]; //start at 1
507 
508  OGDF_ASSERT(m_heapArray);
509 
511 
512  m_startSize = rhs.m_startSize;
513  m_arraySize = rhs.m_arraySize;
514 
515  for (int i = 1; i <= HeapBase<key,HeapObject>::m_size ; i++)
516  m_heapArray[i] = rhs.m_heapArray[i];
517 
518  }//if not self
519  return *this;
520 }
521 
522 
523 
524 }//namespace ogdf
525 
526 #endif