Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_union.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
51# ifndef TPL_UNION_H
52# define TPL_UNION_H
53
54# include <tpl_dynArray.H>
55# include <tpl_dynSetTree.H>
56
57# include <limits>
58# include <stdexcept>
59
60# include <ah-errors.H>
61
62
82{
83protected:
86 size_t num_blocks;
87
88 void verify_index(const size_t i) const
89 {
90 ah_out_of_range_error_if(i >= id.size()) << "index out of range";
91 }
92
93 virtual size_t root(size_t i)
94 {
95 verify_index(i);
96 while (i != id(i))
97 {
98 id(i) = id(id(i));
99 i = id(i);
100 }
101
102 return i;
103 }
104
105 size_t depth(size_t i) const
106 {
107 verify_index(i);
108 size_t d = 0;
109 while (true)
110 {
111 ++d;
112 const size_t parent = id(i);
113 verify_index(parent);
114 if (parent == i)
115 return d;
116 i = parent;
117 if (d > id.size())
118 ah_logic_error_if(d > id.size())
119 << "cycle detected in union-find structure";
120 }
121 }
122
123public:
124 virtual ~Fixed_Relation() = default;
125
127 Fixed_Relation(const size_t n = 0) : num_blocks(n)
128 {
129 if (num_blocks == 0)
130 return;
131
132 id.reserve(num_blocks);
134 for (size_t i = 0; i < num_blocks; ++i)
135 {
136 id(i) = i;
137 sz(i) = 1;
138 }
139 }
140
151 void set_n(size_t n)
152 {
153 id.empty();
154 sz.empty();
155 num_blocks = n;
156 if (num_blocks == 0)
157 return;
158
159 id.reserve(num_blocks);
161 for (size_t i = 0; i < num_blocks; ++i)
162 {
163 id(i) = i;
164 sz(i) = 1;
165 }
166 }
167
169 size_t size() const noexcept { return id.size(); }
170
173 [[nodiscard]] constexpr size_t get_num_blocks() const noexcept { return num_blocks; }
174
187 bool are_connected(size_t i, size_t j)
188 {
189 return root(i) == root(j);
190 }
191
198 void join(size_t i, size_t j)
199 {
200 i = root(i);
201 j = root(j);
202 if (i == j)
203 return;
204
205 if (sz(i) < sz(j))
206 {
207 id(i) = j;
208 sz(j) += sz(i);
209 }
210 else
211 {
212 id(j) = i;
213 sz(i) += sz(j);
214 }
215 --num_blocks;
216 }
217};
218
219
239{
240 void verify_if_add_new_points(const size_t n)
241 {
242 const size_t l = size();
243 if (n < l)
244 return;
245
246 id.reserve(l, n);
247 sz.reserve(l, n);
248 for (size_t i = l; i <= n; ++i)
249 {
250 id(i) = i;
251 sz(i) = 1;
252 }
253 num_blocks += n - l + 1;
254 }
255
256 size_t root(size_t i) override
257 {
259 return Fixed_Relation::root(i);
260 }
261
262public:
264 Relation(const size_t n = 0) : Fixed_Relation(n) {}
265};
266
267
284template <typename T, class Compare = Aleph::less<T>>
285class Relation_T : public Relation
286{
287 struct Pair
288 {
290 size_t i;
291
293
294 Pair(const T & __item, size_t __i)
295 : item(__item), i(__i)
296 { /* empty */
297 }
298 };
299
300 struct Cmp
301 {
302 bool operator ()(const Pair & p1, const Pair & p2) const noexcept
303 {
304 return Compare()(p1.item, p2.item);
305 }
306 };
307
309
310 // returns the item ID; either because it is found or because it is inserted
311 size_t test_and_insert_new_item(const T & item)
312 {
313 Pair p(item, std::numeric_limits<size_t>::max());
314 Pair *ptr = items_tree.search_or_insert(p);
315 if (ptr->i == std::numeric_limits<size_t>::max())
316 {
317 const size_t new_id = size();
318 ptr->i = new_id;
320 }
321 return ptr->i;
322 }
323
324public:
326 bool are_connected(const T & p, const T & q)
327 {
328 const size_t i = test_and_insert_new_item(p);
329 const size_t j = test_and_insert_new_item(q);
330
331 return Relation::are_connected(i, j);
332 }
333
335 void join(const T & p, const T & q)
336 {
337 const size_t i = test_and_insert_new_item(p);
338 const size_t j = test_and_insert_new_item(q);
339 Relation::join(i, j);
340 }
341};
342
343# endif // TPL_UNION_H
Exception handling system with formatted messages for Aleph-w.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Definition ah-errors.H:579
#define ah_logic_error_if(C)
Throws std::logic_error if condition holds.
Definition ah-errors.H:325
void empty() noexcept
Empty the array.
void reserve(const size_t l, const size_t r)
Allocate a range of entries.
Dynamic set implemented using AVL binary search trees of type Avl_Tree<Key>.
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
Binary relation between a set of integers.
Definition tpl_union.H:82
Fixed_Relation(const size_t n=0)
Initialize an empty binary relation of integers between 0 and n - 1.
Definition tpl_union.H:127
size_t size() const noexcept
Return the number of items of the set (not of relation)
Definition tpl_union.H:169
virtual size_t root(size_t i)
Definition tpl_union.H:93
DynArray< size_t > id
Definition tpl_union.H:84
void verify_index(const size_t i) const
Definition tpl_union.H:88
constexpr size_t get_num_blocks() const noexcept
Return the number of connected blocks, which is the number of equivalence classes.
Definition tpl_union.H:173
DynArray< size_t > sz
Definition tpl_union.H:85
void join(size_t i, size_t j)
Insert the pair '(i,j)' in the relation.
Definition tpl_union.H:198
bool are_connected(size_t i, size_t j)
Return true if item i is related to item j.
Definition tpl_union.H:187
size_t num_blocks
Definition tpl_union.H:86
void set_n(size_t n)
Set the number of items of the relation.
Definition tpl_union.H:151
virtual ~Fixed_Relation()=default
size_t depth(size_t i) const
Definition tpl_union.H:105
Binary relation between a set of items.
Definition tpl_union.H:286
bool are_connected(const T &p, const T &q)
Return true if p and q are connected; inserts missing items into the relation.
Definition tpl_union.H:326
size_t test_and_insert_new_item(const T &item)
Definition tpl_union.H:311
void join(const T &p, const T &q)
Join p with q; inserts missing items into the relation.
Definition tpl_union.H:335
DynSetAvlTree< Pair, Cmp > items_tree
Definition tpl_union.H:308
Binary relation between a set of integers.
Definition tpl_union.H:239
void verify_if_add_new_points(const size_t n)
Definition tpl_union.H:240
size_t root(size_t i) override
Definition tpl_union.H:256
Relation(const size_t n=0)
Initialize an empty relation of n elements between [0..n)
Definition tpl_union.H:264
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:107
DynList< T > maps(const C &c, Op op)
Classic map operation.
bool operator()(const Pair &p1, const Pair &p2) const noexcept
Definition tpl_union.H:302
Pair() noexcept
Definition tpl_union.H:292
Pair(const T &__item, size_t __i)
Definition tpl_union.H:294
Lazy and scalable dynamic array implementation.
Dynamic set implementations based on balanced binary search trees.
DynList< int > l