1
- // Copyright 2014-2025 the openage authors. See copying.md for legal info.
1
+ // Copyright 2014-2024 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,8 +570,15 @@ 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; node = nullptr ; };
408
- this ->iter_all <true >(delete_node);
573
+ std::vector<element_t > nodes_vec;
574
+ nodes_vec.reserve (this ->size ());
575
+ for (iterator it = this ->begin (); it != this ->end (); it++) {
576
+ nodes_vec.push_back (it.node ());
577
+ }
578
+ for (element_t node : nodes_vec) {
579
+ delete node;
580
+ }
581
+
409
582
this ->root_node = nullptr ;
410
583
this ->node_count = 0 ;
411
584
#if OPENAGE_PAIRINGHEAP_DEBUG
@@ -586,10 +759,18 @@ class PairingHeap final {
586
759
* @param func Function to apply to each node.
587
760
*/
588
761
template <bool reverse = false >
589
- void iter_all (const std::function<void (element_t &)> &func) {
762
+ void iter_all (const std::function<void (const element_t &)> &func) const {
590
763
this ->walk_tree <reverse>(this ->root_node , func);
591
764
}
592
765
766
+ iterator begin () const {
767
+ return iterator (this ->root_node );
768
+ }
769
+
770
+ iterator end () const {
771
+ return iterator (nullptr );
772
+ }
773
+
593
774
private:
594
775
/* *
595
776
* Apply the given function to all nodes in the tree.
@@ -599,18 +780,21 @@ class PairingHeap final {
599
780
* @param func Function to apply to each node.
600
781
*/
601
782
template <bool reverse = false >
602
- void walk_tree (element_t &start,
603
- const std::function<void (element_t &)> &func) {
783
+ void walk_tree (const element_t &start,
784
+ const std::function<void (const element_t &)> &func) const {
604
785
if constexpr (not reverse) {
605
786
func (start);
606
787
}
607
788
608
789
if (start) {
609
790
auto node = start->first_child ;
610
- while (node) {
791
+ while (true ) {
792
+ if (not node) {
793
+ break ;
794
+ }
795
+
611
796
this ->walk_tree <reverse>(node, func);
612
- if (node)
613
- node = node->next_sibling ;
797
+ node = node->next_sibling ;
614
798
}
615
799
if constexpr (reverse) {
616
800
func (start);
0 commit comments