1
- // Copyright 2014-2024 the openage authors. See copying.md for legal info.
1
+ // Copyright 2014-2025 the openage authors. See copying.md for legal info.
2
2
3
3
#pragma once
4
4
17
17
*/
18
18
19
19
#include < functional>
20
+ #include < iterator>
20
21
#include < memory>
21
22
#include < type_traits>
22
23
#include < unordered_set>
@@ -36,13 +37,17 @@ template <typename T,
36
37
typename heapnode_t >
37
38
class PairingHeap ;
38
39
40
+ template <typename T, typename compare>
41
+ class PairingHeapIterator ;
42
+
39
43
40
44
template <typename T, typename compare = std::less<T>>
41
45
class PairingHeapNode {
42
46
public:
43
47
using this_type = PairingHeapNode<T, compare>;
44
48
45
49
friend PairingHeap<T, compare, this_type>;
50
+ friend PairingHeapIterator<T, compare>;
46
51
47
52
T data;
48
53
compare cmp;
@@ -186,6 +191,166 @@ class PairingHeapNode {
186
191
};
187
192
188
193
194
+ /* *
195
+ * @brief Iterator class for PairingHeap.
196
+ *
197
+ * This class provides a bidirectional iterator for the PairingHeap data structure.
198
+ * It allows traversal of the heap in both forward and backward directions.
199
+ * It is depth-first traversal.
200
+ *
201
+ * @tparam T The type of elements stored in the heap.
202
+ * @tparam compare The comparison functor used to order the elements.
203
+ */
204
+ template <typename T, typename compare = std::less<T>>
205
+ class PairingHeapIterator {
206
+ public:
207
+ using iterator_category = std::bidirectional_iterator_tag;
208
+ using value_type = T;
209
+ using difference_type = std::ptrdiff_t ;
210
+ using pointer = T *;
211
+ using reference = T &;
212
+
213
+ /* *
214
+ * @brief Constructs an iterator starting at the given node.
215
+ *
216
+ * @param node The starting node for the iterator.
217
+ */
218
+ PairingHeapIterator (PairingHeapNode<T, compare> *node) :
219
+ current (node) {}
220
+
221
+ /* *
222
+ * @brief Dereference operator.
223
+ *
224
+ * @return A reference to the data stored in the current node.
225
+ */
226
+ reference operator *() const {
227
+ return current->data ;
228
+ }
229
+
230
+ /* *
231
+ * @brief Member access operator.
232
+ *
233
+ * @return A pointer to the data stored in the current node.
234
+ */
235
+ pointer operator ->() const {
236
+ return &(current->data );
237
+ }
238
+
239
+
240
+ /* *
241
+ * @brief Get current node.
242
+ *
243
+ * @return The current node.
244
+ */
245
+ PairingHeapNode<T, compare> *node () {
246
+ return current;
247
+ }
248
+
249
+
250
+ /* *
251
+ * @brief Pre-increment operator.
252
+ *
253
+ * Moves the iterator to the next node in the heap.
254
+ *
255
+ * @return A reference to the incremented iterator.
256
+ */
257
+ PairingHeapIterator &operator ++() {
258
+ if (current->first_child ) {
259
+ current = current->first_child ;
260
+ }
261
+ else if (current->next_sibling ) {
262
+ current = current->next_sibling ;
263
+ }
264
+ else {
265
+ while (current->parent && !current->parent ->next_sibling ) {
266
+ current = current->parent ;
267
+ }
268
+ if (current->parent ) {
269
+ current = current->parent ->next_sibling ;
270
+ }
271
+ else {
272
+ current = nullptr ;
273
+ }
274
+ }
275
+ return *this ;
276
+ }
277
+
278
+ /* *
279
+ * @brief Post-increment operator.
280
+ *
281
+ * Moves the iterator to the next node in the heap.
282
+ *
283
+ * @return A copy of the iterator before incrementing.
284
+ */
285
+ PairingHeapIterator operator ++(int ) {
286
+ PairingHeapIterator tmp = *this ;
287
+ ++(*this );
288
+ return tmp;
289
+ }
290
+
291
+ /* *
292
+ * @brief Pre-decrement operator.
293
+ *
294
+ * Moves the iterator to the previous node in the heap.
295
+ *
296
+ * @return A reference to the decremented iterator.
297
+ */
298
+ PairingHeapIterator &operator --() {
299
+ if (current->prev_sibling ) {
300
+ current = current->prev_sibling ;
301
+ while (current->first_child ) {
302
+ current = current->first_child ;
303
+ while (current->next_sibling ) {
304
+ current = current->next_sibling ;
305
+ }
306
+ }
307
+ }
308
+ else if (current->parent ) {
309
+ current = current->parent ;
310
+ }
311
+ return *this ;
312
+ }
313
+
314
+ /* *
315
+ * @brief Post-decrement operator.
316
+ *
317
+ * Moves the iterator to the previous node in the heap.
318
+ *
319
+ * @return A copy of the iterator before decrementing.
320
+ */
321
+ PairingHeapIterator operator --(int ) {
322
+ PairingHeapIterator tmp = *this ;
323
+ --(*this );
324
+ return tmp;
325
+ }
326
+
327
+ /* *
328
+ * @brief Equality comparison operator.
329
+ *
330
+ * @param a The first iterator to compare.
331
+ * @param b The second iterator to compare.
332
+ * @return True if both iterators point to the same node, false otherwise.
333
+ */
334
+ friend bool operator ==(const PairingHeapIterator &a, const PairingHeapIterator &b) {
335
+ return a.current == b.current ;
336
+ }
337
+
338
+ /* *
339
+ * @brief Inequality comparison operator.
340
+ *
341
+ * @param a The first iterator to compare.
342
+ * @param b The second iterator to compare.
343
+ * @return True if the iterators point to different nodes, false otherwise.
344
+ */
345
+ friend bool operator !=(const PairingHeapIterator &a, const PairingHeapIterator &b) {
346
+ return a.current != b.current ;
347
+ }
348
+
349
+ private:
350
+ PairingHeapNode<T, compare> *current; // /< Pointer to the current node in the heap.
351
+ };
352
+
353
+
189
354
/* *
190
355
* (Quite) efficient heap implementation.
191
356
*/
@@ -196,6 +361,7 @@ class PairingHeap final {
196
361
public:
197
362
using element_t = heapnode_t *;
198
363
using this_type = PairingHeap<T, compare, heapnode_t >;
364
+ using iterator = PairingHeapIterator<T, compare>;
199
365
200
366
/* *
201
367
* create a empty heap.
@@ -404,11 +570,24 @@ class PairingHeap final {
404
570
* erase all elements on the heap.
405
571
*/
406
572
void clear () {
407
- auto delete_node = [](element_t node) { delete node; };
408
- this ->iter_all <true >(delete_node);
573
+ std::vector<element_t > to_delete;
574
+ to_delete.reserve (this ->size ());
575
+
576
+ // collect all node pointers to delete
577
+ for (iterator it = this ->begin (); it != this ->end (); it++) {
578
+ to_delete.push_back (it.node ());
579
+ }
580
+
581
+ // delete all nodes
582
+ for (element_t node : to_delete) {
583
+ delete node;
584
+ }
585
+
586
+ // reset heap state to empty
409
587
this ->root_node = nullptr ;
410
588
this ->node_count = 0 ;
411
589
#if OPENAGE_PAIRINGHEAP_DEBUG
590
+ // clear the node set for debugging
412
591
this ->nodes .clear ();
413
592
#endif
414
593
}
@@ -590,6 +769,14 @@ class PairingHeap final {
590
769
this ->walk_tree <reverse>(this ->root_node , func);
591
770
}
592
771
772
+ iterator begin () const {
773
+ return iterator (this ->root_node );
774
+ }
775
+
776
+ iterator end () const {
777
+ return iterator (nullptr );
778
+ }
779
+
593
780
private:
594
781
/* *
595
782
* Apply the given function to all nodes in the tree.
0 commit comments