Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

BinaryHeap.h
Go to the documentation of this file.
1 
33 #pragma once
34 
36 
37 namespace ogdf {
38 
46 template<typename T, typename C = std::less<T>>
47 class BinaryHeap : public HeapBase<BinaryHeap<T, C>, int, T, C> {
48  using base_type = HeapBase<BinaryHeap<T, C>, int, T, C>;
49 
50 public:
57  explicit BinaryHeap(const C& comp = C(), int initialSize = 128);
58 
59  virtual ~BinaryHeap() {
60  if (m_heapArray) {
61  for (int i = 1; i <= m_size; i++) {
62  delete m_heapArray[i].handle;
63  }
64 
65  delete[] m_heapArray;
66  }
67  }
68 
74  const T& top() const override;
75 
82  int* push(const T& value) override;
83 
87  void pop() override;
88 
95  void decrease(int* handle, const T& value) override;
96 
103  const T& value(int* handle) const override;
104 
106  int capacity() const { return m_arraySize; }
107 
109  int size() const { return m_size; }
110 
112  bool empty() const { return m_size == 0; }
113 
115 
119  void clear();
120 
121 private:
123  void siftUp(int pos);
124 
126  void siftDown(int pos);
127 
129  int parentIndex(int num) {
130  OGDF_ASSERT(num > 0);
131  return num / 2;
132  }
133 
135  int leftChildIndex(int num) {
136  OGDF_ASSERT(num > 0);
137  return 2 * num;
138  }
139 
141  int rightChildIndex(int num) {
142  OGDF_ASSERT(num > 0);
143  return 2 * num + 1;
144  }
145 
147  bool hasLeft(int num) {
148  OGDF_ASSERT(num > 0);
149  return leftChildIndex(num) <= m_size;
150  }
151 
153  bool hasRight(int num) {
154  OGDF_ASSERT(num > 0);
155  return rightChildIndex(num) <= m_size;
156  }
157 
158  // helper functions for internal maintenance
159 
160  int arrayBound(int arraySize) { return arraySize + 1; }
161 
162  int higherArrayBound(int arraySize) { return 2 * arraySize + 1; }
163 
164  int higherArraySize(int arraySize) { return 2 * arraySize; }
165 
166  int lowerArrayBound(int arraySize) { return arraySize / 2 + 1; }
167 
168  int lowerArraySize(int arraySize) { return arraySize / 2; }
169 
170  void init(int initialSize);
171 
172  struct HeapEntry {
173  T value;
174  int* handle = nullptr;
175  };
176 
177  // dynamically maintained array of entries
179 
180  // number of elements stored in heap
181  int m_size;
182 
183  // current capacity of the heap
185 
186  // used to check reallocation bound
188 };
189 
190 template<typename T, typename C>
191 const T& BinaryHeap<T, C>::top() const {
192  int firstIndex = 1;
193  return value(&firstIndex);
194 }
195 
196 template<typename T, typename C>
197 int* BinaryHeap<T, C>::push(const T& value) {
198  OGDF_ASSERT((m_size) < m_arraySize);
199  m_size++;
200 
201  // does the array size have to be adjusted ?
202  if (m_size == m_arraySize) {
203  HeapEntry* tempHeap = new HeapEntry[higherArrayBound(m_arraySize)];
204 
205  // last one is not occupied yet
206  for (int i = 1; i <= m_arraySize; i++) {
207  tempHeap[i] = m_heapArray[i];
208  }
209 
210  delete[] m_heapArray;
211  m_heapArray = tempHeap;
212  m_arraySize = higherArraySize(m_arraySize);
213  }
214 
215  // actually insert object and reestablish heap property
216  HeapEntry& entry = m_heapArray[m_size];
217  entry.value = value;
218  entry.handle = new int;
219  *(entry.handle) = m_size;
220 
221  int* result = entry.handle;
222 
223  OGDF_ASSERT(*result == *(m_heapArray[*result].handle));
224 
225  siftUp(m_size);
226 
227  OGDF_ASSERT(*result == *(m_heapArray[*result].handle));
228 
229  return result;
230 }
231 
232 template<typename T, typename C>
234  OGDF_ASSERT(!empty());
235  delete m_heapArray[1].handle;
236  m_size--;
237 
238  if (m_size > 0) {
239  // former last leaf
240  m_heapArray[1] = m_heapArray[m_size + 1];
241 
242  // check if reallocation is possible
243  // TODO make reallocation threshold configurable?
244  if (m_size < m_arraySize / 3 && m_arraySize > 2 * m_initialSize - 1) {
245  HeapEntry* tempHeap = new HeapEntry[lowerArrayBound(m_arraySize)];
246 
247  for (int i = 1; i <= m_size; i++) {
248  tempHeap[i] = m_heapArray[i];
249  }
250 
251  delete[] m_heapArray;
252  m_heapArray = tempHeap;
253  m_arraySize = lowerArraySize(m_arraySize);
254  }
255 
256  siftDown(1);
257  }
258 }
259 
260 template<typename T, typename C>
261 void BinaryHeap<T, C>::decrease(int* handle, const T& value) {
262  HeapEntry& he = m_heapArray[*handle];
263  OGDF_ASSERT(this->comparator()(value, he.value));
264 
265  he.value = value;
266  siftUp(*handle);
267 }
268 
269 template<typename T, typename C>
270 const T& BinaryHeap<T, C>::value(int* handle) const {
271  OGDF_ASSERT(handle != nullptr);
272  OGDF_ASSERT(*handle > 0);
273  OGDF_ASSERT(*handle <= m_size);
274 
275  return m_heapArray[*handle].value;
276 }
277 
278 template<typename T, typename C>
279 BinaryHeap<T, C>::BinaryHeap(const C& comp, int initialSize) : base_type(comp) {
280  init(initialSize);
281 }
282 
283 template<typename T, typename C>
284 void BinaryHeap<T, C>::init(int initialSize) {
285  m_arraySize = initialSize;
286  m_initialSize = initialSize;
287  m_size = 0;
288 
289  // create an array of HeapEntry Elements
290  // start at 1
291  m_heapArray = new HeapEntry[arrayBound(m_arraySize)];
292 }
293 
294 template<typename T, typename C>
296  for (int i = 1; i <= m_size; i++) {
297  delete m_heapArray[i].handle;
298  }
299 
300  delete[] m_heapArray;
301  init(m_initialSize);
302 }
303 
304 template<typename T, typename C>
306  OGDF_ASSERT(pos > 0);
307  OGDF_ASSERT(pos <= m_size);
308 
309  if (pos == 1) {
310  *(m_heapArray[1].handle) = 1;
311  } else {
312  HeapEntry tempEntry = m_heapArray[pos];
313  int run = pos;
314 
315  while ((parentIndex(run) >= 1)
316  && this->comparator()(tempEntry.value, m_heapArray[parentIndex(run)].value)) {
317  m_heapArray[run] = m_heapArray[parentIndex(run)];
318  *(m_heapArray[run].handle) = run;
319 
320  run = parentIndex(run);
321  }
322 
323  m_heapArray[run] = tempEntry;
324  *(m_heapArray[run].handle) = run;
325  }
326 }
327 
328 template<typename T, typename C>
330  OGDF_ASSERT(pos > 0);
331  OGDF_ASSERT(pos <= m_size);
332 
333  // is leaf?
334  if (pos >= m_size / 2 + 1) {
335  *(m_heapArray[pos].handle) = pos;
336  // leafs cant move further down
337  } else {
338  T value = m_heapArray[pos].value;
339  int sIndex = pos;
340  const C& compare = this->comparator();
341 
342  // left child is smallest child?
343  if (hasLeft(pos) && compare(m_heapArray[leftChildIndex(pos)].value, value)
344  && compare(m_heapArray[leftChildIndex(pos)].value,
345  m_heapArray[rightChildIndex(pos)].value)) {
346  sIndex = leftChildIndex(pos);
347  // or is right child smaller?
348  } else if (hasRight(pos) && compare(m_heapArray[rightChildIndex(pos)].value, value)) {
349  sIndex = rightChildIndex(pos);
350  }
351 
352  // need recursive sift?
353  if (sIndex != pos) {
354  HeapEntry tempEntry = m_heapArray[pos];
355  m_heapArray[pos] = m_heapArray[sIndex];
356  m_heapArray[sIndex] = tempEntry;
357 
358  // update both index entries
359  *(m_heapArray[pos].handle) = pos;
360  *(m_heapArray[sIndex].handle) = sIndex;
361 
362  siftDown(sIndex);
363  } else {
364  *(m_heapArray[pos].handle) = pos;
365  }
366  }
367 }
368 
369 }
ogdf::BinaryHeap::leftChildIndex
int leftChildIndex(int num)
Array index of left child.
Definition: BinaryHeap.h:135
ogdf
The namespace for all OGDF objects.
Definition: AugmentationModule.h:36
ogdf::BinaryHeap::BinaryHeap
BinaryHeap(const C &comp=C(), int initialSize=128)
Initializes an empty binary heap.
Definition: BinaryHeap.h:279
ogdf::BinaryHeap::siftUp
void siftUp(int pos)
Establishes heap property by moving element up in heap if necessary.
Definition: BinaryHeap.h:305
ogdf::BinaryHeap::decrease
void decrease(int *handle, const T &value) override
Decreases a single value.
Definition: BinaryHeap.h:261
ogdf::BinaryHeap::clear
void clear()
Reinitializes the data structure.
Definition: BinaryHeap.h:295
ogdf::HeapBase
Common interface for all heap classes.
Definition: HeapBase.h:50
ogdf::BinaryHeap::hasLeft
bool hasLeft(int num)
Returns true if left child exists.
Definition: BinaryHeap.h:147
ogdf::BinaryHeap::m_heapArray
HeapEntry * m_heapArray
Definition: BinaryHeap.h:178
OGDF_ASSERT
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition: basic.h:54
ogdf::BinaryHeap::HeapEntry
Definition: BinaryHeap.h:172
ogdf::BinaryHeap::HeapEntry::handle
int * handle
Definition: BinaryHeap.h:174
ogdf::BinaryHeap::m_size
int m_size
Definition: BinaryHeap.h:181
ogdf::HeapBase::value
virtual const T & value(const Handle handle) const =0
Returns the value of that handle.
ogdf::BinaryHeap::higherArraySize
int higherArraySize(int arraySize)
Definition: BinaryHeap.h:164
ogdf::BinaryHeap::top
const T & top() const override
Returns the topmost value in the heap.
Definition: BinaryHeap.h:191
ogdf::BinaryHeap::capacity
int capacity() const
Returns the current size.
Definition: BinaryHeap.h:106
ogdf::BinaryHeap::~BinaryHeap
virtual ~BinaryHeap()
Definition: BinaryHeap.h:59
ogdf::BinaryHeap::empty
bool empty() const
Returns true iff the heap is empty.
Definition: BinaryHeap.h:112
ogdf::BinaryHeap::pop
void pop() override
Removes the topmost value from the heap.
Definition: BinaryHeap.h:233
ogdf::BinaryHeap::siftDown
void siftDown(int pos)
Establishes heap property by moving element down in heap if necessary.
Definition: BinaryHeap.h:329
ogdf::BinaryHeap::size
int size() const
Returns the number of stored elements.
Definition: BinaryHeap.h:109
ogdf::BinaryHeap::arrayBound
int arrayBound(int arraySize)
Definition: BinaryHeap.h:160
ogdf::BinaryHeap::higherArrayBound
int higherArrayBound(int arraySize)
Definition: BinaryHeap.h:162
HeapBase.h
Interface for heap implementations.
ogdf::BinaryHeap::rightChildIndex
int rightChildIndex(int num)
Array index of right child.
Definition: BinaryHeap.h:141
ogdf::BinaryHeap::lowerArraySize
int lowerArraySize(int arraySize)
Definition: BinaryHeap.h:168
ogdf::BinaryHeap::m_initialSize
int m_initialSize
Definition: BinaryHeap.h:187
ogdf::BinaryHeap::value
const T & value(int *handle) const override
Returns the value of that handle.
Definition: BinaryHeap.h:270
ogdf::BinaryHeap::lowerArrayBound
int lowerArrayBound(int arraySize)
Definition: BinaryHeap.h:166
ogdf::graphics::init
void init()
Definition: graphics.h:446
ogdf::BinaryHeap::push
int * push(const T &value) override
Inserts a value into the heap.
Definition: BinaryHeap.h:197
ogdf::BinaryHeap::hasRight
bool hasRight(int num)
Returns true if right child exists.
Definition: BinaryHeap.h:153
ogdf::BinaryHeap::parentIndex
int parentIndex(int num)
Array index of parent node.
Definition: BinaryHeap.h:129
ogdf::BinaryHeap
Heap realized by a data array.
Definition: BinaryHeap.h:47
ogdf::BinaryHeap::m_arraySize
int m_arraySize
Definition: BinaryHeap.h:184
ogdf::BinaryHeap::HeapEntry::value
T value
Definition: BinaryHeap.h:173
ogdf::BinaryHeap::init
void init(int initialSize)
Definition: BinaryHeap.h:284