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
36
37namespace ogdf {
38
46template<typename T, typename C = std::less<T>>
47class BinaryHeap : public HeapBase<BinaryHeap<T, C>, int, T, C> {
49
50public:
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
121private:
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 {
174 int* handle = nullptr;
175 };
176
177 // dynamically maintained array of entries
179
180 // number of elements stored in heap
182
183 // current capacity of the heap
185
186 // used to check reallocation bound
188};
189
190template<typename T, typename C>
191const T& BinaryHeap<T, C>::top() const {
192 int firstIndex = 1;
193 return value(&firstIndex);
194}
195
196template<typename T, typename C>
197int* 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
232template<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
260template<typename T, typename C>
261void 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
269template<typename T, typename C>
270const 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
278template<typename T, typename C>
282
283template<typename T, typename C>
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
294template<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
304template<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
328template<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}
Interface for heap implementations.
Heap realized by a data array.
Definition BinaryHeap.h:47
bool hasRight(int num)
Returns true if right child exists.
Definition BinaryHeap.h:153
int size() const
Returns the number of stored elements.
Definition BinaryHeap.h:109
bool empty() const
Returns true iff the heap is empty.
Definition BinaryHeap.h:112
void clear()
Reinitializes the data structure.
Definition BinaryHeap.h:295
void siftUp(int pos)
Establishes heap property by moving element up in heap if necessary.
Definition BinaryHeap.h:305
const T & top() const override
Returns the topmost value in the heap.
Definition BinaryHeap.h:191
HeapEntry * m_heapArray
Definition BinaryHeap.h:178
int * push(const T &value) override
Inserts a value into the heap.
Definition BinaryHeap.h:197
int lowerArraySize(int arraySize)
Definition BinaryHeap.h:168
void decrease(int *handle, const T &value) override
Decreases a single value.
Definition BinaryHeap.h:261
int leftChildIndex(int num)
Array index of left child.
Definition BinaryHeap.h:135
void siftDown(int pos)
Establishes heap property by moving element down in heap if necessary.
Definition BinaryHeap.h:329
int capacity() const
Returns the current size.
Definition BinaryHeap.h:106
int higherArraySize(int arraySize)
Definition BinaryHeap.h:164
int rightChildIndex(int num)
Array index of right child.
Definition BinaryHeap.h:141
void pop() override
Removes the topmost value from the heap.
Definition BinaryHeap.h:233
int higherArrayBound(int arraySize)
Definition BinaryHeap.h:162
int parentIndex(int num)
Array index of parent node.
Definition BinaryHeap.h:129
int arrayBound(int arraySize)
Definition BinaryHeap.h:160
int lowerArrayBound(int arraySize)
Definition BinaryHeap.h:166
virtual ~BinaryHeap()
Definition BinaryHeap.h:59
bool hasLeft(int num)
Returns true if left child exists.
Definition BinaryHeap.h:147
BinaryHeap(const C &comp=C(), int initialSize=128)
Initializes an empty binary heap.
Definition BinaryHeap.h:279
const T & value(int *handle) const override
Returns the value of that handle.
Definition BinaryHeap.h:270
void init(int initialSize)
Definition BinaryHeap.h:284
Common interface for all heap classes.
Definition HeapBase.h:50
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:41
static MultilevelBuilder * getDoubleFactoredZeroAdjustedMerger()
The namespace for all OGDF objects.
Definition BinaryHeap.h:172
int * handle
Definition BinaryHeap.h:174
T value
Definition BinaryHeap.h:173