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.
22
33#pragma once
44
1717 */
1818
1919#include < functional>
20+ #include < iterator>
2021#include < memory>
2122#include < type_traits>
2223#include < unordered_set>
@@ -36,13 +37,17 @@ template <typename T,
3637 typename heapnode_t >
3738class PairingHeap ;
3839
40+ template <typename T, typename compare>
41+ class PairingHeapIterator ;
42+
3943
4044template <typename T, typename compare = std::less<T>>
4145class PairingHeapNode {
4246public:
4347 using this_type = PairingHeapNode<T, compare>;
4448
4549 friend PairingHeap<T, compare, this_type>;
50+ friend PairingHeapIterator<T, compare>;
4651
4752 T data;
4853 compare cmp;
@@ -186,6 +191,166 @@ class PairingHeapNode {
186191};
187192
188193
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+
189354/* *
190355 * (Quite) efficient heap implementation.
191356 */
@@ -196,6 +361,7 @@ class PairingHeap final {
196361public:
197362 using element_t = heapnode_t *;
198363 using this_type = PairingHeap<T, compare, heapnode_t >;
364+ using iterator = PairingHeapIterator<T, compare>;
199365
200366 /* *
201367 * create a empty heap.
@@ -404,11 +570,24 @@ class PairingHeap final {
404570 * erase all elements on the heap.
405571 */
406572 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
409587 this ->root_node = nullptr ;
410588 this ->node_count = 0 ;
411589#if OPENAGE_PAIRINGHEAP_DEBUG
590+ // clear the node set for debugging
412591 this ->nodes .clear ();
413592#endif
414593 }
@@ -590,6 +769,14 @@ class PairingHeap final {
590769 this ->walk_tree <reverse>(this ->root_node , func);
591770 }
592771
772+ iterator begin () const {
773+ return iterator (this ->root_node );
774+ }
775+
776+ iterator end () const {
777+ return iterator (nullptr );
778+ }
779+
593780private:
594781 /* *
595782 * Apply the given function to all nodes in the tree.
0 commit comments