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 // Test for const select (RB, AVL, etc.)
289 template <typename U>
290 static auto test_select_const(int)
291 -> decltype(std::declval<const U &>().select(std::declval<size_t>()),
292 std::true_type());
293
294 template <typename>
295 static std::false_type test_select_const(...);
296
297 // Test for non-const select (Splay tree - mutates on access)
298 template <typename U>
299 static auto test_select_nonconst(int)
300 -> decltype(std::declval<U &>().select(std::declval<size_t>()),
301 std::true_type());
302
303 template <typename>
304 static std::false_type test_select_nonconst(...);
305
306 template <typename U>
307 static auto test_remove_pos(int)
308 -> decltype(std::declval<U &>().remove_pos(std::declval<size_t>()),
309 std::true_type());
310
311 template <typename>
312 static std::false_type test_remove_pos(...);
313
314 template <typename U>
315 static auto test_split_pos(int)
316 -> decltype(std::declval<U &>().split_pos(std::declval<size_t>(),
317 std::declval<U &>(),
318 std::declval<U &>()),
319 std::true_type());
320
321 template <typename>
322 static std::false_type test_split_pos(...);
323
324 // Test for const position
325 template <typename U>
326 static auto test_position_const(int)
327 -> decltype(std::declval<const U &>().position(std::declval<const Key &>()),
328 std::true_type());
329
330 template <typename>
331 static std::false_type test_position_const(...);
332
333 // Test for non-const position (Splay tree)
334 template <typename U>
335 static auto test_position_nonconst(int)
336 -> decltype(std::declval<U &>().position(std::declval<const Key &>()),
337 std::true_type());
338
339 template <typename>
340 static std::false_type test_position_nonconst(...);
341
342 // Test for const find_position
343 template <typename U>
345 -> decltype(std::declval<const U &>().find_position(std::declval<const Key &>()),
346 std::true_type());
347
348 template <typename>
349 static std::false_type test_find_position_const(...);
350
351 // Test for non-const find_position (Splay tree)
352 template <typename U>
354 -> decltype(std::declval<U &>().find_position(std::declval<const Key &>()),
355 std::true_type());
356
357 template <typename>
358 static std::false_type test_find_position_nonconst(...);
359
360 static constexpr bool has_select =
361 std::is_same_v<decltype(test_select_const<T>(0)), std::true_type> or
362 std::is_same_v<decltype(test_select_nonconst<T>(0)), std::true_type>;
363 static constexpr bool has_remove_pos =
364 std::is_same_v<decltype(test_remove_pos<T>(0)), std::true_type>;
365 static constexpr bool has_split_pos =
366 std::is_same_v<decltype(test_split_pos<T>(0)), std::true_type>;
367 static constexpr bool has_position =
368 std::is_same_v<decltype(test_position_const<T>(0)), std::true_type> or
369 std::is_same_v<decltype(test_position_nonconst<T>(0)), std::true_type>;
370 static constexpr bool has_find_position =
371 std::is_same_v<decltype(test_find_position_const<T>(0)), std::true_type> or
372 std::is_same_v<decltype(test_find_position_nonconst<T>(0)), std::true_type>;
373 };
374
375 // call_select for const trees (RB, AVL, etc.)
376 template <typename T>
377 static auto call_select(const T & t, const size_t i, int)
378 -> decltype(t.select(i))
379 {
380 return t.select(i);
381 }
382
383 // call_select for non-const trees (Splay - mutates on access)
384 template <typename T>
385 static auto call_select_nc(T & t, const size_t i, int)
386 -> decltype(t.select(i))
387 {
388 return t.select(i);
389 }
390
391 template <typename T>
392 static Node * call_select(const T &, const size_t, ...)
393 {
394 ah_domain_error() << "select is not supported by underlying tree";
395 return nullptr;
396 }
397
398 template <typename T>
399 static Node * call_select_nc(T &, const size_t, ...)
400 {
401 ah_domain_error() << "select is not supported by underlying tree";
402 return nullptr;
403 }
404
405 template <typename T>
406 static auto call_remove_pos(T & t, const size_t i, int)
407 -> decltype(t.remove_pos(i))
408 {
409 return t.remove_pos(i);
410 }
411
412 template <typename T>
413 static Node * call_remove_pos(T &, const size_t, ...)
414 {
415 ah_domain_error() << "remove_pos is not supported by underlying tree";
416 return nullptr;
417 }
418
419 template <typename T>
420 static auto call_split_pos(T & t, const size_t pos, T & l, T & r, int)
421 -> decltype(t.split_pos(pos, l, r), void())
422 {
423 t.split_pos(pos, l, r);
424 }
425
426 template <typename T>
427 static void call_split_pos(T &, const size_t, T &, T &, ...)
428 {
429 ah_domain_error() << "split_pos is not supported by underlying tree";
430 }
431
432 template <typename T>
433 static auto call_position(const T & t, const Key & key, int)
434 -> decltype(t.position(key))
435 {
436 return t.position(key);
437 }
438
439 template <typename T>
440 static std::pair<long, Node *> call_position(const T &, const Key &, ...)
441 {
442 ah_domain_error() << "position is not supported by underlying tree";
443 return std::pair<long, Node *>(0, nullptr);
444 }
445
446 template <typename T>
447 static auto call_find_position(const T & t, const Key & key, int)
448 -> decltype(t.find_position(key))
449 {
450 return t.find_position(key);
451 }
452
453 template <typename T>
454 static std::pair<long, Node *> call_find_position(const T &, const Key &, ...)
455 {
456 ah_domain_error() << "find_position is not supported by underlying tree";
457 return std::pair<long, Node *>(0, nullptr);
458 }
459
460 static constexpr size_t dim = 13;
461
463 size_t num_nodes;
464 std::unique_ptr<ArenaTreeAllocator<Node>> arena_allocator;
465
466 Node * alloc_node(const Key & key)
467 {
468 if (arena_allocator)
469 return arena_allocator->alloc_lval(key);
470 return new Node(key);
471 }
472
473 Node * alloc_node(Key && key)
474 {
475 if (arena_allocator)
476 return arena_allocator->alloc_rval(std::forward<Key>(key));
477 return new Node(std::forward<Key>(key));
478 }
479
481 {
482 if (arena_allocator)
483 arena_allocator->unalloc(p);
484 else
485 delete p;
486 }
487
488 public:
490
491 typedef Key Item_Type;
492
493 typedef Key Key_Type;
494
501 noexcept(noexcept(tree.swap(dset.tree)) and
502 noexcept(std::swap(num_nodes, dset.num_nodes)) and
503 noexcept(std::swap(arena_allocator, dset.arena_allocator)))
504 {
505 tree.swap(dset.tree);
506 std::swap(num_nodes, dset.num_nodes);
507 std::swap(arena_allocator, dset.arena_allocator);
508 }
509
511 DynSetTree(const Compare & cmp = Compare())
512 : tree(cmp), num_nodes(0)
513 {
514 // empty
515 }
516
518 DynSetTree(const char *base_addr, const size_t & sz,
519 const Compare & cmp = Compare())
520 : tree(cmp), num_nodes(0),
522 {
523 // empty
524 }
525
527 explicit DynSetTree(const size_t & arena_sz,
528 const Compare & cmp = Compare())
529 : tree(cmp), num_nodes(0),
531 {
532 // empty
533 }
534
537 : tree(srcTree.tree.get_compare()), num_nodes(srcTree.num_nodes)
538 {
539 Node *srcRoot = srcTree.tree.getRoot();
540 try
541 {
542 tree.getRoot() = copyRec(srcRoot);
543 }
544 catch (...)
545 {
546 num_nodes = 0;
547 throw;
548 }
549 }
550
552
558
560 void empty()
561 {
562 if (arena_allocator)
563 {
564 // For arena allocation, just call destructors on keys
565 // (arena handles memory deallocation)
566 callKeyDestructorsRec(tree.getRoot());
567
568 // Reset tree
569 tree.getRoot() = Node::NullPtr;
570 num_nodes = 0;
571 return;
572 }
573
574 destroyRec(tree.getRoot());
575 tree.getRoot() = Node::NullPtr;
576 num_nodes = 0;
577 }
578
584 void clear() { empty(); }
585
587 {
588 return *this = DynSetTree(list);
589 }
590
593 {
594 if (this == &srcTree)
595 return *this;
596
597 Node *src_root = srcTree.tree.getRoot();
598
599 empty();
600
601 tree.getRoot() = copyRec(src_root);
602 num_nodes = srcTree.num_nodes;
603
604 return *this;
605 }
606
609 noexcept
610 {
611 if (this == &srcTree)
612 return *this;
613
614 empty();
615 swap(srcTree);
616 return *this;
617 }
618
620 virtual ~DynSetTree()
621 {
622 empty();
623 }
624
625 private:
626 Key * __insert(Node *p)
627 {
628 Node *q = nullptr;
629 try
630 {
631 q = tree.search_or_insert(p);
632 }
633 catch (...)
634 {
635 free_node(p);
636 throw;
637 }
638
639 if (q != p)
640 return nullptr;
641
642 ++num_nodes;
643
644 return &p->get_key();
645 }
646
647 public:
656 Key * insert(const Key & key)
657 {
658 Node *p = alloc_node(key);
659 Key *key_p = __insert(p);
660 if (key_p == nullptr) // was there insertion?
661 { // No (KEY(p) is already in the tree) ==> free p and return nullptr
662 free_node(p);
663 return nullptr;
664 }
665
666 return key_p;
667 }
668
669 Key * insert(Key && key)
670 {
671 Node *p = alloc_node(std::forward<Key>(key));
672 Key *key_p = __insert(p);
673 if (key_p == nullptr) // was there insertion?
674 {
675 free_node(p);
676 return nullptr;
677 }
678
679 return key_p;
680 }
681
682 Key * append(const Key & key)
683 {
684 return insert(key);
685 }
686
687 Key * append(Key && key)
688 {
689 return insert(std::forward<Key>(key));
690 }
691
692 private:
694 {
695 Node *q = nullptr;
696 try
697 {
698 q = tree.search_or_insert(p);
699 }
700 catch (...)
701 {
702 free_node(p);
703 throw;
704 }
705 if (q != p) // was there an insertion?
706 free_node(p); // No (KEY(p) is already in the tree) ==> free
707 // allocated node
708 else
709 ++num_nodes;
710
711 return &q->get_key();
712 }
713
714 std::pair<Node *, bool> __contains_or_insert(Node *p)
715 {
716 Node *q = nullptr;
717 try
718 {
719 q = tree.search_or_insert(p);
720 }
721 catch (...)
722 {
723 free_node(p);
724 throw;
725 }
726 if (q != p)
727 { // KEY(p) is already inside the tree
728 free_node(p);
729 return std::pair<Node *, bool>(q, true);
730 }
731 ++num_nodes;
732 return std::pair<Node *, bool>(p, false);
733 }
734
735 public:
748 Key * search_or_insert(const Key & key)
749 {
750 return __search_or_insert(alloc_node(key));
751 }
752
753 Key * search_or_insert(Key && key)
754 {
755 return
756 __search_or_insert(alloc_node(std::forward<Key>(key)));
757 }
758
759 /* Look for the key <code>key</code> in the binary search tree and
760 eventually inserts it if it is not found.
761
762 <code>contains_or_insert(key)</code> searches the tree for the key
763 <code>key</code>. If the key is already found, then it is returned
764 true. Otherwise, the key is inserted and false is returned.
765
766 @param[in] key to find or insert
767 @return a std::pair whose first field is a pointer to the found or
768 inserted key, and the second field is a boolean whose value is
769 `false` if the key was inserted; `true` otherwise, that is if the
770 key is already present in the tree.
771 */
772 std::pair<Key *, bool> contains_or_insert(const Key & key)
773 {
774 auto p = __contains_or_insert(alloc_node(key));
775 return std::pair<Key *, bool>(&p.first->get_key(), p.second);
776 }
777
778 std::pair<Key *, bool> contains_or_insert(Key && key)
779 {
780 auto p = __contains_or_insert(alloc_node(std::forward<Key>(key)));
781 return std::pair<Key *, bool>(&p.first->get_key(), p.second);
782 }
783
784 private:
786 {
787 try
788 {
789 Node *p = tree.insert_dup(q);
790 ++num_nodes;
791 return &p->get_key();
792 }
793 catch (...)
794 {
795 free_node(q);
796 throw;
797 }
798 }
799
800 public:
801 Key * insert_dup(const Key & key)
802 {
803 return __insert_dup(alloc_node(key));
804 }
805
806 Key * insert_dup(Key && key)
807 {
808 return __insert_dup(alloc_node(std::forward<Key>(key)));
809 }
810
811 Key * put(const Key & key)
812 {
813 return insert(key);
814 }
815
816 Key * put(Key && key)
817 {
818 return insert(std::forward<Key>(key));
819 }
820
828 size_t remove(const Key & key)
829 {
830 Node *p = static_cast<Node *>(tree.remove(key));
831
832 if (p == nullptr)
833 return num_nodes;
834
835 free_node(p);
836
837 return --num_nodes;
838 }
839
850 Key del(const Key & key)
851 {
852 Node *p = static_cast<Node *>(tree.remove(key));
853
854 ah_domain_error_if(p == nullptr)
855 << "DynSetTree::del key is not found in the tree";
856
857 auto ret_val = p->get_key();
858
859 free_node(p);
860
861 --num_nodes;
862
863 return ret_val;
864 }
865
870 Key remove_pos(const size_t i)
871 {
873 << "remove_pos is not supported by underlying tree";
874
876 << "remove_pos index out of range";
877
878 Node *p = static_cast<Node *>(call_remove_pos(tree, i, 0));
879 ah_logic_error_if(p == nullptr)
880 << "remove_pos returned nullptr";
881 const Key ret_val = KEY(p);
882
883 free_node(p);
884
885 --num_nodes;
886
887 return ret_val;
888 }
889
891 bool exist(const Key & key) const
892 {
893 return search(key) != nullptr;
894 }
895
896 bool has(const Key & key) const
897 {
898 return exist(key);
899 }
900
907 bool contains(const Key & key) const
908 {
909 return exist(key);
910 }
911
926 Key &find(const Key & key) const
927 {
928 Node *node = static_cast<Node *>(tree.search(key));
929
930 ah_domain_error_if(node == nullptr)
931 << "key not found";
932
933 return node->get_key();
934 }
935
950 std::pair<long, Key *> find_position(const Key & key) const
951 {
953 << "find_position is not supported by underlying tree";
954
955 if (num_nodes == 0)
956 return std::pair<long, Key *>(0, nullptr);
957
958 auto p = call_find_position(tree, key, 0);
959 if (p.second == nullptr)
960 return std::pair<long, Key *>(static_cast<long>(p.first), nullptr);
961
962 return std::pair<long, Key *>(static_cast<long>(p.first),
963 &p.second->get_key());
964 }
965
980 Key * search(const Key & key) const
981 {
982 Node *node = static_cast<Node *>(tree.search(key));
983
984 if (node == nullptr)
985 return nullptr;
986
987 return &(node->get_key());
988 }
989
992 const Key &min() const
993 {
995 << "set is empty";
996
997 return find_min(tree.getRoot())->get_key();
998 }
999
1001 const Key &get_first() const { return min(); }
1002
1005 const Key &max() const
1006 {
1008 << "set is empty";
1009
1010 return find_max(tree.getRoot())->get_key();
1011 }
1012
1014 const Key &get_last() const { return max(); }
1015
1017 const Key &get() const { return max(); }
1018
1020 const size_t &size() const { return num_nodes; }
1021
1023 bool is_empty() const { return num_nodes == 0; }
1024
1027 {
1028 return arena_allocator != nullptr;
1029 }
1030
1033 {
1034 if (arena_allocator)
1035 return arena_allocator->allocated_size();
1036 return 0;
1037 }
1038
1041 {
1042 if (arena_allocator)
1043 return arena_allocator->available_size();
1044 return 0;
1045 }
1046
1050 {
1051 return Aleph::internal_path_length(tree.getRoot());
1052 }
1053
1054 Node * get_root_node() const { return tree.getRoot(); }
1055
1056 const Key &get_root() const
1057 {
1059 << "Tree is empty";
1060 return KEY(tree.getRoot());
1061 }
1062
1064 const Key &get_item() const { return get_root(); }
1065
1067 size_t height() const { return computeHeightRec(tree.getRoot()); }
1068
1071 template <class Op>
1072 void for_each_in_preorder(void (*visitFct)(Node *, int, int))
1073 {
1074 Node *root = static_cast<Node *>(tree.getRoot());
1076 }
1077
1090 long position(const Key & key) const
1091 {
1093 << "position is not supported by underlying tree";
1094
1095 auto p = call_position(tree, key, 0);
1096 return static_cast<long>(p.first);
1097 }
1098
1104 Key &select(size_t i)
1105 {
1107 << "select is not supported by underlying tree";
1108
1110 << "select index out of range";
1111
1112 // Try non-const first (for Splay trees), then const
1113 Node *p = call_select_nc(tree, i, 0);
1114 ah_logic_error_if(p == nullptr)
1115 << "select returned nullptr";
1116 return p->get_key();
1117 }
1118
1119 const Key &select(size_t i) const
1120 {
1122 << "select is not supported by underlying tree";
1123
1125 << "select index out of range";
1126
1127 // For const version, only const select works (not for Splay trees)
1128 Node *p = call_select(tree, i, 0);
1129 ah_logic_error_if(p == nullptr)
1130 << "select returned nullptr";
1131 return p->get_key();
1132 }
1133
1134 Key &operator ()(size_t i)
1135 {
1136 return select(i);
1137 }
1138
1139 const Key &operator [](const Key & key) const
1140 {
1141 return find(key);
1142 }
1143
1144 const Key &operator [](const Key & key)
1145 {
1146 return *search_or_insert(key);
1147 }
1148
1149 Key &access(size_t i)
1150 {
1151 return select(i);
1152 }
1153
1154 bool verify() const
1155 {
1156 return tree.verify() and check_bst(tree.getRoot());
1157 }
1158
1159 private:
1160 template <class Key_Op>
1161 struct Node_Op
1162 {
1164
1166 { /* empty */
1167 }
1168
1170 {
1171 /* empty */
1172 }
1173
1175 {
1176 assert(root != nullptr);
1177 key_op(KEY(root));
1178 }
1179 };
1180
1181 public:
1206 template <class Key_Op>
1207 void for_each_preorder(Key_Op & key_op) const
1208 {
1209 Node *root = static_cast<Node *>(tree.getRoot());
1210
1211 Node_Op<Key_Op> node_op(const_cast<Key_Op &>(key_op));
1212
1214 }
1215
1223 template <class Key_Op>
1224 void for_each_preorder(Key_Op && key_op = Key_Op()) const
1225 {
1227 }
1228
1253 template <class Key_Op>
1254 void for_each_inorder(Key_Op & key_op) const
1255 {
1256 Node *root = static_cast<Node *>(tree.getRoot());
1257
1258 Node_Op<Key_Op> node_op(const_cast<Key_Op &>(key_op));
1259
1261 }
1262
1270 template <class Key_Op>
1271 void for_each_inorder(Key_Op && key_op = Key_Op()) const
1272 {
1274 }
1275
1300 template <class Key_Op>
1301 void for_each_postorder(Key_Op & key_op) const
1302 {
1303 Node *root = static_cast<Node *>(tree.getRoot());
1304
1305 Node_Op<Key_Op> node_op(const_cast<Key_Op &>(key_op));
1306
1308 }
1309
1317 template <class Key_Op>
1318 void for_each_postorder(Key_Op && key_op = Key_Op()) const
1319 {
1321 }
1322
1336 {
1337 tree.join(t.tree, dup.tree);
1338 t.tree.getRoot() = Node::NullPtr;
1339 t.num_nodes = 0;
1341 dup.num_nodes = compute_cardinality_rec(dup.tree.getRoot());
1342 return *this;
1343 }
1344
1355 {
1356 return join(t, dup);
1357 }
1358
1372 {
1373 tree.join_dup(t.tree);
1374 t.num_nodes = 0;
1375 t.tree.getRoot() = Node::NullPtr;
1377 return *this;
1378 }
1379
1395 bool split_key(const Key & key, DynSetTree & l, DynSetTree & r)
1396 {
1397 if (not tree.split_key(key, l.tree, r.tree))
1398 return false;
1399
1400 tree.getRoot() = Node::NullPtr;
1401 num_nodes = 0;
1402 l.num_nodes = compute_cardinality_rec(l.tree.getRoot());
1403 r.num_nodes = compute_cardinality_rec(r.tree.getRoot());
1404
1405 return true;
1406 }
1407
1420 void split_pos(const size_t pos, DynSetTree & l, DynSetTree & r)
1421 {
1423 << "split_pos is not supported by underlying tree";
1424
1426 << "split_pos position out of range";
1427
1428 // Underlying split_pos splits at [0, pos) and [pos, N)
1429 // But we want [0, pos] and (pos, N), so we split at pos+1
1430 call_split_pos(tree, pos + 1, l.tree, r.tree, 0);
1431 tree.getRoot() = Node::NullPtr;
1432 num_nodes = 0;
1433 l.num_nodes = compute_cardinality_rec(l.tree.getRoot());
1434 r.num_nodes = compute_cardinality_rec(r.tree.getRoot());
1435 }
1436
1449 void split_key_dup(const Key & key, DynSetTree & l, DynSetTree & r)
1450 {
1451 tree.split_key_dup(key, l.tree, r.tree);
1452 tree.getRoot() = Node::NullPtr;
1453 num_nodes = 0;
1454 l.num_nodes = compute_cardinality_rec(l.tree.getRoot());
1455 r.num_nodes = compute_cardinality_rec(r.tree.getRoot());
1456 }
1457
1458 struct Iterator : public Tree_Type::Iterator
1459 {
1460 using Base = typename Tree_Type::Iterator;
1461
1463
1466
1468 { /* empty */
1469 }
1470
1472 {
1473 return Base::get_curr_ne()->get_key();
1474 }
1475
1476 Key &get_curr_ne() noexcept { return Base::get_curr_ne()->get_key(); }
1477
1478 const Key &get_curr() const { return Base::get_curr()->get_key(); }
1479
1480 Key &get_curr() { return Base::get_curr()->get_key(); }
1481 };
1482
1497 template <class Operation>
1499 {
1500 return Aleph::traverse(tree.getRoot(), [&op](Node *p)
1501 {
1502 return op(p->get_key());
1503 });
1504 }
1505
1506 template <class Operation>
1508 {
1509 return traverse<Operation>(op);
1510 }
1511
1512 template <class Operation>
1513 bool traverse(Operation & op) const
1514 {
1515 return Aleph::traverse(tree.getRoot(), [&op](Node *p)
1516 {
1517 return op(p->get_key());
1518 });
1519 }
1520
1521 template <class Operation>
1522 bool traverse(Operation && op = Operation()) const
1523 {
1524 return traverse<Operation>(op);
1525 }
1526 };
1527
1528
1529# define SETTREE_ITOR(Name, Key, Cmp) \
1530 class Iterator : public DynSetTree<Key, Name, Cmp>::Iterator \
1531 { \
1532 public: \
1533 Iterator() : DynSetTree<Key, Name, Cmp>::Iterator() \
1534 { /* empty */ } \
1535 \
1536 Iterator(DynSetTree<Key, Name, Cmp> & tree) \
1537 : DynSetTree<Key, Name, Cmp>::Iterator(tree) \
1538 { /* empty */ } \
1539 };
1540
1541
1548 template <typename Key, class Compare = Aleph::less<Key>>
1549 class DynSetBinTree : public DynSetTree<Key, BinTree, Compare>
1550 {
1551 public:
1553 using Base::Base;
1554 };
1555
1556
1563 template <typename Key, class Compare = Aleph::less<Key>>
1564 class DynSetAvlTree : public DynSetTree<Key, Avl_Tree, Compare>
1565 {
1566 public:
1568 using Base::Base;
1569 };
1570
1571
1578 template <typename Key, class Compare = Aleph::less<Key>>
1579 class DynSetSplayTree : public DynSetTree<Key, Splay_Tree, Compare>
1580 {
1581 public:
1583 using Base::Base;
1584 };
1585
1586
1600 template <typename Key, class Compare = Aleph::less<Key>>
1601 class DynSetSplayRkTree : public DynSetTree<Key, Splay_Tree_Rk, Compare>
1602 {
1603 public:
1605 using Base::Base;
1607 };
1608
1609
1616 template <typename Key, class Compare = Aleph::less<Key>>
1617 class DynSetRandTree : public DynSetTree<Key, Rand_Tree, Compare>
1618 {
1619 public:
1621 using Base::Base;
1622
1623 class Iterator : public DynSetTree<Key, Rand_Tree, Compare>::Iterator
1624 {
1625 public:
1627 { /* empty */
1628 }
1629
1631 : DynSetTree<Key, Rand_Tree, Compare>::Iterator(tree)
1632 { /* empty */
1633 }
1634 };
1635 };
1636
1637
1644 template <typename Key, class Compare = Aleph::less<Key>>
1645 class DynSetTreap : public DynSetTree<Key, Treap, Compare>
1646 {
1647 public:
1649 using Base::Base;
1650 };
1651
1658 template <typename Key, class Compare = Aleph::less<Key>>
1659 class DynSetTreapRk : public DynSetTree<Key, Treap_Rk, Compare>
1660 {
1661 public:
1663 using Base::Base;
1664 SETTREE_ITOR(Treap_Rk, Key, Compare);
1665 };
1666
1667
1676 template <typename Key, class Compare = Aleph::less<Key>>
1677 class DynSetAvlRkTree : public DynSetTree<Key, Avl_Tree_Rk, Compare>
1678 {
1679 public:
1681 using Base::Base;
1683 };
1684
1685
1692 template <typename Key, class Compare = Aleph::less<Key>>
1693 class DynSetRbTree : public DynSetTree<Key, Rb_Tree, Compare>
1694 {
1695 public:
1697 using Base::Base;
1698 };
1699
1700
1711 template <typename Key, class Compare = Aleph::less<Key>>
1712 class DynSetTdRbTree : public DynSetTree<Key, TdRbTree, Compare>
1713 {
1714 public:
1716 using Base::Base;
1717 };
1718
1719
1728 template <typename Key, class Compare = Aleph::less<Key>>
1729 class DynSetRbRkTree : public DynSetTree<Key, Rb_Tree_Rk, Compare>
1730 {
1731 public:
1733 using Base::Base;
1734 SETTREE_ITOR(Rb_Tree_Rk, Key, Compare);
1735 };
1736
1737
1747 template <typename Key, class Compare = Aleph::less<Key>>
1748 class DynSetTdRbRkTree : public DynSetTree<Key, TdRbTreeRk, Compare>
1749 {
1750 public:
1752 using Base::Base;
1753 SETTREE_ITOR(TdRbTreeRk, Key, Compare);
1754 };
1755
1756
1770 template <typename Key, class Compare = Aleph::less<Key>>
1771 class DynSetHtdRbTree : public DynSetTree<Key, HtdRbTree, Compare>
1772 {
1773 public:
1775 using Base::Base;
1776 SETTREE_ITOR(HtdRbTree, Key, Compare);
1777 };
1778
1779
1793 template <typename Key, class Compare = Aleph::less<Key>>
1794 class DynSetHtdRbRkTree : public DynSetTree<Key, HtdRbTreeRk, Compare>
1795 {
1796 public:
1798 using Base::Base;
1800 };
1801
1802
1803 template <typename T, class Op, class C>
1804 DynSetTree<T> set_unify(const C & c, Op op)
1805 {
1807 for (auto it = c.get_it(); it.has_curr(); it.next_ne())
1808 ret.insert(op(it.get_curr()));
1809 return ret;
1810 }
1811} // end namespace Aleph
1812
1813# endif /* TPL_DYNSETTREE_H */
Memory arena for fast bulk allocations.
Variadic constructor macros for containers.
C++20 concepts for constraining comparison functors.
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error()
Throws std::domain_error unconditionally.
Definition ah-errors.H:554
#define ah_domain_error_if_constexpr(C)
Definition ah-errors.H:557
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Definition ah-errors.H:579
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
#define ah_logic_error_if(C)
Throws std::logic_error if condition holds.
Definition ah-errors.H:325
#define ah_bad_alloc_if(C)
Throws std::bad_alloc if condition holds.
Definition ah-errors.H:429
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
Dynamic singly linked list with functional programming support.
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:1826
Common methods to the Aleph-w ( ) containers.
Definition ah-dry.H:642
Common sequential searching methods on containers.
Definition ah-dry.H:196
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:4060
int cmp(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4118
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
and
Check uniqueness with explicit hash + equality functors.
bool traverse(Node *root, Op op)
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
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
AVL binary search tree with nodes without virtual destructor and with subtree counters for select/pos...
Definition tpl_avlRk.H:1445
AVL binary search tree with nodes without virtual destructor.
Definition tpl_avl.H:737
bool operator()(const Container &c1, const Container &c2) const
static auto test_remove_pos(int) -> decltype(std::declval< U & >().remove_pos(std::declval< size_t >()), std::true_type())
static std::false_type test_remove_pos(...)
static auto test_position_const(int) -> decltype(std::declval< const U & >().position(std::declval< const Key & >()), std::true_type())
static auto test_find_position_const(int) -> decltype(std::declval< const U & >().find_position(std::declval< const Key & >()), std::true_type())
static auto test_split_pos(int) -> decltype(std::declval< U & >().split_pos(std::declval< size_t >(), std::declval< U & >(), std::declval< U & >()), std::true_type())
static constexpr bool has_find_position
static std::false_type test_select_const(...)
static std::false_type test_find_position_nonconst(...)
static auto test_find_position_nonconst(int) -> decltype(std::declval< U & >().find_position(std::declval< const Key & >()), std::true_type())
static std::false_type test_find_position_const(...)
static auto test_select_nonconst(int) -> decltype(std::declval< U & >().select(std::declval< size_t >()), std::true_type())
static std::false_type test_position_const(...)
static std::false_type test_split_pos(...)
static auto test_position_nonconst(int) -> decltype(std::declval< U & >().position(std::declval< const Key & >()), std::true_type())
static auto test_select_const(int) -> decltype(std::declval< const U & >().select(std::declval< size_t >()), std::true_type())
static std::false_type test_position_nonconst(...)
static std::false_type test_select_nonconst(...)
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:1714
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