Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
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
40namespace ogdf {
41
49template<typename T, typename C = std::less<T>>
50class BinaryHeap : public HeapBase<BinaryHeap<T, C>, int, T, C> {
52
53public:
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
124private:
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 {
177 int* handle = nullptr;
178 };
179
180 // dynamically maintained array of entries
182
183 // number of elements stored in heap
185
186 // current capacity of the heap
188
189 // used to check reallocation bound
191};
192
193template<typename T, typename C>
194const T& BinaryHeap<T, C>::top() const {
195 int firstIndex = 1;
196 return value(&firstIndex);
197}
198
199template<typename T, typename C>
200int* 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
235template<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
263template<typename T, typename C>
264void 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
272template<typename T, typename C>
273const 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
281template<typename T, typename C>
282BinaryHeap<T, C>::BinaryHeap(const C& comp, int initialSize) : base_type(comp) {
283 init(initialSize);
284}
285
286template<typename T, typename C>
287void 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
297template<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
307template<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
331template<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}
Interface for heap implementations.
Basic declarations, included by all source files.
Heap realized by a data array.
Definition BinaryHeap.h:50
bool hasRight(int num)
Returns true if right child exists.
Definition BinaryHeap.h:156
int size() const
Returns the number of stored elements.
Definition BinaryHeap.h:112
bool empty() const
Returns true iff the heap is empty.
Definition BinaryHeap.h:115
void clear()
Reinitializes the data structure.
Definition BinaryHeap.h:298
void siftUp(int pos)
Establishes heap property by moving element up in heap if necessary.
Definition BinaryHeap.h:308
const T & top() const override
Returns the topmost value in the heap.
Definition BinaryHeap.h:194
HeapEntry * m_heapArray
Definition BinaryHeap.h:181
int * push(const T &value) override
Inserts a value into the heap.
Definition BinaryHeap.h:200
int lowerArraySize(int arraySize)
Definition BinaryHeap.h:171
void decrease(int *handle, const T &value) override
Decreases a single value.
Definition BinaryHeap.h:264
int leftChildIndex(int num)
Array index of left child.
Definition BinaryHeap.h:138
void siftDown(int pos)
Establishes heap property by moving element down in heap if necessary.
Definition BinaryHeap.h:332
int capacity() const
Returns the current size.
Definition BinaryHeap.h:109
int higherArraySize(int arraySize)
Definition BinaryHeap.h:167
int rightChildIndex(int num)
Array index of right child.
Definition BinaryHeap.h:144
void pop() override
Removes the topmost value from the heap.
Definition BinaryHeap.h:236
int higherArrayBound(int arraySize)
Definition BinaryHeap.h:165
int parentIndex(int num)
Array index of parent node.
Definition BinaryHeap.h:132
int arrayBound(int arraySize)
Definition BinaryHeap.h:163
int lowerArrayBound(int arraySize)
Definition BinaryHeap.h:169
virtual ~BinaryHeap()
Definition BinaryHeap.h:62
bool hasLeft(int num)
Returns true if left child exists.
Definition BinaryHeap.h:150
BinaryHeap(const C &comp=C(), int initialSize=128)
Initializes an empty binary heap.
Definition BinaryHeap.h:282
const T & value(int *handle) const override
Returns the value of that handle.
Definition BinaryHeap.h:273
void init(int initialSize)
Definition BinaryHeap.h:287
Common interface for all heap classes.
Definition HeapBase.h:48
virtual const T & value(const Handle handle) const =0
Returns the value of that handle.
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition basic.h:52
The namespace for all OGDF objects.
Definition BinaryHeap.h:175
int * handle
Definition BinaryHeap.h:177
T value
Definition BinaryHeap.h:176