Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_flat_set.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
66#ifndef TPL_FLAT_SET_H
67#define TPL_FLAT_SET_H
68
69#include <algorithm>
70#include <initializer_list>
71#include <iterator>
72#include <utility>
73
74#include <ah-errors.H>
75#include <ahFunction.H>
76#include <tpl_memArray.H>
77#include <tpl_sort_utils.H>
78
79namespace Aleph {
80
127template <typename Key, class Compare = Aleph::less<Key>>
129{
131 Compare cmp_;
132
133 // Index of the first element not less than k (lower bound position).
134 size_t lower_idx(const Key &k) const
135 {
136 size_t lo = 0, hi = keys_.size();
137 while (lo < hi)
138 if (const size_t mid = lo + ((hi - lo) >> 1); cmp_(keys_(mid), k))
139 lo = mid + 1;
140 else
141 hi = mid;
142 return lo;
143 }
144
145 // Index of the first element greater than k (upper bound position).
146 size_t upper_idx(const Key &k) const
147 {
148 size_t lo = 0, hi = keys_.size();
149 while (lo < hi)
150 if (const size_t mid = lo + ((hi - lo) >> 1); not cmp_(k, keys_(mid)))
151 lo = mid + 1;
152 else
153 hi = mid;
154 return lo;
155 }
156
157 // True if pos holds a key equivalent to k. Assumes pos == lower_idx(k),
158 // so only the second half of the equivalence needs testing.
159 bool match_at(size_t pos, const Key &k) const
160 {
161 return pos < keys_.size() and not cmp_(k, keys_(pos));
162 }
163
164 // Opens one slot at pos by shifting [pos, n) one place right.
165 void make_room(const size_t pos)
166 {
167 keys_.putn(1);
168 Key *p = keys_.get_ptr();
169 for (size_t i = keys_.size() - 1; i > pos; --i)
170 p[i] = std::move(p[i - 1]);
171 }
172
173 // Removes the slot at pos by shifting (pos, n) one place left. A failed
174 // shrinking reallocation is ignored: the logical removal always succeeds.
175 void remove_at(const size_t pos)
176 {
177 Key *p = keys_.get_ptr();
178 const size_t last = keys_.size() - 1;
179 for (size_t i = pos; i < last; ++i)
180 p[i] = std::move(p[i + 1]);
181 try
182 {
183 (void) keys_.get();
184 }
185 catch (const std::bad_alloc &)
186 {
187 // Shrinking reallocation can fail; the logical removal already
188 // took effect because the element count was decremented first.
189 }
190 }
191
192 // Sorts the freshly loaded backing array and drops duplicates, keeping
193 // the first occurrence of each equivalence class.
195 {
196 Key *p = keys_.get_ptr();
197 timsort(p, keys_.size(), cmp_);
198 size_t m = 0;
199 for (size_t i = 0; i < keys_.size(); ++i)
200 if (m == 0 or cmp_(p[m - 1], p[i]))
201 {
202 if (i != m)
203 p[m] = std::move(p[i]);
204 ++m;
205 }
206 const size_t excess = keys_.size() - m;
207 if (excess > 0)
208 try
209 {
210 (void) keys_.get(excess);
211 }
212 catch (const std::bad_alloc &)
213 { /* shrink failed; logical removal already done */ }
214 }
215
216public:
217 using Item_Type = Key;
218 using Key_Type = Key;
219 using key_type = Key;
220 using value_type = Key;
221 using key_compare = Compare;
222 using size_type = size_t;
223 using iterator = const Key *;
224 using const_iterator = const Key *;
225
232 explicit FlatSet(size_t cap = MemArray<Key>::Min_Dim) : keys_(cap) {}
233
240 explicit FlatSet(const Compare &cmp, size_t cap = MemArray<Key>::Min_Dim) : keys_(cap), cmp_(cmp)
241 {}
242
255 template <std::input_iterator It>
256 FlatSet(It first, It last, const Compare &cmp = Compare())
257 : keys_(MemArray<Key>::Min_Dim), cmp_(cmp)
258 {
259 for (; first != last; ++first)
260 keys_.put(*first);
262 }
263
270 FlatSet(std::initializer_list<Key> l, const Compare &cmp = Compare())
271 : FlatSet(l.begin(), l.end(), cmp)
272 {}
273
275 FlatSet(const FlatSet &) = default;
276
279
282
285
287
292 {
293 keys_.swap(s.keys_);
294 std::swap(cmp_, s.cmp_);
295 }
296
297 // -- capacity -------------------------------------------------------------
298
301 {
302 return keys_.size();
303 }
304
307 {
308 return keys_.is_empty();
309 }
310
313 {
314 return keys_.capacity();
315 }
316
321 void reserve(size_t cap)
322 {
323 keys_.reserve(cap);
324 }
325
331 {
332 keys_.empty();
333 }
334
337 {
338 keys_.clear();
339 }
340
341 // -- lookup ---------------------------------------------------------------
342
348 const_iterator find(const Key &k) const
349 {
350 const size_t pos = lower_idx(k);
351 return match_at(pos, k) ? begin() + pos : end();
352 }
353
359 [[nodiscard]] bool contains(const Key &k) const
360 {
361 return match_at(lower_idx(k), k);
362 }
363
369 [[nodiscard]] size_t count(const Key &k) const
370 {
371 return contains(k) ? 1 : 0;
372 }
373
379 const_iterator lower_bound(const Key &k) const
380 {
381 return begin() + lower_idx(k);
382 }
383
389 const_iterator upper_bound(const Key &k) const
390 {
391 return begin() + upper_idx(k);
392 }
393
399 std::pair<const_iterator, const_iterator> equal_range(const Key &k) const
400 {
401 return {lower_bound(k), upper_bound(k)};
402 }
403
410 const Key &nth(size_t i) const
411 {
412 return keys_[i];
413 }
414
419 const Key &operator () (size_t i) const noexcept
420 {
421 return keys_(i);
422 }
423
428 const Key &get_first() const
429 {
430 ah_underflow_error_if(is_empty()) << "FlatSet::get_first(): empty set";
431 return keys_(0);
432 }
433
438 const Key &get_last() const
439 {
440 ah_underflow_error_if(is_empty()) << "FlatSet::get_last(): empty set";
441 return keys_(keys_.size() - 1);
442 }
443
445 const Key &min() const
446 {
447 return get_first();
448 }
449
451 const Key &max() const
452 {
453 return get_last();
454 }
455
456 // -- modifiers ------------------------------------------------------------
457
465 std::pair<const_iterator, bool> insert(const Key &k)
466 {
467 const size_t pos = lower_idx(k);
468 if (match_at(pos, k))
469 return {begin() + pos, false};
470 make_room(pos);
471 keys_.get_ptr()[pos] = k;
472 return {begin() + pos, true};
473 }
474
481 std::pair<const_iterator, bool> insert(Key &&k)
482 {
483 const size_t pos = lower_idx(k);
484 if (match_at(pos, k))
485 return {begin() + pos, false};
486 make_room(pos);
487 keys_.get_ptr()[pos] = std::move(k);
488 return {begin() + pos, true};
489 }
490
502 template <class... Args>
503 std::pair<const_iterator, bool> emplace(Args &&...args)
504 {
505 return insert(Key(std::forward<Args>(args)...));
506 }
507
514 size_t erase(const Key &k)
515 {
516 const size_t pos = lower_idx(k);
517 if (not match_at(pos, k))
518 return 0;
519 remove_at(pos);
520 return 1;
521 }
522
530 {
531 const size_t pos = it - begin();
532 ah_out_of_range_error_if(pos >= size()) << "FlatSet::erase(): iterator out of range";
533 remove_at(pos);
534 return begin() + pos;
535 }
536
537 // -- iteration ------------------------------------------------------------
538
541 {
542 return keys_.get_ptr();
543 }
544
547 {
548 return keys_.get_ptr() + keys_.size();
549 }
550
553 {
554 return begin();
555 }
556
559 {
560 return end();
561 }
562
564 const Key *data() const noexcept
565 {
566 return keys_.get_ptr();
567 }
568
578 template <class Operation>
580 {
581 const Key *p = keys_.get_ptr();
582 const size_t m = keys_.size();
583 for (size_t i = 0; i < m; ++i)
584 if (not operation(p[i]))
585 return false;
586 return true;
587 }
588
589 // -- comparison -----------------------------------------------------------
590
596 bool operator == (const FlatSet &s) const
597 {
598 return size() == s.size() and std::equal(begin(), end(), s.begin());
599 }
600
602 bool operator != (const FlatSet &s) const
603 {
604 return not (*this == s);
605 }
606};
607
608} // end namespace Aleph
609
610#endif // TPL_FLAT_SET_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:584
#define ah_underflow_error_if(C)
Throws std::underflow_error if condition holds.
Definition ah-errors.H:373
Standard functor implementations and comparison objects.
Generic filter iterator wrapper.
Ordered set stored as a sorted contiguous array.
const Key * iterator
Random-access iterator (immutable).
const Key * const_iterator
Random-access const iterator.
const_iterator erase(const_iterator it)
Remove the key at iterator it.
FlatSet(const Compare &cmp, size_t cap=MemArray< Key >::Min_Dim)
Construct an empty set with a specific comparator.
void make_room(const size_t pos)
size_t capacity() const noexcept
Return the capacity of the backing array. O(1).
bool operator==(const FlatSet &s) const
Equality: same size and pairwise equal elements.
void sort_and_unique()
const Key & min() const
Smallest key (checked). Alias of get_first().
size_t upper_idx(const Key &k) const
const_iterator upper_bound(const Key &k) const
First element greater than k.
size_t erase(const Key &k)
Remove the key equivalent to k, if present.
FlatSet(std::initializer_list< Key > l, const Compare &cmp=Compare())
Construct from an initializer list.
FlatSet(It first, It last, const Compare &cmp=Compare())
Construct from an iterator range.
size_t lower_idx(const Key &k) const
Key value_type
STL convention: value type.
Key Item_Type
Aleph convention: element type.
const_iterator end() const noexcept
Iterator past the greatest key. O(1).
Key key_type
STL convention: key type.
const_iterator find(const Key &k) const
Find a key.
FlatSet(const FlatSet &)=default
Copy constructor (requires copyable Key).
FlatSet(size_t cap=MemArray< Key >::Min_Dim)
Construct an empty set.
bool match_at(size_t pos, const Key &k) const
std::pair< const_iterator, bool > insert(Key &&k)
Insert k by moving if no equivalent key exists.
void empty() noexcept
Remove all keys (Aleph convention).
Compare key_compare
STL convention: comparator type.
size_t count(const Key &k) const
Count occurrences of a key (0 or 1).
FlatSet(FlatSet &&) noexcept=default
Move constructor. The source is left valid but unspecified.
std::pair< const_iterator, bool > emplace(Args &&...args)
Construct a key in place and insert it.
std::pair< const_iterator, const_iterator > equal_range(const Key &k) const
Range of elements equivalent to k.
const_iterator cend() const noexcept
Const iterator past the greatest key. O(1).
void clear() noexcept
Remove all keys. Alias of empty(). Capacity is kept.
MemArray< Key > keys_
const Key & operator()(size_t i) const noexcept
Positional access without bounds checking.
const Key & max() const
Greatest key (checked). Alias of get_last().
bool traverse(Operation operation) const
Traverse keys in sorted order while operation returns true.
const Key * data() const noexcept
Pointer to the underlying sorted, contiguous storage. O(1).
void reserve(size_t cap)
Reserve capacity for at least cap keys.
const_iterator lower_bound(const Key &k) const
First element not less than k.
bool contains(const Key &k) const
Test membership.
size_t size() const noexcept
Return the number of stored keys. O(1).
size_t size_type
STL convention: size type.
bool is_empty() const noexcept
Return true if the set holds no keys. O(1).
const Key & get_first() const
Smallest key (checked).
const_iterator cbegin() const noexcept
Const iterator to the smallest key. O(1).
const Key & nth(size_t i) const
Positional access to the i-th smallest key (checked).
std::pair< const_iterator, bool > insert(const Key &k)
Insert a copy of k if no equivalent key exists.
Key Key_Type
Aleph convention: key type.
void remove_at(const size_t pos)
const Key & get_last() const
Greatest key (checked).
void swap(FlatSet &s) noexcept(std::is_nothrow_swappable_v< Compare >)
Swap contents with s in O(1).
bool operator!=(const FlatSet &s) const
Inequality: negation of operator==.
const_iterator begin() const noexcept
Iterator to the smallest key. O(1).
Simple, scalable and fast dynamic array.
void reserve(const size_t cap)
Reserves cap cells into the array.
size_t size() const noexcept
Return the number of elements.
void putn(const size_t more)
Reserve more additional logical slots in the array.
void clear() noexcept
Alias for empty().
T * get_ptr() const noexcept
Return the current base of array.
constexpr size_t capacity() const noexcept
The type of element of array.
bool is_empty() const noexcept
Return true is the array is empty.
void empty() noexcept
Empties the container.
T get(const size_t i=1)
Remove i elements from the end.
void swap(MemArray &a) noexcept
Swap in constant time this with a
T & put(const T &item)
Put a copy of item at the end of sequence.
int cmp(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4129
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
void timsort(T *a, const size_t n, const Compare &cmp=Compare())
Timsort — adaptive, stable, natural merge sort.
and
Check uniqueness with explicit hash + equality functors.
STL namespace.
FooMap m(5, fst_unit_pair_hash, snd_unit_pair_hash)
static int * k
Simple, scalable, contiguous dynamic array.
Comprehensive sorting algorithms and search utilities for Aleph-w.
DynList< int > l