Skip to content

Commit d24c165

Browse files
feat(graph): expand disjoint set iterators (#128)
1 parent e71f092 commit d24c165

File tree

3 files changed

+160
-39
lines changed

3 files changed

+160
-39
lines changed

cpl/inc/tree.h

Lines changed: 146 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,116 +9,226 @@
99

1010
#include "xcore.h"
1111

12+
#include <iterator>
1213
#include <numeric>
1314
#include <vector>
1415

1516
CPL_BEGIN
16-
#ifdef USE_DISJOINT_SET_ITERATORS
1717
template <class MyDisj>
18-
class _Disjoint_set_const_iterator {
18+
class disjoint_set_const_iterator {
1919
public:
2020
using iterator_category = std::random_access_iterator_tag;
21+
using iterator_concept = std::random_access_iterator_tag;
22+
using difference_type = std::ptrdiff_t;
23+
24+
private:
25+
using parent_value_type = typename MyDisj::value_type;
26+
using parent_rank_type = typename MyDisj::rank_type;
27+
28+
using parent_iterator = typename std::vector<parent_value_type>::const_iterator;
29+
using rank_iterator = typename std::vector<parent_rank_type>::const_iterator;
2130

2231
protected:
23-
using parent_iterator = typename std::vector<typename MyDisj::value_type>::iterator;
24-
using rank_iterator = typename std::vector<typename MyDisj::rank_type>::iterator;
32+
using pair_cref = std::pair<const parent_value_type&, const parent_rank_type&>;
33+
34+
struct arrow_proxy {
35+
pair_cref ref;
36+
37+
const pair_cref* operator->() const noexcept {
38+
return &ref;
39+
}
40+
};
2541

2642
public:
27-
using value_type = std::pair<typename MyDisj::value_type, typename MyDisj::rank_type>;
28-
using difference_type = std::ptrdiff_t;
29-
using pointer = value_type*;
30-
using const_pointer = value_type*;
31-
using reference = value_type&;
32-
using const_reference = const value_type&;
43+
using value_type = std::pair<parent_value_type, parent_rank_type>;
44+
using reference = value_type;
45+
using const_reference = value_type;
46+
using pointer = const value_type*;
47+
using const_pointer = const value_type*;
3348

34-
_Disjoint_set_const_iterator(parent_iterator parent, rank_iterator rank) noexcept : parent(parent), rank(rank) {}
49+
disjoint_set_const_iterator() = default;
3550

36-
[[nodiscard]] value_type operator*() const noexcept {
37-
return {(*parent), (*rank)};
51+
disjoint_set_const_iterator(parent_iterator parent, rank_iterator rank) noexcept : parent(parent), rank(rank) {}
52+
53+
[[nodiscard]] reference operator*() const noexcept {
54+
return reference{*parent, *rank};
3855
}
3956

40-
[[nodiscard]] pointer operator->() const noexcept {
41-
return &operator*();
57+
[[nodiscard]] arrow_proxy operator->() const noexcept {
58+
return arrow_proxy{reference{*parent, *rank}};
4259
}
4360

44-
_Disjoint_set_const_iterator& operator++() noexcept {
61+
disjoint_set_const_iterator& operator++() noexcept {
4562
++parent;
4663
++rank;
4764
return *this;
4865
}
4966

50-
_Disjoint_set_const_iterator& operator++(int) noexcept {
67+
disjoint_set_const_iterator operator++(int) noexcept {
5168
auto tmp = *this;
5269
++(*this);
5370
return tmp;
5471
}
5572

56-
_Disjoint_set_const_iterator& operator--() noexcept {
73+
disjoint_set_const_iterator& operator--() noexcept {
5774
--parent;
5875
--rank;
5976
return *this;
6077
}
6178

62-
_Disjoint_set_const_iterator& operator--(int) noexcept {
79+
disjoint_set_const_iterator operator--(int) noexcept {
6380
auto tmp = *this;
6481
--(*this);
6582
return tmp;
6683
}
6784

68-
[[nodiscard]] _Disjoint_set_const_iterator& operator+=(const difference_type off) noexcept {
85+
[[nodiscard]] disjoint_set_const_iterator& operator+=(const difference_type off) noexcept {
6986
parent += off;
7087
rank += off;
7188
return *this;
7289
}
7390

74-
[[nodiscard]] _Disjoint_set_const_iterator operator+(const difference_type off) const noexcept {
91+
[[nodiscard]] disjoint_set_const_iterator operator+(const difference_type off) const noexcept {
7592
auto tmp = *this;
7693
tmp += off;
7794
return tmp;
7895
}
7996

80-
[[nodiscard]] friend _Disjoint_set_const_iterator operator+(
81-
const difference_type off, _Disjoint_set_const_iterator next) noexcept {
97+
[[nodiscard]] friend disjoint_set_const_iterator operator+(
98+
const difference_type off, disjoint_set_const_iterator next) noexcept {
8299
next += off;
83100
return next;
84101
}
85102

86-
[[nodiscard]] _Disjoint_set_const_iterator& operator-=(const difference_type off) noexcept {
103+
[[nodiscard]] disjoint_set_const_iterator& operator-=(const difference_type off) noexcept {
87104
return *this += -off;
88105
}
89106

90-
[[nodiscard]] _Disjoint_set_const_iterator operator-(const difference_type off) const noexcept {
107+
[[nodiscard]] disjoint_set_const_iterator operator-(const difference_type off) const noexcept {
91108
auto tmp = *this;
92109
tmp -= off;
93110
return tmp;
94111
}
95112

96-
[[nodiscard]] difference_type operator-(const _Disjoint_set_const_iterator& right) const noexcept {
113+
[[nodiscard]] difference_type operator-(const disjoint_set_const_iterator& right) const noexcept {
97114
return static_cast<difference_type>(parent - right.parent);
98115
}
99116

100-
[[nodiscard]] bool operator==(const _Disjoint_set_const_iterator& right) const noexcept {
117+
[[nodiscard]] reference operator[](const difference_type off) const noexcept {
118+
return *(*this + off);
119+
}
120+
121+
[[nodiscard]] bool operator==(const disjoint_set_const_iterator& right) const noexcept {
101122
return parent == right.parent;
102123
}
103124

104-
[[nodiscard]] bool operator!=(const _Disjoint_set_const_iterator& right) const noexcept {
125+
[[nodiscard]] bool operator!=(const disjoint_set_const_iterator& right) const noexcept {
105126
return !(*this == right);
106127
}
107128

129+
[[nodiscard]] bool operator<(const disjoint_set_const_iterator& right) const noexcept {
130+
return parent < right.parent;
131+
}
132+
133+
[[nodiscard]] bool operator>(const disjoint_set_const_iterator& right) const noexcept {
134+
return right < *this;
135+
}
136+
137+
[[nodiscard]] bool operator<=(const disjoint_set_const_iterator& right) const noexcept {
138+
return !(right < *this);
139+
}
140+
141+
[[nodiscard]] bool operator>=(const disjoint_set_const_iterator& right) const noexcept {
142+
return !(*this < right);
143+
}
144+
108145
protected:
109146
parent_iterator parent;
110147
rank_iterator rank;
111148
};
112149

113150
template <class Mydisj>
114-
class _Disjoint_set_iterator : public _Disjoint_set_const_iterator<Mydisj> {
151+
class disjoint_set_iterator : public disjoint_set_const_iterator<Mydisj> {
115152
protected:
116-
using _Mybase = _Disjoint_set_const_iterator<Mydisj>;
153+
using Mybase = disjoint_set_const_iterator<Mydisj>;
117154

118155
public:
119-
using _Mybase::_Mybase;
156+
using iterator_category = std::random_access_iterator_tag;
157+
using iterator_concept = std::random_access_iterator_tag;
158+
using difference_type = typename Mybase::difference_type;
159+
160+
using value_type = typename Mybase::value_type;
161+
using reference = typename Mybase::reference;
162+
using pointer = typename Mybase::pointer;
163+
164+
using Mybase::Mybase;
165+
166+
[[nodiscard]] reference operator*() const noexcept {
167+
return Mybase::operator*();
168+
}
169+
170+
[[nodiscard]] Mybase::arrow_proxy operator->() const noexcept {
171+
return Mybase::operator->();
172+
}
173+
174+
disjoint_set_iterator& operator++() noexcept {
175+
Mybase::operator++();
176+
return *this;
177+
}
178+
179+
disjoint_set_iterator operator++(int) noexcept {
180+
auto tmp = *this;
181+
Mybase::operator++();
182+
return tmp;
183+
}
184+
185+
disjoint_set_iterator& operator--() noexcept {
186+
Mybase::operator--();
187+
return *this;
188+
}
189+
190+
disjoint_set_iterator operator--(int) noexcept {
191+
auto tmp = *this;
192+
Mybase::operator--();
193+
return tmp;
194+
}
195+
196+
[[nodiscard]] disjoint_set_iterator& operator+=(const difference_type off) noexcept {
197+
Mybase::operator+=(off);
198+
return *this;
199+
}
200+
201+
[[nodiscard]] disjoint_set_iterator operator+(const difference_type off) const noexcept {
202+
auto tmp = *this;
203+
tmp += off;
204+
return tmp;
205+
}
206+
207+
[[nodiscard]] friend disjoint_set_iterator operator+(
208+
const difference_type off, disjoint_set_iterator next) noexcept {
209+
next += off;
210+
return next;
211+
}
212+
213+
[[nodiscard]] disjoint_set_iterator& operator-=(const difference_type off) noexcept {
214+
Mybase::operator-=(off);
215+
return *this;
216+
}
217+
218+
[[nodiscard]] disjoint_set_iterator operator-(const difference_type off) const noexcept {
219+
auto tmp = *this;
220+
tmp -= off;
221+
return tmp;
222+
}
223+
224+
[[nodiscard]] difference_type operator-(const disjoint_set_iterator& right) const noexcept {
225+
return static_cast<difference_type>(this->parent - right.parent);
226+
}
227+
228+
[[nodiscard]] reference operator[](const difference_type off) const noexcept {
229+
return const_cast<reference>(Mybase::operator[](off));
230+
}
120231
};
121-
#endif // USE_DISJOINT_SET_ITERATORS
122232

123233
template <class Ty, class Ranty = std::size_t>
124234
class DisjointSet { // fixed size union find structure
@@ -180,9 +290,9 @@ class DisjointSet { // fixed size union find structure
180290
rank.resize(size, 0);
181291
}
182292

183-
#ifdef USE_DISJOINT_SET_ITERATORS
184-
using iterator = _Disjoint_set_iterator<DisjointSet<value_type>>;
185-
using const_iterator = _Disjoint_set_const_iterator<DisjointSet<value_type>>;
293+
#ifdef CPL
294+
using iterator = disjoint_set_iterator<DisjointSet<value_type>>;
295+
using const_iterator = disjoint_set_const_iterator<DisjointSet<value_type>>;
186296

187297
[[nodiscard]] iterator begin() noexcept {
188298
return iterator(parent.begin(), rank.begin());
@@ -199,7 +309,7 @@ class DisjointSet { // fixed size union find structure
199309
[[nodiscard]] const_iterator end() const noexcept {
200310
return const_iterator(parent.end(), rank.end());
201311
}
202-
#endif // USE_DISJOINT_SET_ITERATORS
312+
#endif // CPL
203313

204314
private:
205315
std::vector<value_type> parent;

cpl/inc/xcore.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@
2323
// All macro library checks must first satisfy the `CPL` check.
2424
#define CPL 1
2525

26-
#define USE_DISJOINT_SET_ITERATORS 1
27-
2826
#undef CPL_STRINGIZE_
2927
#undef CPL_STRINGIZE
3028

tests/cpl/disjoint_set/test.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// SPDX-License-Identifier: MIT
33

44
#include <cassert>
5-
#include <iostream>
65

76
#include "tree.h"
87

@@ -45,6 +44,20 @@ int main() {
4544
assert(ds.find(i) == 0);
4645
}
4746
}
47+
{
48+
using CIt = DisjointSet<int>::const_iterator;
49+
50+
static_assert(std::random_access_iterator<CIt>);
51+
static_assert(std::same_as<std::iter_value_t<CIt>, std::pair<int, std::size_t>>);
52+
static_assert(std::same_as<std::iter_difference_t<CIt>, std::ptrdiff_t>);
53+
}
54+
{
55+
using CIt = DisjointSet<int>::iterator;
56+
57+
static_assert(std::random_access_iterator<CIt>);
58+
static_assert(std::same_as<std::iter_value_t<CIt>, std::pair<int, std::size_t>>);
59+
static_assert(std::same_as<std::iter_difference_t<CIt>, std::ptrdiff_t>);
60+
}
4861
{
4962
DisjointSet<int> ds(5);
5063
ds.union_rank(0, 1);

0 commit comments

Comments
 (0)