Loading [MathJax]/extensions/tex2jax.js

Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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