Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

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