Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_dynSetTree.H
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
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
31
45# ifndef TPL_DYNSETTREE_H
46# define TPL_DYNSETTREE_H
47
48# include <cassert>
49# include <typeinfo>
50# include <type_traits>
51# include <utility>
52# include <algorithm>
53# include <memory>
54# include <stdexcept>
55# include <ah-errors.H>
56# include <ah-args-ctor.H>
57# include <ahIterator.H>
58# include <ah-zip.H>
59# include <ah-arena.H>
60# include <tpl_binNodeUtils.H>
61# include <tpl_binNodeXt.H>
62# include <tpl_binTree.H>
63# include <tpl_treap.H>
64# include <tpl_treapRk.H>
65# include <tpl_avl.H>
66# include <tpl_avlRk.H>
67# include <tpl_rand_tree.H>
68# include <tpl_rb_tree.H>
69# include <tpl_rbRk.H>
70# include <tpl_tdRbTree.H>
71# include <tpl_tdRbTreeRk.H>
72# include <tpl_hRbTree.H>
73# include <tpl_hRbTreeRk.H>
74# include <tpl_splay_tree.H>
75# include <tpl_splay_treeRk.H>
76# include <ah-concepts.H>
77
78using namespace Aleph;
79
80namespace Aleph
81{
82 template <typename Node>
84 {
85 public:
87
88 virtual Node * alloc_lval(const typename Node::key_type & key) = 0;
89
90 virtual Node * alloc_rval(typename Node::key_type && key) = 0;
91
92 virtual void unalloc(Node *) = 0;
93
94 virtual ~AbstractTreeNodeAllocator() = default;
95 };
96
97 template <typename Node>
99 {
100 public:
101 Node * alloc_lval(const typename Node::key_type & key) override
102 {
103 return new Node(key);
104 }
105
106 Node * alloc_rval(typename Node::key_type && key) override
107 {
108 return new Node(std::forward<typename Node::key_type>(key));
109 }
110
111 void unalloc(Node *p) override
112 {
113 delete p;
115
116 ~DftTreeNodeAllocator() override = default;
117 };
118
119 template <typename Node>
121 {
123
124 ArenaTreeAllocator(const size_t & sz = 1024 * 1024)
125 : arena(sz)
126 {
127 // empty
128 }
129
130 ArenaTreeAllocator(const char *base_addr, const size_t & sz)
131 : arena(base_addr, sz)
132 {
133 // empty
134 }
135
136 Node * alloc_lval(const typename Node::key_type & key) override
137 {
138 Node *ptr = allocate<Node>(arena, key);
139 ah_bad_alloc_if(ptr == nullptr);
140 return ptr;
141 }
142
143 Node * alloc_rval(typename Node::key_type && key) override
144 {
145 Node *ptr =
146 allocate<Node>(arena, std::forward<typename Node::key_type>(key));
147 ah_bad_alloc_if(ptr == nullptr);
148 return ptr;
149 }
150
151 void unalloc(Node *p) override
152 {
154 }
155
157 {
158 return arena.allocated_size();
159 }
160
162 {
163 return arena.available_size();
164 }
165
167 };
168
169 template <typename Container, typename T>
171 {
172 bool operator ()(const Container & c1, const Container & c2) const
173 {
174 return std::lexicographical_compare(c1.begin(), c1.end(), c2.begin(), c2.end(),
175 [](const T & item1, const T & item2)
176 {
177 return item1 < item2;
178 });
179 }
180 };
181
265 template <typename Key,
266 template <typename, class> class Tree = Avl_Tree,
267 class Compare = Aleph::less<Key>>
271 : public LocateFunctions<DynSetTree<Key, Tree, Compare>, Key>,
272 public FunctionalMethods<DynSetTree<Key, Tree, Compare>, Key>,
273 public GenericKeys<DynSetTree<Key, Tree, Compare>, Key>,
274 public EqualToMethod<DynSetTree<Key, Tree, Compare>>,
275 public StlAlephIterator<DynSetTree<Key, Tree, Compare>>
276 {
277 public:
281
283
284 private:
285 template <typename T>
287 {
288 // The const forms cover RB, AVL, etc.; the non-const ones cover the
289 // splay tree, whose lookups restructure the tree.
290 static constexpr bool has_select =
291 requires(const T & t) { t.select(std::declval<size_t>()); } or
292 requires(T & t) { t.select(std::declval<size_t>()); };
293 static constexpr bool has_remove_pos =
294 requires(T & t) { t.remove_pos(std::declval<size_t>()); };
295 static constexpr bool has_split_pos =
296 requires(T & t, T & l, T & r) { t.split_pos(std::declval<size_t>(), l, r); };
297 static constexpr bool has_position =
298 requires(const T & t, const Key & k) { t.position(k); } or
299 requires(T & t, const Key & k) { t.position(k); };
300 static constexpr bool has_find_position =
301 requires(const T & t, const Key & k) { t.find_position(k); } or
302 requires(T & t, const Key & k) { t.find_position(k); };
303 };
304
305 // call_select for const trees (RB, AVL, etc.)
306 template <typename T>
307 static auto call_select(const T & t, const size_t i, int)
308 -> decltype(t.select(i))
309 {
310 return t.select(i);
311 }
312
313 // call_select for non-const trees (Splay - mutates on access)
314 template <typename T>
315 static auto call_select_nc(T & t, const size_t i, int)
316 -> decltype(t.select(i))
317 {
318 return t.select(i);
319 }
320
321 template <typename T>
322 static Node * call_select(const T &, const size_t, ...)
323 {
324 ah_domain_error() << "select is not supported by underlying tree";
325 return nullptr;
326 }
327
328 template <typename T>
329 static Node * call_select_nc(T &, const size_t, ...)
330 {
331 ah_domain_error() << "select is not supported by underlying tree";
332 return nullptr;
333 }
334
335 template <typename T>
336 static auto call_remove_pos(T & t, const size_t i, int)
337 -> decltype(t.remove_pos(i))
338 {
339 return t.remove_pos(i);
340 }
341
342 template <typename T>
343 static Node * call_remove_pos(T &, const size_t, ...)
344 {
345 ah_domain_error() << "remove_pos is not supported by underlying tree";
346 return nullptr;
347 }
348
349 template <typename T>
350 static auto call_split_pos(T & t, const size_t pos, T & l, T & r, int)
351 -> decltype(t.split_pos(pos, l, r), void())
352 {
353 t.split_pos(pos, l, r);
354 }
355
356 template <typename T>
357 static void call_split_pos(T &, const size_t, T &, T &, ...)
358 {
359 ah_domain_error() << "split_pos is not supported by underlying tree";
360 }
361
362 template <typename T>
363 static auto call_position(const T & t, const Key & key, int)
364 -> decltype(t.position(key))
365 {
366 return t.position(key);
367 }
368
369 template <typename T>
370 static std::pair<long, Node *> call_position(const T &, const Key &, ...)
371 {
372 ah_domain_error() << "position is not supported by underlying tree";
373 return std::pair<long, Node *>(0, nullptr);
374 }
375
376 template <typename T>
377 static auto call_find_position(const T & t, const Key & key, int)
378 -> decltype(t.find_position(key))
379 {
380 return t.find_position(key);
381 }
382
383 template <typename T>
384 static std::pair<long, Node *> call_find_position(const T &, const Key &, ...)
385 {
386 ah_domain_error() << "find_position is not supported by underlying tree";
387 return std::pair<long, Node *>(0, nullptr);
388 }
389
390 static constexpr size_t dim = 13;
391
393 size_t num_nodes;
394 std::unique_ptr<ArenaTreeAllocator<Node>> arena_allocator;
395
396 Node * alloc_node(const Key & key)
397 {
398 if (arena_allocator)
399 return arena_allocator->alloc_lval(key);
400 return new Node(key);
401 }
402
403 Node * alloc_node(Key && key)
404 {
405 if (arena_allocator)
406 return arena_allocator->alloc_rval(std::forward<Key>(key));
407 return new Node(std::forward<Key>(key));
408 }
409
411 {
412 if (arena_allocator)
413 arena_allocator->unalloc(p);
414 else
415 delete p;
416 }
417
418 public:
420
421 typedef Key Item_Type;
422
423 typedef Key Key_Type;
424
431 noexcept(noexcept(tree.swap(dset.tree)) and
432 noexcept(std::swap(num_nodes, dset.num_nodes)) and
433 noexcept(std::swap(arena_allocator, dset.arena_allocator)))
434 {
435 tree.swap(dset.tree);
436 std::swap(num_nodes, dset.num_nodes);
437 std::swap(arena_allocator, dset.arena_allocator);
438 }
439
441 DynSetTree(const Compare & cmp = Compare())
442 : tree(cmp), num_nodes(0)
443 {
444 // empty
445 }
446
448 DynSetTree(const char *base_addr, const size_t & sz,
449 const Compare & cmp = Compare())
450 : tree(cmp), num_nodes(0),
452 {
453 // empty
454 }
455
457 explicit DynSetTree(const size_t & arena_sz,
458 const Compare & cmp = Compare())
459 : tree(cmp), num_nodes(0),
461 {
462 // empty
463 }
464
467 : tree(srcTree.tree.get_compare()), num_nodes(srcTree.num_nodes)
468 {
469 Node *srcRoot = srcTree.tree.getRoot();
470 try
471 {
472 tree.getRoot() = copyRec(srcRoot);
473 }
474 catch (...)
475 {
476 num_nodes = 0;
477 throw;
478 }
479 }
480
482
488
490 void empty()
491 {
492 if (arena_allocator)
493 {
494 // For arena allocation, just call destructors on keys
495 // (arena handles memory deallocation)
496 callKeyDestructorsRec(tree.getRoot());
497
498 // Reset tree
499 tree.getRoot() = Node::NullPtr;
500 num_nodes = 0;
501 return;
502 }
503
504 destroyRec(tree.getRoot());
505 tree.getRoot() = Node::NullPtr;
506 num_nodes = 0;
507 }
508
514 void clear() { empty(); }
515
517 {
518 return *this = DynSetTree(list);
519 }
520
523 {
524 if (this == &srcTree)
525 return *this;
526
527 Node *src_root = srcTree.tree.getRoot();
528
529 empty();
530
531 tree.getRoot() = copyRec(src_root);
532 num_nodes = srcTree.num_nodes;
533
534 return *this;
535 }
536
539 noexcept
540 {
541 if (this == &srcTree)
542 return *this;
543
544 empty();
545 swap(srcTree);
546 return *this;
547 }
548
550 virtual ~DynSetTree()
551 {
552 empty();
553 }
554
555 private:
556 Key * __insert(Node *p)
557 {
558 Node *q = nullptr;
559 try
560 {
561 q = tree.search_or_insert(p);
562 }
563 catch (...)
564 {
565 free_node(p);
566 throw;
567 }
568
569 if (q != p)
570 return nullptr;
571
572 ++num_nodes;
573
574 return &p->get_key();
575 }
576
577 public:
586 Key * insert(const Key & key)
587 {
588 Node *p = alloc_node(key);
589 Key *key_p = __insert(p);
590 if (key_p == nullptr) // was there insertion?
591 { // No (KEY(p) is already in the tree) ==> free p and return nullptr
592 free_node(p);
593 return nullptr;
594 }
595
596 return key_p;
597 }
598
599 Key * insert(Key && key)
600 {
601 Node *p = alloc_node(std::forward<Key>(key));
602 Key *key_p = __insert(p);
603 if (key_p == nullptr) // was there insertion?
604 {
605 free_node(p);
606 return nullptr;
607 }
608
609 return key_p;
610 }
611
612 Key * append(const Key & key)
613 {
614 return insert(key);
615 }
616
617 Key * append(Key && key)
618 {
619 return insert(std::forward<Key>(key));
620 }
621
622 private:
624 {
625 Node *q = nullptr;
626 try
627 {
628 q = tree.search_or_insert(p);
629 }
630 catch (...)
631 {
632 free_node(p);
633 throw;
634 }
635 if (q != p) // was there an insertion?
636 free_node(p); // No (KEY(p) is already in the tree) ==> free
637 // allocated node
638 else
639 ++num_nodes;
640
641 return &q->get_key();
642 }
643
644 std::pair<Node *, bool> __contains_or_insert(Node *p)
645 {
646 Node *q = nullptr;
647 try
648 {
649 q = tree.search_or_insert(p);
650 }
651 catch (...)
652 {
653 free_node(p);
654 throw;
655 }
656 if (q != p)
657 { // KEY(p) is already inside the tree
658 free_node(p);
659 return std::pair<Node *, bool>(q, true);
660 }
661 ++num_nodes;
662 return std::pair<Node *, bool>(p, false);
663 }
664
665 public:
678 Key * search_or_insert(const Key & key)
679 {
680 return __search_or_insert(alloc_node(key));
681 }
682
683 Key * search_or_insert(Key && key)
684 {
685 return
686 __search_or_insert(alloc_node(std::forward<Key>(key)));
687 }
688
689 /* Look for the key <code>key</code> in the binary search tree and
690 eventually inserts it if it is not found.
691
692 <code>contains_or_insert(key)</code> searches the tree for the key
693 <code>key</code>. If the key is already found, then it is returned
694 true. Otherwise, the key is inserted and false is returned.
695
696 @param[in] key to find or insert
697 @return a std::pair whose first field is a pointer to the found or
698 inserted key, and the second field is a boolean whose value is
699 `false` if the key was inserted; `true` otherwise, that is if the
700 key is already present in the tree.
701 */
702 std::pair<Key *, bool> contains_or_insert(const Key & key)
703 {
704 auto p = __contains_or_insert(alloc_node(key));
705 return std::pair<Key *, bool>(&p.first->get_key(), p.second);
706 }
707
708 std::pair<Key *, bool> contains_or_insert(Key && key)
709 {
710 auto p = __contains_or_insert(alloc_node(std::forward<Key>(key)));
711 return std::pair<Key *, bool>(&p.first->get_key(), p.second);
712 }
713
714 private:
716 {
717 try
718 {
719 Node *p = tree.insert_dup(q);
720 ++num_nodes;
721 return &p->get_key();
722 }
723 catch (...)
724 {
725 free_node(q);
726 throw;
727 }
728 }
729
730 public:
731 Key * insert_dup(const Key & key)
732 {
733 return __insert_dup(alloc_node(key));
734 }
735
736 Key * insert_dup(Key && key)
737 {
738 return __insert_dup(alloc_node(std::forward<Key>(key)));
739 }
740
741 Key * put(const Key & key)
742 {
743 return insert(key);
744 }
745
746 Key * put(Key && key)
747 {
748 return insert(std::forward<Key>(key));
749 }
750
758 size_t remove(const Key & key)
759 {
760 Node *p = static_cast<Node *>(tree.remove(key));
761
762 if (p == nullptr)
763 return num_nodes;
764
765 free_node(p);
766
767 return --num_nodes;
768 }
769
780 Key del(const Key & key)
781 {
782 Node *p = static_cast<Node *>(tree.remove(key));
783
784 ah_domain_error_if(p == nullptr)
785 << "DynSetTree::del key is not found in the tree";
786
787 auto ret_val = p->get_key();
788
789 free_node(p);
790
791 --num_nodes;
792
793 return ret_val;
794 }
795
800 Key remove_pos(const size_t i)
801 {
803 << "remove_pos is not supported by underlying tree";
804
806 << "remove_pos index out of range";
807
808 Node *p = static_cast<Node *>(call_remove_pos(tree, i, 0));
809 ah_logic_error_if(p == nullptr)
810 << "remove_pos returned nullptr";
811 const Key ret_val = KEY(p);
812
813 free_node(p);
814
815 --num_nodes;
816
817 return ret_val;
818 }
819
821 bool exist(const Key & key) const
822 {
823 return search(key) != nullptr;
824 }
825
826 bool has(const Key & key) const
827 {
828 return exist(key);
829 }
830
837 bool contains(const Key & key) const
838 {
839 return exist(key);
840 }
841
856 Key &find(const Key & key) const
857 {
858 Node *node = static_cast<Node *>(tree.search(key));
859
860 ah_domain_error_if(node == nullptr)
861 << "key not found";
862
863 return node->get_key();
864 }
865
880 std::pair<long, Key *> find_position(const Key & key) const
881 {
883 << "find_position is not supported by underlying tree";
884
885 if (num_nodes == 0)
886 return std::pair<long, Key *>(0, nullptr);
887
888 auto p = call_find_position(tree, key, 0);
889 if (p.second == nullptr)
890 return std::pair<long, Key *>(static_cast<long>(p.first), nullptr);
891
892 return std::pair<long, Key *>(static_cast<long>(p.first),
893 &p.second->get_key());
894 }
895
910 Key * search(const Key & key) const
911 {
912 Node *node = static_cast<Node *>(tree.search(key));
913
914 if (node == nullptr)
915 return nullptr;
916
917 return &(node->get_key());
918 }
919
922 const Key &min() const
923 {
925 << "set is empty";
926
927 return find_min(tree.getRoot())->get_key();
928 }
929
931 const Key &get_first() const { return min(); }
932
935 const Key &max() const
936 {
938 << "set is empty";
939
940 return find_max(tree.getRoot())->get_key();
941 }
942
944 const Key &get_last() const { return max(); }
945
947 const Key &get() const { return max(); }
948
950 const size_t &size() const { return num_nodes; }
951
953 bool is_empty() const { return num_nodes == 0; }
954
957 {
958 return arena_allocator != nullptr;
959 }
960
963 {
964 if (arena_allocator)
965 return arena_allocator->allocated_size();
966 return 0;
967 }
968
971 {
972 if (arena_allocator)
973 return arena_allocator->available_size();
974 return 0;
975 }
976
979 size_t internal_path_length() const
980 {
981 return Aleph::internal_path_length(tree.getRoot());
982 }
983
984 Node * get_root_node() const { return tree.getRoot(); }
985
986 const Key &get_root() const
987 {
989 << "Tree is empty";
990 return KEY(tree.getRoot());
991 }
992
994 const Key &get_item() const { return get_root(); }
995
997 size_t height() const { return computeHeightRec(tree.getRoot()); }
998
1001 template <class Op>
1002 void for_each_in_preorder(void (*visitFct)(Node *, int, int))
1003 {
1004 Node *root = static_cast<Node *>(tree.getRoot());
1006 }
1007
1020 long position(const Key & key) const
1021 {
1023 << "position is not supported by underlying tree";
1024
1025 auto p = call_position(tree, key, 0);
1026 return static_cast<long>(p.first);
1027 }
1028
1034 Key &select(size_t i)
1035 {
1037 << "select is not supported by underlying tree";
1038
1040 << "select index out of range";
1041
1042 // Try non-const first (for Splay trees), then const
1043 Node *p = call_select_nc(tree, i, 0);
1044 ah_logic_error_if(p == nullptr)
1045 << "select returned nullptr";
1046 return p->get_key();
1047 }
1048
1049 const Key &select(size_t i) const
1050 {
1052 << "select is not supported by underlying tree";
1053
1055 << "select index out of range";
1056
1057 // For const version, only const select works (not for Splay trees)
1058 Node *p = call_select(tree, i, 0);
1059 ah_logic_error_if(p == nullptr)
1060 << "select returned nullptr";
1061 return p->get_key();
1062 }
1063
1064 Key &operator ()(size_t i)
1065 {
1066 return select(i);
1067 }
1068
1069 const Key &operator [](const Key & key) const
1070 {
1071 return find(key);
1072 }
1073
1074 const Key &operator [](const Key & key)
1075 {
1076 return *search_or_insert(key);
1077 }
1078
1079 Key &access(size_t i)
1080 {
1081 return select(i);
1082 }
1083
1084 bool verify() const
1085 {
1086 return tree.verify() and check_bst(tree.getRoot());
1087 }
1088
1089 private:
1090 template <class Key_Op>
1091 struct Node_Op
1092 {
1094
1096 { /* empty */
1097 }
1098
1100 {
1101 /* empty */
1102 }
1103
1105 {
1106 assert(root != nullptr);
1107 key_op(KEY(root));
1108 }
1109 };
1110
1111 public:
1136 template <class Key_Op>
1137 void for_each_preorder(Key_Op & key_op) const
1138 {
1139 Node *root = static_cast<Node *>(tree.getRoot());
1140
1141 Node_Op<Key_Op> node_op(const_cast<Key_Op &>(key_op));
1142
1144 }
1145
1153 template <class Key_Op>
1154 void for_each_preorder(Key_Op && key_op = Key_Op()) const
1155 {
1157 }
1158
1183 template <class Key_Op>
1184 void for_each_inorder(Key_Op & key_op) const
1185 {
1186 Node *root = static_cast<Node *>(tree.getRoot());
1187
1188 Node_Op<Key_Op> node_op(const_cast<Key_Op &>(key_op));
1189
1191 }
1192
1200 template <class Key_Op>
1201 void for_each_inorder(Key_Op && key_op = Key_Op()) const
1202 {
1204 }
1205
1230 template <class Key_Op>
1231 void for_each_postorder(Key_Op & key_op) const
1232 {
1233 Node *root = static_cast<Node *>(tree.getRoot());
1234
1235 Node_Op<Key_Op> node_op(const_cast<Key_Op &>(key_op));
1236
1238 }
1239
1247 template <class Key_Op>
1248 void for_each_postorder(Key_Op && key_op = Key_Op()) const
1249 {
1251 }
1252
1266 {
1267 tree.join(t.tree, dup.tree);
1268 t.tree.getRoot() = Node::NullPtr;
1269 t.num_nodes = 0;
1271 dup.num_nodes = compute_cardinality_rec(dup.tree.getRoot());
1272 return *this;
1273 }
1274
1285 {
1286 return join(t, dup);
1287 }
1288
1302 {
1303 tree.join_dup(t.tree);
1304 t.num_nodes = 0;
1305 t.tree.getRoot() = Node::NullPtr;
1307 return *this;
1308 }
1309
1325 bool split_key(const Key & key, DynSetTree & l, DynSetTree & r)
1326 {
1327 if (not tree.split_key(key, l.tree, r.tree))
1328 return false;
1329
1330 tree.getRoot() = Node::NullPtr;
1331 num_nodes = 0;
1332 l.num_nodes = compute_cardinality_rec(l.tree.getRoot());
1333 r.num_nodes = compute_cardinality_rec(r.tree.getRoot());
1334
1335 return true;
1336 }
1337
1350 void split_pos(const size_t pos, DynSetTree & l, DynSetTree & r)
1351 {
1353 << "split_pos is not supported by underlying tree";
1354
1356 << "split_pos position out of range";
1357
1358 // Underlying split_pos splits at [0, pos) and [pos, N)
1359 // But we want [0, pos] and (pos, N), so we split at pos+1
1360 call_split_pos(tree, pos + 1, l.tree, r.tree, 0);
1361 tree.getRoot() = Node::NullPtr;
1362 num_nodes = 0;
1363 l.num_nodes = compute_cardinality_rec(l.tree.getRoot());
1364 r.num_nodes = compute_cardinality_rec(r.tree.getRoot());
1365 }
1366
1379 void split_key_dup(const Key & key, DynSetTree & l, DynSetTree & r)
1380 {
1381 tree.split_key_dup(key, l.tree, r.tree);
1382 tree.getRoot() = Node::NullPtr;
1383 num_nodes = 0;
1384 l.num_nodes = compute_cardinality_rec(l.tree.getRoot());
1385 r.num_nodes = compute_cardinality_rec(r.tree.getRoot());
1386 }
1387
1388 struct Iterator : public Tree_Type::Iterator
1389 {
1390 using Base = typename Tree_Type::Iterator;
1391
1393
1396
1398 { /* empty */
1399 }
1400
1402 {
1403 return Base::get_curr_ne()->get_key();
1404 }
1405
1406 Key &get_curr_ne() noexcept { return Base::get_curr_ne()->get_key(); }
1407
1408 const Key &get_curr() const { return Base::get_curr()->get_key(); }
1409
1410 Key &get_curr() { return Base::get_curr()->get_key(); }
1411 };
1412
1427 template <class Operation>
1429 {
1430 return Aleph::traverse(tree.getRoot(), [&op](Node *p)
1431 {
1432 return op(p->get_key());
1433 });
1434 }
1435
1436 template <class Operation>
1438 {
1439 return traverse<Operation>(op);
1440 }
1441
1442 template <class Operation>
1443 bool traverse(Operation & op) const
1444 {
1445 return Aleph::traverse(tree.getRoot(), [&op](Node *p)
1446 {
1447 return op(p->get_key());
1448 });
1449 }
1450
1451 template <class Operation>
1452 bool traverse(Operation && op = Operation()) const
1453 {
1454 return traverse<Operation>(op);
1455 }
1456 };
1457
1458
1459# define SETTREE_ITOR(Name, Key, Cmp) \
1460 class Iterator : public DynSetTree<Key, Name, Cmp>::Iterator \
1461 { \
1462 public: \
1463 Iterator() : DynSetTree<Key, Name, Cmp>::Iterator() \
1464 { /* empty */ } \
1465 \
1466 Iterator(DynSetTree<Key, Name, Cmp> & tree) \
1467 : DynSetTree<Key, Name, Cmp>::Iterator(tree) \
1468 { /* empty */ } \
1469 };
1470
1471
1478 template <typename Key, class Compare = Aleph::less<Key>>
1479 class DynSetBinTree : public DynSetTree<Key, BinTree, Compare>
1480 {
1481 public:
1483 using Base::Base;
1484 };
1485
1486
1493 template <typename Key, class Compare = Aleph::less<Key>>
1494 class DynSetAvlTree : public DynSetTree<Key, Avl_Tree, Compare>
1495 {
1496 public:
1498 using Base::Base;
1499 };
1500
1501
1508 template <typename Key, class Compare = Aleph::less<Key>>
1509 class DynSetSplayTree : public DynSetTree<Key, Splay_Tree, Compare>
1510 {
1511 public:
1513 using Base::Base;
1514 };
1515
1516
1530 template <typename Key, class Compare = Aleph::less<Key>>
1531 class DynSetSplayRkTree : public DynSetTree<Key, Splay_Tree_Rk, Compare>
1532 {
1533 public:
1535 using Base::Base;
1537 };
1538
1539
1546 template <typename Key, class Compare = Aleph::less<Key>>
1547 class DynSetRandTree : public DynSetTree<Key, Rand_Tree, Compare>
1548 {
1549 public:
1551 using Base::Base;
1552
1553 class Iterator : public DynSetTree<Key, Rand_Tree, Compare>::Iterator
1554 {
1555 public:
1557 { /* empty */
1558 }
1559
1561 : DynSetTree<Key, Rand_Tree, Compare>::Iterator(tree)
1562 { /* empty */
1563 }
1564 };
1565 };
1566
1567
1574 template <typename Key, class Compare = Aleph::less<Key>>
1575 class DynSetTreap : public DynSetTree<Key, Treap, Compare>
1576 {
1577 public:
1579 using Base::Base;
1580 };
1581
1588 template <typename Key, class Compare = Aleph::less<Key>>
1589 class DynSetTreapRk : public DynSetTree<Key, Treap_Rk, Compare>
1590 {
1591 public:
1593 using Base::Base;
1594 SETTREE_ITOR(Treap_Rk, Key, Compare);
1595 };
1596
1597
1606 template <typename Key, class Compare = Aleph::less<Key>>
1607 class DynSetAvlRkTree : public DynSetTree<Key, Avl_Tree_Rk, Compare>
1608 {
1609 public:
1611 using Base::Base;
1613 };
1614
1615
1622 template <typename Key, class Compare = Aleph::less<Key>>
1623 class DynSetRbTree : public DynSetTree<Key, Rb_Tree, Compare>
1624 {
1625 public:
1627 using Base::Base;
1628 };
1629
1630
1641 template <typename Key, class Compare = Aleph::less<Key>>
1642 class DynSetTdRbTree : public DynSetTree<Key, TdRbTree, Compare>
1643 {
1644 public:
1646 using Base::Base;
1647 };
1648
1649
1658 template <typename Key, class Compare = Aleph::less<Key>>
1659 class DynSetRbRkTree : public DynSetTree<Key, Rb_Tree_Rk, Compare>
1660 {
1661 public:
1663 using Base::Base;
1664 SETTREE_ITOR(Rb_Tree_Rk, Key, Compare);
1665 };
1666
1667
1677 template <typename Key, class Compare = Aleph::less<Key>>
1678 class DynSetTdRbRkTree : public DynSetTree<Key, TdRbTreeRk, Compare>
1679 {
1680 public:
1682 using Base::Base;
1683 SETTREE_ITOR(TdRbTreeRk, Key, Compare);
1684 };
1685
1686
1700 template <typename Key, class Compare = Aleph::less<Key>>
1701 class DynSetHtdRbTree : public DynSetTree<Key, HtdRbTree, Compare>
1702 {
1703 public:
1705 using Base::Base;
1706 SETTREE_ITOR(HtdRbTree, Key, Compare);
1707 };
1708
1709
1723 template <typename Key, class Compare = Aleph::less<Key>>
1724 class DynSetHtdRbRkTree : public DynSetTree<Key, HtdRbTreeRk, Compare>
1725 {
1726 public:
1728 using Base::Base;
1730 };
1731
1732
1733 template <typename T, class Op, class C>
1734 DynSetTree<T> set_unify(const C & c, Op op)
1735 {
1737 for (auto it = c.get_it(); it.has_curr(); it.next_ne())
1738 ret.insert(op(it.get_curr()));
1739 return ret;
1740 }
1741} // end namespace Aleph
1742
1743# endif /* TPL_DYNSETTREE_H */
Memory arena for fast bulk allocations.
Variadic constructor macros for containers.
C++20 concepts hub: comparison, BST policy, and Aleph container concepts.
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error()
Throws std::domain_error unconditionally.
Definition ah-errors.H:559
#define ah_domain_error_if_constexpr(C)
Definition ah-errors.H:562
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Definition ah-errors.H:584
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:527
#define ah_logic_error_if(C)
Throws std::logic_error if condition holds.
Definition ah-errors.H:330
#define ah_bad_alloc_if(C)
Throws std::bad_alloc if condition holds.
Definition ah-errors.H:434
Zip iterators and functional operations for multiple containers.
#define Special_Ctors(Set_Type, Type)
Generates special constructors for containers.
Definition ahDry.H:113
Iterator traits and STL-compatible iterator wrappers.
WeightedDigraph::Node Node
@ KEY
Definition btreepic.C:169
virtual void unalloc(Node *)=0
virtual Node * alloc_rval(typename Node::key_type &&key)=0
virtual Node * alloc_lval(const typename Node::key_type &key)=0
virtual ~AbstractTreeNodeAllocator()=default
Arena allocator for fast bump-pointer allocation.
Definition ah-arena.H:122
size_t allocated_size() const noexcept
Get total bytes currently allocated.
Definition ah-arena.H:395
size_t available_size() const noexcept
Get remaining bytes available.
Definition ah-arena.H:401
~DftTreeNodeAllocator() override=default
Node * alloc_lval(const typename Node::key_type &key) override
Node * alloc_rval(typename Node::key_type &&key) override
void unalloc(Node *p) override
Doubly-linked list (defined in tpl_dynList.H).
Definition htlist.H:1155
Dynamic set implemented using extended AVL binary search trees with rank support of type Avl_Tree_Rk<...
Dynamic set implemented using AVL binary search trees of type Avl_Tree<Key>.
Dynamic set implemented using binary search trees of type BinTree<Key>.
Dynamic set implemented using Hybrid Red-Black trees with rank support of type HtdRbTreeRk<Key>.
Dynamic set implemented using Hybrid Top-Down/Bottom-Up Red-Black trees of type HtdRbTree<Key>.
Iterator(DynSetTree< Key, Rand_Tree, Compare > &tree)
Dynamic set implemented using randomized binary search trees of type Rand_Tree<Key>.
Dynamic set implemented using extended Red-Black binary search trees with rank support of type Rb_Tre...
Dynamic set implemented using Red-Black binary search trees of type Rb_Tree<Key> (bottom-up implement...
Dynamic set implemented using splay trees with rank support of type Splay_Tree_Rk<Key>.
Dynamic set implemented using splay binary search trees of type Splay_Tree<Key>.
Dynamic set implemented using Top-Down Red-Black binary search trees with rank support of type TdRbTr...
Dynamic set implemented using Top-Down Red-Black binary search trees of type TdRbTree<Key>.
Dynamic set implemented using extended treap binary search trees with rank support of type Treap_Rk<K...
Dynamic set implemented using randomized treap binary search trees of type Treap<Key>.
Dynamic set backed by balanced binary search trees with automatic memory management.
Key & access(size_t i)
const Key & get_first() const
size_t height() const
Calculates and returns the height of the binary search tree.
DynSetTree(const Compare &cmp=Compare())
Instantiate a dynamic set.
virtual ~DynSetTree()
Destroyer; all elements are released.
long position(const Key &key) const
Returns the infix (ordered) position of the key.
void free_node(Node *p)
Key * append(const Key &key)
const Key & get_last() const
Key * __insert_dup(Node *q)
bool split_key(const Key &key, DynSetTree &l, DynSetTree &r)
Partitions the binary search tree based on a key.
typename Tree< Key, Compare >::Node Node
Type of binary node used by the binary search tree internal.
std::pair< Key *, bool > contains_or_insert(Key &&key)
const Key & get_item() const
Returns any element of the set.
DynSetTree & join(DynSetTree &t, DynSetTree &&dup=DynSetTree())
This is an overloaded member function, provided for convenience. It differs from the above function o...
Key & operator()(size_t i)
const size_t & size() const
Returns the cardinality of the set.
Key remove_pos(const size_t i)
Removes a key from the dynamic set.
static auto call_select(const T &t, const size_t i, int) -> decltype(t.select(i))
Node * alloc_node(const Key &key)
static auto call_find_position(const T &t, const Key &key, int) -> decltype(t.find_position(key))
static auto call_split_pos(T &t, const size_t pos, T &l, T &r, int) -> decltype(t.split_pos(pos, l, r), void())
Key * append(Key &&key)
static constexpr size_t dim
Key del(const Key &key)
Deletes key and returns a full copy of stored key.
void clear()
Empties the container.
std::pair< long, Key * > find_position(const Key &key) const
Returns the infix (ordinate) position of the key key or whatever It would be your position of belongi...
DynSetTree(const DynSetTree &srcTree)
instantiates a dynamic copy of srcTree
Tree< Key, Compare > tree
const Key & operator[](const Key &key) const
Key * insert(const Key &key)
Inserts a key into the dynamic set.
Key * put(Key &&key)
bool exist(const Key &key) const
Returns true if key belongs to the dynamic set.
void split_key_dup(const Key &key, DynSetTree &l, DynSetTree &r)
Partitions the binary search tree based on a key that may be present in the tree.
bool has(const Key &key) const
void swap(DynSetTree &dset) noexcept(noexcept(tree.swap(dset.tree)) and noexcept(std::swap(num_nodes, dset.num_nodes)) and noexcept(std::swap(arena_allocator, dset.arena_allocator)))
Exchange all elements of this set with dset in constant time (and extremely fast).
void for_each_postorder(Key_Op &key_op) const
Performs a postfix traversal over all keys in the set and invokes operation Op.
Key * put(const Key &key)
static std::pair< long, Node * > call_position(const T &, const Key &,...)
Key & find(const Key &key) const
Returns a modifiable reference to an element within the set.
size_t internal_path_length() const
Calculates and returns the length of the internal path of the tree search binary.
size_t remove(const Key &key)
Removes a key from the dynamic set.
std::unique_ptr< ArenaTreeAllocator< Node > > arena_allocator
bool traverse(Operation &&op=Operation()) const
const Key & min() const
Returns the smallest key contained in the set according to the criterion comparison given.
bool contains(const Key &key) const
Checks if a key exists in the set.
const Key & get() const
Synonym of max.
const Key & get_root() const
DynSetTree(const size_t &arena_sz, const Compare &cmp=Compare())
Instantiate a dynamic set using an arena allocator with dynamic buffer.
Key * search_or_insert(Key &&key)
Key * insert(Key &&key)
Node * alloc_node(Key &&key)
Key * __insert(Node *p)
Key * insert_dup(const Key &key)
void for_each_preorder(Key_Op &&key_op=Key_Op()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
DynSetTree(DynSetTree &&srcTree) noexcept
void split_pos(const size_t pos, DynSetTree &l, DynSetTree &r)
Partitions the binary search tree based on an infix position.
void for_each_postorder(Key_Op &&key_op=Key_Op()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
void for_each_in_preorder(void(*visitFct)(Node *, int, int))
Performs a prefix traversal over all nodes in the tree and invokes the visitFct operation on each vis...
DynSetTree(const char *base_addr, const size_t &sz, const Compare &cmp=Compare())
Instantiate a dynamic set using an arena allocator with external buffer.
static Node * call_select_nc(T &, const size_t,...)
static auto call_position(const T &t, const Key &key, int) -> decltype(t.position(key))
bool traverse(Operation &&op=Operation())
size_t arena_allocated_size() const noexcept
Returns the allocated size from the arena (0 if not using arena)
Key * search(const Key &key) const
Find an element in the set.
Key & select(size_t i)
Returns the ith node in infix position.
Key * __search_or_insert(Node *p)
static auto call_select_nc(T &t, const size_t i, int) -> decltype(t.select(i))
std::pair< Node *, bool > __contains_or_insert(Node *p)
void empty()
remove all elements from the set
bool uses_arena() const noexcept
Returns true if the set is using an arena allocator.
static auto call_remove_pos(T &t, const size_t i, int) -> decltype(t.remove_pos(i))
bool traverse(Operation &op)
Traverse all the set of pairs and for each key executes the operation op.
static Node * call_select(const T &, const size_t,...)
bool traverse(Operation &op) const
void for_each_inorder(Key_Op &&key_op=Key_Op()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
const Key & select(size_t i) const
DynSetTree & operator=(const DynList< Key > &list)
Key * search_or_insert(const Key &key)
Look for the key in the binary search tree or inserts it if it is not found.
static void call_split_pos(T &, const size_t, T &, T &,...)
void for_each_preorder(Key_Op &key_op) const
Performs a prefix traversal over all keys in the set and invokes operation Op.
const Key & max() const
Returns the largest key contained in the set according to the criteria comparison given.
static Node * call_remove_pos(T &, const size_t,...)
void for_each_inorder(Key_Op &key_op) const
Performs an infix traversal over all keys in the set and invokes operation Op.
std::pair< Key *, bool > contains_or_insert(const Key &key)
bool is_empty() const
returns true if the set is empty
static std::pair< long, Node * > call_find_position(const T &, const Key &,...)
Key * insert_dup(Key &&key)
Node * get_root_node() const
size_t arena_available_size() const noexcept
Returns the available size in the arena (0 if not using arena)
Hybrid top-down/bottom-up red-black tree with rank support.
Hybrid top-down/bottom-up red-black tree.
Definition tpl_hRbTree.H:86
Top-down red-black tree with rank (no virtual destructor).
Equality test for containers.
Definition ah-dry.H:1959
Common methods to the Aleph-w ( ) containers.
Definition ah-dry.H:658
and
Conditional mapping of the elements of the container.
Definition ah-dry.H:1137
Common sequential searching methods on containers.
Definition ah-dry.H:200
Node for QuadTree spatial data structure.
Definition quadnode.H:94
QuadTree - Hierarchical spatial index for 2D points.
Definition quadtree.H:126
Mixin that adds STL begin()/end() and cbegin()/cend() to Aleph containers.
__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
size_t compute_cardinality_rec(Node *root) noexcept
Count the number of nodes of a binary tree.
DynSetTree & join(DynSetTree &t, DynSetTree &dup)
Union of two binary search trees.
int preOrderRec(Node *root, void(*visitFct)(Node *, int, int))
Traverse recursively in preorder a binary tree.
Node * find_min(Node *root) noexcept
Return the minimum key contained in a binary search tree.
Node * copyRec(Node *root)
Copy recursively a tree.
bool check_bst(Node *p, const Compare &cmp=Compare())
Return true if p is a binary search tree.
DynSetTree & join_dup(DynSetTree &t)
Union of two binary search trees.
size_t internal_path_length(Node *p) noexcept
Compute the internal path length.
void destroyRec(Node *&root) noexcept
Free recursively all the memory occupied by the tree root
size_t computeHeightRec(Node *root) noexcept
Compute recursively the height of root
Node * find_max(Node *root) noexcept
Return the maximum key contained in a binary search tree.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
bool traverse(Node *root, Op op)
DynSetTree< T > set_unify(const C &c, Op op)
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:105
void callKeyDestructorsRec(Node *&root) noexcept
Traverses recursively the tree and calls key's destructors.
STL namespace.
Node * alloc_rval(typename Node::key_type &&key) override
ArenaTreeAllocator(const size_t &sz=1024 *1024)
size_t available_size() const noexcept
ArenaTreeAllocator(const char *base_addr, const size_t &sz)
size_t allocated_size() const noexcept
Node * alloc_lval(const typename Node::key_type &key) override
void unalloc(Node *p) override
Ranked AVL tree with nodes without a virtual destructor.
Definition tpl_avlRk.H:1469
AVL binary search tree with nodes without a virtual destructor.
Definition tpl_avl.H:743
bool operator()(const Container &c1, const Container &c2) const
static constexpr bool has_find_position
const Key & get_curr_ne() const noexcept
typename Tree_Type::Iterator Base
Iterator() noexcept=default
Default constructor creates an "end" iterator.
const Key & get_curr() const
Randomized binary search tree.
Red-Black binary search tree with nodes without virtual destructor and with subtree counters for sele...
Definition tpl_rbRk.H:1551
Extended treap (a special type of randomized binary search tree) which manages selection and splittin...
Generic list of items stored in a container.
Definition ah-dry.H:1846
static int * k
gsl_rng * r
AVL tree with rank (order statistics).
AVL tree implementation (height-balanced BST).
Utility functions for binary tree operations.
Extended binary node with subtree count.
Generic unbalanced binary search tree.
#define SETTREE_ITOR(Name, Key, Cmp)
Hybrid top-down/bottom-up red-black tree with rank support.
Hybrid top-down/bottom-up red-black tree implementation.
Randomized binary search tree.
Red-Black tree with rank (order statistics).
Red-Black tree implementation (bottom-up balancing).
Top-down splay tree with rank support.
Top-down splay tree implementation (without rank support).
Top-down Red-Black tree with rank support.
Top-down Red-Black tree implementation.
Treap with rank (order statistics).
Treap: randomized BST combining tree and heap properties.
DynList< int > l