Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_persistent_treap.H
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 https://github.com/lrleon/Aleph-w
6
7 This file is part of Aleph-w library
8
9 Copyright (c) 2002-2026 Leandro Rabindranath Leon
10
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
17
18 The above copyright notice and this permission notice shall be included in all
19 copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 SOFTWARE.
28*/
29
72#ifndef TPL_PERSISTENT_TREAP_H
73#define TPL_PERSISTENT_TREAP_H
74
75#include <algorithm>
76#include <concepts>
77#include <cstdint>
78#include <limits>
79#include <memory>
80#include <type_traits>
81#include <utility>
82
83#include <ah-errors.H>
84#include <ahFunction.H>
85#include <tpl_array.H>
86
87namespace Aleph
88{
89
90namespace detail
91{
92 [[nodiscard]] inline std::uint64_t persistent_treap_priority(const std::uint64_t n) noexcept
93 {
94 std::uint64_t x = n + 0x9e3779b97f4a7c15ULL;
95 x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL;
96 x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL;
97 return x ^ (x >> 31);
98 }
99
100 template <typename Node, typename Key, class Compare>
102 {
103 using NodePtr = std::shared_ptr<const Node>;
104
105 [[nodiscard]] static size_t node_size(const NodePtr &p) noexcept
106 {
107 return p == nullptr ? 0 : p->count;
108 }
109
110 [[nodiscard]] static const Key *min_key(const NodePtr &node) noexcept
111 {
112 const Node *curr = node.get();
113 while (curr->left != nullptr)
114 curr = curr->left.get();
115 return curr->key.get();
116 }
117
118 [[nodiscard]] static const Key *max_key(const NodePtr &node) noexcept
119 {
120 const Node *curr = node.get();
121 while (curr->right != nullptr)
122 curr = curr->right.get();
123 return curr->key.get();
124 }
125
126 [[nodiscard]] static bool can_join(const NodePtr &left,
127 const NodePtr &right,
128 const Compare &cmp)
129 {
130 return left == nullptr or right == nullptr or cmp(*max_key(left), *min_key(right));
131 }
132
133 template <class Rebuild>
134 [[nodiscard]] static NodePtr rotate_right(const NodePtr &node, const Rebuild &rebuild)
135 {
136 const NodePtr child = node->left;
137 NodePtr new_right = rebuild(node, child->right, node->right);
138 return rebuild(child, child->left, std::move(new_right));
139 }
140
141 template <class Rebuild>
142 [[nodiscard]] static NodePtr rotate_left(const NodePtr &node, const Rebuild &rebuild)
143 {
144 const NodePtr child = node->right;
145 NodePtr new_left = rebuild(node, node->left, child->left);
146 return rebuild(child, std::move(new_left), child->right);
147 }
148
149 template <class Rebuild>
150 [[nodiscard]] static NodePtr join_nodes(const NodePtr &left,
151 const NodePtr &right,
152 const Rebuild &rebuild)
153 {
154 if (left == nullptr)
155 return right;
156 if (right == nullptr)
157 return left;
158
159 if (left->priority <= right->priority)
160 {
161 NodePtr new_right = join_nodes(left->right, right, rebuild);
162 return rebuild(left, left->left, std::move(new_right));
163 }
164
165 NodePtr new_left = join_nodes(left, right->left, rebuild);
166 return rebuild(right, std::move(new_left), right->right);
167 }
168
169 template <class Rebuild>
170 [[nodiscard]] static NodePtr erase_rec(const NodePtr &node,
171 const Key &key,
172 const Compare &cmp,
173 bool &erased,
174 const Rebuild &rebuild)
175 {
176 if (node == nullptr)
177 {
178 erased = false;
179 return nullptr;
180 }
181
182 if (cmp(key, *node->key))
183 {
184 NodePtr new_left = erase_rec(node->left, key, cmp, erased, rebuild);
185 if (not erased)
186 return node;
187 return rebuild(node, std::move(new_left), node->right);
188 }
189
190 if (cmp(*node->key, key))
191 {
192 NodePtr new_right = erase_rec(node->right, key, cmp, erased, rebuild);
193 if (not erased)
194 return node;
195 return rebuild(node, node->left, std::move(new_right));
196 }
197
198 erased = true;
199 return join_nodes(node->left, node->right, rebuild);
200 }
201
202 template <class Rebuild>
203 [[nodiscard]] static std::pair<NodePtr, NodePtr> split_rec(const NodePtr &node,
204 const Key &pivot,
205 const Compare &cmp,
206 const Rebuild &rebuild)
207 {
208 if (node == nullptr)
209 return {nullptr, nullptr};
210
211 if (cmp(*node->key, pivot))
212 {
213 auto [right_left, right_right] = split_rec(node->right, pivot, cmp, rebuild);
214 NodePtr left = rebuild(node, node->left, std::move(right_left));
215 return {std::move(left), std::move(right_right)};
216 }
217
218 auto [left_left, left_right] = split_rec(node->left, pivot, cmp, rebuild);
219 NodePtr right = rebuild(node, std::move(left_right), node->right);
220 return {std::move(left_left), std::move(right)};
221 }
222
223 static void collect_keys(const NodePtr &node, Array<Key> &out)
224 requires std::copy_constructible<Key>
225 {
226 if (node == nullptr)
227 return;
228 collect_keys(node->left, out);
229 out.append(Key(*node->key));
230 collect_keys(node->right, out);
231 }
232
233 [[nodiscard]] static bool verify_rec(const NodePtr &node,
234 const Key *lo,
235 const Key *hi,
236 const Compare &cmp,
237 size_t &count)
238 {
239 if (node == nullptr)
240 return true;
241 if (node->key == nullptr)
242 return false;
243 if constexpr (requires (const Node &n) { n.value; })
244 if (node->value == nullptr)
245 return false;
246 if (lo != nullptr and not cmp(*lo, *node->key))
247 return false;
248 if (hi != nullptr and not cmp(*node->key, *hi))
249 return false;
250 if (node->left != nullptr and node->left->priority < node->priority)
251 return false;
252 if (node->right != nullptr and node->right->priority < node->priority)
253 return false;
254
255 size_t left_count = 0;
256 size_t right_count = 0;
257 if (not verify_rec(node->left, lo, node->key.get(), cmp, left_count))
258 return false;
259 if (not verify_rec(node->right, node->key.get(), hi, cmp, right_count))
260 return false;
261 if (node->count != left_count + right_count + 1)
262 return false;
263 count = node->count;
264 return true;
265 }
266
267 [[nodiscard]] static bool is_valid_under(const NodePtr &node, const Compare &cmp)
268 {
269 size_t count = 0;
270 return verify_rec(node, nullptr, nullptr, cmp, count) and count == node_size(node);
271 }
272 };
273}
274
281template <typename Key, class Compare = Aleph::less<Key>>
283{
284 struct Node
285 {
286 std::shared_ptr<const Key> key;
287 std::uint64_t priority = 0;
288 size_t count = 1;
289 std::shared_ptr<const Node> left;
290 std::shared_ptr<const Node> right;
291 };
292
293 using NodePtr = std::shared_ptr<const Node>;
295
297 Compare cmp_;
298 std::uint64_t next_priority_ = 0;
299
300 [[nodiscard]] static NodePtr make_node(std::shared_ptr<const Key> key,
301 const std::uint64_t priority,
302 NodePtr left,
303 NodePtr right)
304 {
305 const size_t left_size = NodeOps::node_size(left);
306 const size_t right_size = NodeOps::node_size(right);
307 ah_overflow_error_if(left_size > std::numeric_limits<size_t>::max() - right_size)
308 << "PersistentTreapSet: node size would overflow";
309 const size_t children_size = left_size + right_size;
310 ah_overflow_error_if(children_size == std::numeric_limits<size_t>::max())
311 << "PersistentTreapSet: node size would overflow";
312
313 auto node = std::make_shared<Node>();
314 node->key = std::move(key);
315 node->priority = priority;
316 node->left = std::move(left);
317 node->right = std::move(right);
318 node->count = children_size + 1;
319 return node;
320 }
321
322 [[nodiscard]] static NodePtr rebuild_node(const NodePtr &node, NodePtr left, NodePtr right)
323 {
324 return make_node(node->key, node->priority, std::move(left), std::move(right));
325 }
326
327 [[nodiscard]] static NodePtr insert_rec(const NodePtr &node,
328 std::shared_ptr<const Key> key,
329 const std::uint64_t priority,
330 const Compare &cmp,
331 bool &inserted)
332 {
333 if (node == nullptr)
334 {
335 inserted = true;
336 return make_node(std::move(key), priority, nullptr, nullptr);
337 }
338
339 if (cmp(*key, *node->key))
340 {
341 NodePtr new_left = insert_rec(node->left, std::move(key), priority, cmp, inserted);
342 if (not inserted)
343 return node;
344 NodePtr rebuilt = make_node(node->key, node->priority, std::move(new_left), node->right);
345 return rebuilt->left->priority < rebuilt->priority
347 }
348
349 if (cmp(*node->key, *key))
350 {
351 NodePtr new_right = insert_rec(node->right, std::move(key), priority, cmp, inserted);
352 if (not inserted)
353 return node;
354 NodePtr rebuilt = make_node(node->key, node->priority, node->left, std::move(new_right));
355 return rebuilt->right->priority < rebuilt->priority
357 }
358
359 inserted = false;
360 return node;
361 }
362
363 PersistentTreapSet(NodePtr root, Compare cmp, const std::uint64_t next_priority)
364 : root_(std::move(root)), cmp_(std::move(cmp)), next_priority_(next_priority)
365 {
366 // Empty.
367 }
368
369public:
374 explicit PersistentTreapSet(Compare cmp = Compare())
375 : cmp_(std::move(cmp))
376 {
377 // Empty.
378 }
379
384 [[nodiscard]] bool is_empty() const noexcept { return root_ == nullptr; }
385
391
398 [[nodiscard]] const Key *find(const Key &key) const
399 {
400 const Node *curr = root_.get();
401 while (curr != nullptr)
402 if (cmp_(key, *curr->key))
403 curr = curr->left.get();
404 else if (cmp_(*curr->key, key))
405 curr = curr->right.get();
406 else
407 return curr->key.get();
408 return nullptr;
409 }
410
416 [[nodiscard]] bool contains(const Key &key) const
417 {
418 return find(key) != nullptr;
419 }
420
427 [[nodiscard]] PersistentTreapSet insert(const Key &key) const
428 {
429 auto stored_key = std::make_shared<const Key>(key);
430 bool inserted = false;
431 NodePtr root = insert_rec(root_, std::move(stored_key),
433 cmp_, inserted);
434 return inserted ? PersistentTreapSet(std::move(root), cmp_, next_priority_ + 1) : *this;
435 }
436
444 {
445 auto stored_key = std::make_shared<const Key>(std::move(key));
446 bool inserted = false;
447 NodePtr root = insert_rec(root_, std::move(stored_key),
449 cmp_, inserted);
450 return inserted ? PersistentTreapSet(std::move(root), cmp_, next_priority_ + 1) : *this;
451 }
452
459 [[nodiscard]] PersistentTreapSet erase(const Key &key) const
460 {
461 bool erased = false;
463 return erased ? PersistentTreapSet(std::move(root), cmp_, next_priority_) : *this;
464 }
465
472 [[nodiscard]] std::pair<PersistentTreapSet, PersistentTreapSet>
473 split(const Key &pivot) const
474 {
475 auto [left, right] = NodeOps::split_rec(root_, pivot, cmp_, rebuild_node);
476 return {PersistentTreapSet(std::move(left), cmp_, next_priority_),
477 PersistentTreapSet(std::move(right), cmp_, next_priority_)};
478 }
479
490 const PersistentTreapSet &right)
491 {
493 << "PersistentTreapSet::join(): right tree must be ordered by left comparator";
495 << "PersistentTreapSet::join(): left keys must be strictly less than right keys";
497 std::max(left.next_priority_, right.next_priority_));
498 }
499
509 {
510 return join(*this, right);
511 }
512
525
531 [[nodiscard]] bool verify() const
532 {
533 size_t count = 0;
534 return NodeOps::verify_rec(root_, nullptr, nullptr, cmp_, count) and count == size();
535 }
536};
537
545template <typename Key, typename T, class Compare = Aleph::less<Key>>
547{
548 struct Node
549 {
550 std::shared_ptr<const Key> key;
551 std::shared_ptr<const T> value;
552 std::uint64_t priority = 0;
553 size_t count = 1;
554 std::shared_ptr<const Node> left;
555 std::shared_ptr<const Node> right;
556 };
557
558 using NodePtr = std::shared_ptr<const Node>;
560
562 Compare cmp_;
563 std::uint64_t next_priority_ = 0;
564
565 [[nodiscard]] static NodePtr make_node(std::shared_ptr<const Key> key,
566 std::shared_ptr<const T> value,
567 const std::uint64_t priority,
568 NodePtr left,
569 NodePtr right)
570 {
571 const size_t left_size = NodeOps::node_size(left);
572 const size_t right_size = NodeOps::node_size(right);
573 ah_overflow_error_if(left_size > std::numeric_limits<size_t>::max() - right_size)
574 << "PersistentTreapMap: node size would overflow";
575 const size_t children_size = left_size + right_size;
576 ah_overflow_error_if(children_size == std::numeric_limits<size_t>::max())
577 << "PersistentTreapMap: node size would overflow";
578
579 auto node = std::make_shared<Node>();
580 node->key = std::move(key);
581 node->value = std::move(value);
582 node->priority = priority;
583 node->left = std::move(left);
584 node->right = std::move(right);
585 node->count = children_size + 1;
586 return node;
587 }
588
589 [[nodiscard]] static NodePtr rebuild_node(const NodePtr &node, NodePtr left, NodePtr right)
590 {
591 return make_node(node->key, node->value, node->priority,
592 std::move(left), std::move(right));
593 }
594
595 [[nodiscard]] static NodePtr insert_rec(const NodePtr &node,
596 std::shared_ptr<const Key> key,
597 std::shared_ptr<const T> value,
598 const std::uint64_t priority,
599 const Compare &cmp,
600 bool &inserted)
601 {
602 if (node == nullptr)
603 {
604 inserted = true;
605 return make_node(std::move(key), std::move(value), priority, nullptr, nullptr);
606 }
607
608 if (cmp(*key, *node->key))
609 {
610 NodePtr new_left = insert_rec(node->left, std::move(key), std::move(value),
611 priority, cmp, inserted);
612 if (not inserted)
613 return node;
614 NodePtr rebuilt = make_node(node->key, node->value, node->priority,
615 std::move(new_left), node->right);
616 return rebuilt->left->priority < rebuilt->priority
618 }
619
620 if (cmp(*node->key, *key))
621 {
622 NodePtr new_right = insert_rec(node->right, std::move(key), std::move(value),
623 priority, cmp, inserted);
624 if (not inserted)
625 return node;
626 NodePtr rebuilt = make_node(node->key, node->value, node->priority,
627 node->left, std::move(new_right));
628 return rebuilt->right->priority < rebuilt->priority
630 }
631
632 inserted = false;
633 return node;
634 }
635
637 std::shared_ptr<const Key> key,
638 std::shared_ptr<const T> value,
639 const std::uint64_t priority,
640 const Compare &cmp,
641 bool &inserted)
642 {
643 if (node == nullptr)
644 {
645 inserted = true;
646 return make_node(std::move(key), std::move(value), priority, nullptr, nullptr);
647 }
648
649 if (cmp(*key, *node->key))
650 {
651 NodePtr new_left = insert_or_assign_rec(node->left, std::move(key),
652 std::move(value), priority, cmp,
653 inserted);
654 NodePtr rebuilt = make_node(node->key, node->value, node->priority,
655 std::move(new_left), node->right);
656 return inserted and rebuilt->left->priority < rebuilt->priority
658 }
659
660 if (cmp(*node->key, *key))
661 {
662 NodePtr new_right = insert_or_assign_rec(node->right, std::move(key),
663 std::move(value), priority, cmp,
664 inserted);
665 NodePtr rebuilt = make_node(node->key, node->value, node->priority,
666 node->left, std::move(new_right));
667 return inserted and rebuilt->right->priority < rebuilt->priority
669 }
670
671 inserted = false;
672 return make_node(node->key, std::move(value), node->priority, node->left, node->right);
673 }
674
675 static void collect_items(const NodePtr &node, Array<std::pair<Key, T>> &out)
676 requires (std::copy_constructible<Key> and std::copy_constructible<T>)
677 {
678 if (node == nullptr)
679 return;
680 collect_items(node->left, out);
681 out.append(std::pair<Key, T>{*node->key, *node->value});
682 collect_items(node->right, out);
683 }
684
685 PersistentTreapMap(NodePtr root, Compare cmp, const std::uint64_t next_priority)
686 : root_(std::move(root)), cmp_(std::move(cmp)), next_priority_(next_priority)
687 {
688 // Empty.
689 }
690
691public:
696 explicit PersistentTreapMap(Compare cmp = Compare())
697 : cmp_(std::move(cmp))
698 {
699 // Empty.
700 }
701
706 [[nodiscard]] bool is_empty() const noexcept { return root_ == nullptr; }
707
713
720 [[nodiscard]] const T *find(const Key &key) const
721 {
722 const Node *curr = root_.get();
723 while (curr != nullptr)
724 if (cmp_(key, *curr->key))
725 curr = curr->left.get();
726 else if (cmp_(*curr->key, key))
727 curr = curr->right.get();
728 else
729 return curr->value.get();
730 return nullptr;
731 }
732
738 [[nodiscard]] bool contains(const Key &key) const
739 {
740 return find(key) != nullptr;
741 }
742
752 template <typename KArg, typename VArg>
753 requires std::constructible_from<Key, KArg &&> and std::constructible_from<T, VArg &&>
755 {
756 auto stored_key = std::make_shared<const Key>(std::forward<KArg>(key));
757 auto stored_value = std::make_shared<const T>(std::forward<VArg>(value));
758 bool inserted = false;
759 NodePtr root = insert_rec(root_, std::move(stored_key), std::move(stored_value),
761 cmp_, inserted);
762 return inserted ? PersistentTreapMap(std::move(root), cmp_, next_priority_ + 1) : *this;
763 }
764
773 template <typename KArg, typename VArg>
774 requires std::constructible_from<Key, KArg &&> and std::constructible_from<T, VArg &&>
776 {
777 auto stored_key = std::make_shared<const Key>(std::forward<KArg>(key));
778 auto stored_value = std::make_shared<const T>(std::forward<VArg>(value));
779 bool inserted = false;
781 std::move(stored_value),
783 cmp_, inserted);
784 return PersistentTreapMap(std::move(root), cmp_, inserted ? next_priority_ + 1
786 }
787
794 [[nodiscard]] PersistentTreapMap erase(const Key &key) const
795 {
796 bool erased = false;
798 return erased ? PersistentTreapMap(std::move(root), cmp_, next_priority_) : *this;
799 }
800
807 [[nodiscard]] std::pair<PersistentTreapMap, PersistentTreapMap>
808 split(const Key &pivot) const
809 {
810 auto [left, right] = NodeOps::split_rec(root_, pivot, cmp_, rebuild_node);
811 return {PersistentTreapMap(std::move(left), cmp_, next_priority_),
812 PersistentTreapMap(std::move(right), cmp_, next_priority_)};
813 }
814
825 const PersistentTreapMap &right)
826 {
828 << "PersistentTreapMap::join(): right tree must be ordered by left comparator";
830 << "PersistentTreapMap::join(): left keys must be strictly less than right keys";
832 std::max(left.next_priority_, right.next_priority_));
833 }
834
844 {
845 return join(*this, right);
846 }
847
860
873
879 [[nodiscard]] bool verify() const
880 {
881 size_t count = 0;
882 return NodeOps::verify_rec(root_, nullptr, nullptr, cmp_, count) and count == size();
883 }
884};
885
886} // namespace Aleph
887
888#endif // TPL_PERSISTENT_TREAP_H
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_unless(C)
Throws std::domain_error if condition does NOT hold.
Definition ah-errors.H:543
#define ah_overflow_error_if(C)
Throws std::overflow_error if condition holds.
Definition ah-errors.H:468
Standard functor implementations and comparison objects.
WeightedDigraph::Node Node
size_t size_t int32_t value
Definition ca-c-api.h:116
size_t size_t int32_t * out
Definition ca-c-api.h:120
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:138
void reserve(size_t cap)
Reserves cap cells into the array.
Definition tpl_array.H:320
Immutable ordered map backed by a path-copying treap.
std::pair< PersistentTreapMap, PersistentTreapMap > split(const Key &pivot) const
Split this version around pivot.
static void collect_items(const NodePtr &node, Array< std::pair< Key, T > > &out)
PersistentTreapMap(NodePtr root, Compare cmp, const std::uint64_t next_priority)
const T * find(const Key &key) const
Find a mapped value.
static NodePtr rebuild_node(const NodePtr &node, NodePtr left, NodePtr right)
and std::constructible_from< T, VArg && > PersistentTreapMap insert_or_assign(KArg &&key, VArg &&value) const
Return a new version with key assigned to value.
bool is_empty() const noexcept
Return true when the map has no bindings.
PersistentTreapMap erase(const Key &key) const
Return a new version without key.
PersistentTreapMap(Compare cmp=Compare())
Construct an empty persistent map.
static NodePtr make_node(std::shared_ptr< const Key > key, std::shared_ptr< const T > value, const std::uint64_t priority, NodePtr left, NodePtr right)
static NodePtr insert_rec(const NodePtr &node, std::shared_ptr< const Key > key, std::shared_ptr< const T > value, const std::uint64_t priority, const Compare &cmp, bool &inserted)
static PersistentTreapMap join(const PersistentTreapMap &left, const PersistentTreapMap &right)
Join two ordered, non-overlapping map versions.
Array< Key > keys() const
Return all keys in sorted order.
size_t size() const noexcept
Return the number of key/value bindings in this version.
bool verify() const
Verify treap, BST and cached-size invariants.
bool contains(const Key &key) const
Test whether key is present.
Array< std::pair< Key, T > > items() const
Return all key/value bindings in sorted-key order.
static NodePtr insert_or_assign_rec(const NodePtr &node, std::shared_ptr< const Key > key, std::shared_ptr< const T > value, const std::uint64_t priority, const Compare &cmp, bool &inserted)
PersistentTreapMap join(const PersistentTreapMap &right) const
Join this version with right.
std::shared_ptr< const Node > NodePtr
and std::constructible_from< T, VArg && > PersistentTreapMap insert(KArg &&key, VArg &&value) const
Return a new version with a binding inserted if absent.
Immutable ordered set backed by a path-copying treap.
static NodePtr rebuild_node(const NodePtr &node, NodePtr left, NodePtr right)
size_t size() const noexcept
Return the number of keys stored in this version.
Array< Key > keys() const
Return all keys in sorted order.
PersistentTreapSet insert(Key &&key) const
Return a new version with key inserted by move.
static NodePtr insert_rec(const NodePtr &node, std::shared_ptr< const Key > key, const std::uint64_t priority, const Compare &cmp, bool &inserted)
const Key * find(const Key &key) const
Find a key equivalent to key.
bool verify() const
Verify treap, BST and cached-size invariants.
PersistentTreapSet erase(const Key &key) const
Return a new version without key.
PersistentTreapSet insert(const Key &key) const
Return a new version with key inserted by copy.
std::shared_ptr< const Node > NodePtr
std::pair< PersistentTreapSet, PersistentTreapSet > split(const Key &pivot) const
Split this version around pivot.
bool is_empty() const noexcept
Return true when the set has no keys.
bool contains(const Key &key) const
Test whether key is present.
PersistentTreapSet(Compare cmp=Compare())
Construct an empty persistent set.
static PersistentTreapSet join(const PersistentTreapSet &left, const PersistentTreapSet &right)
Join two ordered, non-overlapping set versions.
PersistentTreapSet(NodePtr root, Compare cmp, const std::uint64_t next_priority)
static NodePtr make_node(std::shared_ptr< const Key > key, const std::uint64_t priority, NodePtr left, NodePtr right)
PersistentTreapSet join(const PersistentTreapSet &right) const
Join this version with right.
__gmp_expr< T, __gmp_binary_expr< __gmp_expr< T, U >, unsigned long int, __gmp_root_function > > root(const __gmp_expr< T, U > &expr, unsigned long int l)
Definition gmpfrxx.h:4071
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
std::uint64_t persistent_treap_priority(const std::uint64_t n) noexcept
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
and
Check uniqueness with explicit hash + equality functors.
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:105
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
STL namespace.
std::shared_ptr< const T > value
std::shared_ptr< const Node > left
std::shared_ptr< const Node > right
std::shared_ptr< const Key > key
std::shared_ptr< const Node > right
std::shared_ptr< const Node > left
std::shared_ptr< const Key > key
static std::pair< NodePtr, NodePtr > split_rec(const NodePtr &node, const Key &pivot, const Compare &cmp, const Rebuild &rebuild)
static NodePtr rotate_left(const NodePtr &node, const Rebuild &rebuild)
static void collect_keys(const NodePtr &node, Array< Key > &out)
std::shared_ptr< const Node > NodePtr
static NodePtr rotate_right(const NodePtr &node, const Rebuild &rebuild)
static const Key * min_key(const NodePtr &node) noexcept
static NodePtr join_nodes(const NodePtr &left, const NodePtr &right, const Rebuild &rebuild)
static size_t node_size(const NodePtr &p) noexcept
static const Key * max_key(const NodePtr &node) noexcept
static bool can_join(const NodePtr &left, const NodePtr &right, const Compare &cmp)
static bool verify_rec(const NodePtr &node, const Key *lo, const Key *hi, const Compare &cmp, size_t &count)
static NodePtr erase_rec(const NodePtr &node, const Key &key, const Compare &cmp, bool &erased, const Rebuild &rebuild)
static bool is_valid_under(const NodePtr &node, const Compare &cmp)
Dynamic array container with automatic resizing.