Skip to content

Commit 6b485a4

Browse files
committed
add iterator to paring heap
1 parent 865289b commit 6b485a4

File tree

2 files changed

+204
-9
lines changed

2 files changed

+204
-9
lines changed

libopenage/datastructure/pairing_heap.h

+193-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
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.
22

33
#pragma once
44

@@ -17,6 +17,7 @@
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>
3738
class PairingHeap;
3839

40+
template <typename T, typename compare>
41+
class PairingHeapIterator;
42+
3943

4044
template <typename T, typename compare = std::less<T>>
4145
class PairingHeapNode {
4246
public:
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 {
196361
public:
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,8 +570,15 @@ class PairingHeap final {
404570
* erase all elements on the heap.
405571
*/
406572
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+
409582
this->root_node = nullptr;
410583
this->node_count = 0;
411584
#if OPENAGE_PAIRINGHEAP_DEBUG
@@ -586,10 +759,18 @@ class PairingHeap final {
586759
* @param func Function to apply to each node.
587760
*/
588761
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 {
590763
this->walk_tree<reverse>(this->root_node, func);
591764
}
592765

766+
iterator begin() const {
767+
return iterator(this->root_node);
768+
}
769+
770+
iterator end() const {
771+
return iterator(nullptr);
772+
}
773+
593774
private:
594775
/**
595776
* Apply the given function to all nodes in the tree.
@@ -599,18 +780,21 @@ class PairingHeap final {
599780
* @param func Function to apply to each node.
600781
*/
601782
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 {
604785
if constexpr (not reverse) {
605786
func(start);
606787
}
607788

608789
if (start) {
609790
auto node = start->first_child;
610-
while (node) {
791+
while (true) {
792+
if (not node) {
793+
break;
794+
}
795+
611796
this->walk_tree<reverse>(node, func);
612-
if (node)
613-
node = node->next_sibling;
797+
node = node->next_sibling;
614798
}
615799
if constexpr (reverse) {
616800
func(start);

libopenage/datastructure/tests.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,17 @@ void pairing_heap_3() {
135135
heap.push(heap_elem{3});
136136
heap.push(heap_elem{4});
137137
heap.push(heap_elem{5});
138+
139+
140+
int i = 0;
141+
int a[6] = {0,5,4,3,2,1};
142+
for(auto elem : heap)
143+
{
144+
TESTEQUALS(elem.data, a[i]);
145+
i++;
146+
}
147+
148+
138149
heap.pop(); // trigger pairing
139150

140151
heap.clear();

0 commit comments

Comments
 (0)