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
77using namespace Aleph;
78
79namespace Aleph
80{
81 template <typename Node>
83 {
84 public:
86
87 virtual Node * alloc_lval(const typename Node::key_type & key) = 0;
88
89 virtual Node * alloc_rval(typename Node::key_type && key) = 0;
90
91 virtual void unalloc(Node *) = 0;
92
93 virtual ~AbstractTreeNodeAllocator() = default;
94 };
95
96 template <typename Node>
98 {
99 public:
100 Node * alloc_lval(const typename Node::key_type & key) override
101 {
102 return new Node(key);
103 }
104
105 Node * alloc_rval(typename Node::key_type && key) override
106 {
107 return new Node(std::forward<typename Node::key_type>(key));
108 }
109
110 void unalloc(Node *p) override
111 {
112 delete p;
113 }
114
115 ~DftTreeNodeAllocator() override = default;
116 };
117
118 template <typename Node>
120 {
122
123 ArenaTreeAllocator(const size_t & sz = 1024 * 1024)
124 : arena(sz)
125 {
126 // empty
127 }
128
129 ArenaTreeAllocator(const char *base_addr, const size_t & sz)
130 : arena(base_addr, sz)
131 {
132 // empty
133 }
134
135 Node * alloc_lval(const typename Node::key_type & key) override
136 {
137 Node *ptr = allocate<Node>(arena, key);
138 ah_bad_alloc_if(ptr == nullptr);
139 return ptr;
140 }
141
142 Node * alloc_rval(typename Node::key_type && key) override
143 {
144 Node *ptr =
145 allocate<Node>(arena, std::forward<typename Node::key_type>(key));
146 ah_bad_alloc_if(ptr == nullptr);
147 return ptr;
148 }
149
150 void unalloc(Node *p) override
151 {
153 }
154
156 {
157 return arena.allocated_size();
158 }
159
161 {
162 return arena.available_size();
163 }
164
166 };
167
168 template <typename Container, typename T>
170 {
171 bool operator ()(const Container & c1, const Container & c2) const
172 {
173 return std::lexicographical_compare(c1.begin(), c1.end(), c2.begin(), c2.end(),
174 [](const T & item1, const T & item2)
175 {
176 return item1 < item2;
177 });
178 }
179 };
180
264 template <typename Key,
265 template <typename, class> class Tree = Avl_Tree,
266 class Compare = Aleph::less<Key>>
268 : public LocateFunctions<DynSetTree<Key, Tree, Compare>, Key>,
269 public FunctionalMethods<DynSetTree<Key, Tree, Compare>, Key>,
270 public GenericKeys<DynSetTree<Key, Tree, Compare>, Key>,
271 public EqualToMethod<DynSetTree<Key, Tree, Compare>>,
272 public StlAlephIterator<DynSetTree<Key, Tree, Compare>>
273 {
274 public:
278
280
281 private:
282 template <typename T>
284 {
285 // Test for const select (RB, AVL, etc.)
286 template <typename U>
287 static auto test_select_const(int)
288 -> decltype(std::declval<const U &>().select(std::declval<size_t>()),
289 std::true_type());
290
291 template <typename>
292 static std::false_type test_select_const(...);
293
294 // Test for non-const select (Splay tree - mutates on access)
295 template <typename U>
296 static auto test_select_nonconst(int)
297 -> decltype(std::declval<U &>().select(std::declval<size_t>()),
298 std::true_type());
299
300 template <typename>
301 static std::false_type test_select_nonconst(...);
302
303 template <typename U>
304 static auto test_remove_pos(int)
305 -> decltype(std::declval<U &>().remove_pos(std::declval<size_t>()),
306 std::true_type());
307
308 template <typename>
309 static std::false_type test_remove_pos(...);
310
311 template <typename U>
312 static auto test_split_pos(int)
313 -> decltype(std::declval<U &>().split_pos(std::declval<size_t>(),
314 std::declval<U &>(),
315 std::declval<U &>()),
316 std::true_type());
317
318 template <typename>
319 static std::false_type test_split_pos(...);
320
321 // Test for const position
322 template <typename U>
323 static auto test_position_const(int)
324 -> decltype(std::declval<const U &>().position(std::declval<const Key &>()),
325 std::true_type());
326
327 template <typename>
328 static std::false_type test_position_const(...);
329
330 // Test for non-const position (Splay tree)
331 template <typename U>
332 static auto test_position_nonconst(int)
333 -> decltype(std::declval<U &>().position(std::declval<const Key &>()),
334 std::true_type());
335
336 template <typename>
337 static std::false_type test_position_nonconst(...);
338
339 // Test for const find_position
340 template <typename U>
342 -> decltype(std::declval<const U &>().find_position(std::declval<const Key &>()),
343 std::true_type());
344
345 template <typename>
346 static std::false_type test_find_position_const(...);
347
348 // Test for non-const find_position (Splay tree)
349 template <typename U>
351 -> decltype(std::declval<U &>().find_position(std::declval<const Key &>()),
352 std::true_type());
353
354 template <typename>
355 static std::false_type test_find_position_nonconst(...);
356
357 static constexpr bool has_select =
358 std::is_same_v<decltype(test_select_const<T>(0)), std::true_type> or
359 std::is_same_v<decltype(test_select_nonconst<T>(0)), std::true_type>;
360 static constexpr bool has_remove_pos =
361 std::is_same_v<decltype(test_remove_pos<T>(0)), std::true_type>;
362 static constexpr bool has_split_pos =
363 std::is_same_v<decltype(test_split_pos<T>(0)), std::true_type>;
364 static constexpr bool has_position =
365 std::is_same_v<decltype(test_position_const<T>(0)), std::true_type> or
366 std::is_same_v<decltype(test_position_nonconst<T>(0)), std::true_type>;
367 static constexpr bool has_find_position =
368 std::is_same_v<decltype(test_find_position_const<T>(0)), std::true_type> or
369 std::is_same_v<decltype(test_find_position_nonconst<T>(0)), std::true_type>;
370 };
371
372 // call_select for const trees (RB, AVL, etc.)
373 template <typename T>
374 static auto call_select(const T & t, const size_t i, int)
375 -> decltype(t.select(i))
376 {
377 return t.select(i);
378 }
379
380 // call_select for non-const trees (Splay - mutates on access)
381 template <typename T>
382 static auto call_select_nc(T & t, const size_t i, int)
383 -> decltype(t.select(i))
384 {
385 return t.select(i);
386 }
387
388 template <typename T>
389 static Node * call_select(const T &, const size_t, ...)
390 {
391 ah_domain_error() << "select is not supported by underlying tree";
392 return nullptr;
393 }
394
395 template <typename T>
396 static Node * call_select_nc(T &, const size_t, ...)
397 {
398 ah_domain_error() << "select is not supported by underlying tree";
399 return nullptr;
400 }
401
402 template <typename T>
403 static auto call_remove_pos(T & t, const size_t i, int)
404 -> decltype(t.remove_pos(i))
405 {
406 return t.remove_pos(i);
407 }
408
409 template <typename T>
410 static Node * call_remove_pos(T &, const size_t, ...)
411 {
412 ah_domain_error() << "remove_pos is not supported by underlying tree";
413 return nullptr;
414 }
415
416 template <typename T>
417 static auto call_split_pos(T & t, const size_t pos, T & l, T & r, int)
418 -> decltype(t.split_pos(pos, l, r), void())
419 {
420 t.split_pos(pos, l, r);
421 }
422
423 template <typename T>
424 static void call_split_pos(T &, const size_t, T &, T &, ...)
425 {
426 ah_domain_error() << "split_pos is not supported by underlying tree";
427 }
428
429 template <typename T>
430 static auto call_position(const T & t, const Key & key, int)
431 -> decltype(t.position(key))
432 {
433 return t.position(key);
434 }
435
436 template <typename T>
437 static std::pair<long, Node *> call_position(const T &, const Key &, ...)
438 {
439 ah_domain_error() << "position is not supported by underlying tree";
440 return std::pair<long, Node *>(0, nullptr);
441 }
442
443 template <typename T>
444 static auto call_find_position(const T & t, const Key & key, int)
445 -> decltype(t.find_position(key))
446 {
447 return t.find_position(key);
448 }
449
450 template <typename T>
451 static std::pair<long, Node *> call_find_position(const T &, const Key &, ...)
452 {
453 ah_domain_error() << "find_position is not supported by underlying tree";
454 return std::pair<long, Node *>(0, nullptr);
455 }
456
457 static constexpr size_t dim = 13;
458
460 size_t num_nodes;
461 std::unique_ptr<ArenaTreeAllocator<Node>> arena_allocator;
462
463 Node * alloc_node(const Key & key)
464 {
465 if (arena_allocator)
466 return arena_allocator->alloc_lval(key);
467 return new Node(key);
468 }
469
470 Node * alloc_node(Key && key)
471 {
472 if (arena_allocator)
473 return arena_allocator->alloc_rval(std::forward<Key>(key));
474 return new Node(std::forward<Key>(key));
475 }
476
478 {
479 if (arena_allocator)
480 arena_allocator->unalloc(p);
481 else
482 delete p;
483 }
484
485 public:
487
488 typedef Key Item_Type;
489
490 typedef Key Key_Type;
491
498 noexcept(noexcept(tree.swap(dset.tree)) and
499 noexcept(std::swap(num_nodes, dset.num_nodes)) and
500 noexcept(std::swap(arena_allocator, dset.arena_allocator)))
501 {
502 tree.swap(dset.tree);
503 std::swap(num_nodes, dset.num_nodes);
504 std::swap(arena_allocator, dset.arena_allocator);
505 }
506
508 DynSetTree(const Compare & cmp = Compare())
509 : tree(cmp), num_nodes(0)
510 {
511 // empty
512 }
513
515 DynSetTree(const char *base_addr, const size_t & sz,
516 const Compare & cmp = Compare())
517 : tree(cmp), num_nodes(0),
519 {
520 // empty
521 }
522
524 explicit DynSetTree(const size_t & arena_sz,
525 const Compare & cmp = Compare())
526 : tree(cmp), num_nodes(0),
528 {
529 // empty
530 }
531
534 : tree(srcTree.tree.get_compare()), num_nodes(srcTree.num_nodes)
535 {
536 Node *srcRoot = srcTree.tree.getRoot();
537 try
538 {
539 tree.getRoot() = copyRec(srcRoot);
540 }
541 catch (...)
542 {
543 num_nodes = 0;
544 throw;
545 }
546 }
547
549
555
557 void empty()
558 {
559 if (arena_allocator)
560 {
561 // For arena allocation, just call destructors on keys
562 // (arena handles memory deallocation)
563 callKeyDestructorsRec(tree.getRoot());
564
565 // Reset tree
566 tree.getRoot() = Node::NullPtr;
567 num_nodes = 0;
568 return;
569 }
570
571 destroyRec(tree.getRoot());
572 tree.getRoot() = Node::NullPtr;
573 num_nodes = 0;
574 }
575
577 {
578 return *this = DynSetTree(list);
579 }
580
583 {
584 if (this == &srcTree)
585 return *this;
586
587 Node *src_root = srcTree.tree.getRoot();
588
589 empty();
590
591 tree.getRoot() = copyRec(src_root);
592 num_nodes = srcTree.num_nodes;
593
594 return *this;
595 }
596
599 noexcept
600 {
601 if (this == &srcTree)
602 return *this;
603
604 empty();
605 swap(srcTree);
606 return *this;
607 }
608
610 virtual ~DynSetTree()
611 {
612 empty();
613 }
614
615 private:
616 Key * __insert(Node *p)
617 {
618 Node *q = nullptr;
619 try
620 {
621 q = tree.search_or_insert(p);
622 }
623 catch (...)
624 {
625 free_node(p);
626 throw;
627 }
628
629 if (q != p)
630 return nullptr;
631
632 ++num_nodes;
633
634 return &p->get_key();
635 }
636
637 public:
646 Key * insert(const Key & key)
647 {
648 Node *p = alloc_node(key);
649 Key *key_p = __insert(p);
650 if (key_p == nullptr) // was there insertion?
651 { // No (KEY(p) is already in the tree) ==> free p and return nullptr
652 free_node(p);
653 return nullptr;
654 }
655
656 return key_p;
657 }
658
659 Key * insert(Key && key)
660 {
661 Node *p = alloc_node(std::forward<Key>(key));
662 Key *key_p = __insert(p);
663 if (key_p == nullptr) // was there insertion?
664 {
665 free_node(p);
666 return nullptr;
667 }
668
669 return key_p;
670 }
671
672 Key * append(const Key & key)
673 {
674 return insert(key);
675 }
676
677 Key * append(Key && key)
678 {
679 return insert(std::forward<Key>(key));
680 }
681
682 private:
684 {
685 Node *q = nullptr;
686 try
687 {
688 q = tree.search_or_insert(p);
689 }
690 catch (...)
691 {
692 free_node(p);
693 throw;
694 }
695 if (q != p) // was there an insertion?
696 free_node(p); // No (KEY(p) is already in the tree) ==> free
697 // allocated node
698 else
699 ++num_nodes;
700
701 return &q->get_key();
702 }
703
704 std::pair<Node *, bool> __contains_or_insert(Node *p)
705 {
706 Node *q = nullptr;
707 try
708 {
709 q = tree.search_or_insert(p);
710 }
711 catch (...)
712 {
713 free_node(p);
714 throw;
715 }
716 if (q != p)
717 { // KEY(p) is already inside the tree
718 free_node(p);
719 return std::pair<Node *, bool>(q, true);
720 }
721 ++num_nodes;
722 return std::pair<Node *, bool>(p, false);
723 }
724
725 public:
738 Key * search_or_insert(const Key & key)
739 {
740 return __search_or_insert(alloc_node(key));
741 }
742
743 Key * search_or_insert(Key && key)
744 {
745 return
746 __search_or_insert(alloc_node(std::forward<Key>(key)));
747 }
748
749 /* Look for the key <code>key</code> in the binary search tree and
750 eventually inserts it if it is not found.
751
752 <code>contains_or_insert(key)</code> searches the tree for the key
753 <code>key</code>. If the key is already found, then it is returned
754 true. Otherwise, the key is inserted and false is returned.
755
756 @param[in] key to find or insert
757 @return a std::pair whose first field is a pointer to the found or
758 inserted key, and the second field is a boolean whose value is
759 `false` if the key was inserted; `true` otherwise, that is if the
760 key is already present in the tree.
761 */
762 std::pair<Key *, bool> contains_or_insert(const Key & key)
763 {
764 auto p = __contains_or_insert(alloc_node(key));
765 return std::pair<Key *, bool>(&p.first->get_key(), p.second);
766 }
767
768 std::pair<Key *, bool> contains_or_insert(Key && key)
769 {
770 auto p = __contains_or_insert(alloc_node(std::forward<Key>(key)));
771 return std::pair<Key *, bool>(&p.first->get_key(), p.second);
772 }
773
774 private:
776 {
777 try
778 {
779 Node *p = tree.insert_dup(q);
780 ++num_nodes;
781 return &p->get_key();
782 }
783 catch (...)
784 {
785 free_node(q);
786 throw;
787 }
788 }
789
790 public:
791 Key * insert_dup(const Key & key)
792 {
793 return __insert_dup(alloc_node(key));
794 }
795
796 Key * insert_dup(Key && key)
797 {
798 return __insert_dup(alloc_node(std::forward<Key>(key)));
799 }
800
801 Key * put(const Key & key)
802 {
803 return insert(key);
804 }
805
806 Key * put(Key && key)
807 {
808 return insert(std::forward<Key>(key));
809 }
810
818 size_t remove(const Key & key)
819 {
820 Node *p = static_cast<Node *>(tree.remove(key));
821
822 if (p == nullptr)
823 return num_nodes;
824
825 free_node(p);
826
827 return --num_nodes;
828 }
829
840 Key del(const Key & key)
841 {
842 Node *p = static_cast<Node *>(tree.remove(key));
843
844 ah_domain_error_if(p == nullptr)
845 << "DynSetTree::del key is not found in the tree";
846
847 auto ret_val = p->get_key();
848
849 free_node(p);
850
851 --num_nodes;
852
853 return ret_val;
854 }
855
860 Key remove_pos(const size_t i)
861 {
863 << "remove_pos is not supported by underlying tree";
864
866 << "remove_pos index out of range";
867
868 Node *p = static_cast<Node *>(call_remove_pos(tree, i, 0));
869 ah_logic_error_if(p == nullptr)
870 << "remove_pos returned nullptr";
871 const Key ret_val = KEY(p);
872
873 free_node(p);
874
875 --num_nodes;
876
877 return ret_val;
878 }
879
881 bool exist(const Key & key) const
882 {
883 return search(key) != nullptr;
884 }
885
886 bool has(const Key & key) const
887 {
888 return exist(key);
889 }
890
891 bool contains(const Key & key) const
892 {
893 return exist(key);
894 }
895
910 Key &find(const Key & key) const
911 {
912 Node *node = static_cast<Node *>(tree.search(key));
913
914 ah_domain_error_if(node == nullptr)
915 << "key not found";
916
917 return node->get_key();
918 }
919
934 std::pair<long, Key *> find_position(const Key & key) const
935 {
937 << "find_position is not supported by underlying tree";
938
939 if (num_nodes == 0)
940 return std::pair<long, Key *>(0, nullptr);
941
942 auto p = call_find_position(tree, key, 0);
943 if (p.second == nullptr)
944 return std::pair<long, Key *>(static_cast<long>(p.first), nullptr);
945
946 return std::pair<long, Key *>(static_cast<long>(p.first),
947 &p.second->get_key());
948 }
949
964 Key * search(const Key & key) const
965 {
966 Node *node = static_cast<Node *>(tree.search(key));
967
968 if (node == nullptr)
969 return nullptr;
970
971 return &(node->get_key());
972 }
973
976 const Key &min() const
977 {
979 << "set is empty";
980
981 return find_min(tree.getRoot())->get_key();
982 }
983
985 const Key &get_first() const { return min(); }
986
989 const Key &max() const
990 {
992 << "set is empty";
993
994 return find_max(tree.getRoot())->get_key();
995 }
996
998 const Key &get_last() const { return max(); }
999
1001 const Key &get() const { return max(); }
1002
1004 const size_t &size() const { return num_nodes; }
1005
1007 bool is_empty() const { return num_nodes == 0; }
1008
1011 {
1012 return arena_allocator != nullptr;
1013 }
1014
1017 {
1018 if (arena_allocator)
1019 return arena_allocator->allocated_size();
1020 return 0;
1021 }
1022
1025 {
1026 if (arena_allocator)
1027 return arena_allocator->available_size();
1028 return 0;
1029 }
1030
1034 {
1035 return Aleph::internal_path_length(tree.getRoot());
1036 }
1037
1038 Node * get_root_node() const { return tree.getRoot(); }
1039
1040 const Key &get_root() const
1041 {
1043 << "Tree is empty";
1044 return KEY(tree.getRoot());
1045 }
1046
1048 const Key &get_item() const { return get_root(); }
1049
1051 size_t height() const { return computeHeightRec(tree.getRoot()); }
1052
1055 template <class Op>
1056 void for_each_in_preorder(void (*visitFct)(Node *, int, int))
1057 {
1058 Node *root = static_cast<Node *>(tree.getRoot());
1060 }
1061
1074 long position(const Key & key) const
1075 {
1077 << "position is not supported by underlying tree";
1078
1079 auto p = call_position(tree, key, 0);
1080 return static_cast<long>(p.first);
1081 }
1082
1088 Key &select(size_t i)
1089 {
1091 << "select is not supported by underlying tree";
1092
1094 << "select index out of range";
1095
1096 // Try non-const first (for Splay trees), then const
1097 Node *p = call_select_nc(tree, i, 0);
1098 ah_logic_error_if(p == nullptr)
1099 << "select returned nullptr";
1100 return p->get_key();
1101 }
1102
1103 const Key &select(size_t i) const
1104 {
1106 << "select is not supported by underlying tree";
1107
1109 << "select index out of range";
1110
1111 // For const version, only const select works (not for Splay trees)
1112 Node *p = call_select(tree, i, 0);
1113 ah_logic_error_if(p == nullptr)
1114 << "select returned nullptr";
1115 return p->get_key();
1116 }
1117
1118 Key &operator ()(size_t i)
1119 {
1120 return select(i);
1121 }
1122
1123 const Key &operator [](const Key & key) const
1124 {
1125 return find(key);
1126 }
1127
1128 const Key &operator [](const Key & key)
1129 {
1130 return *search_or_insert(key);
1131 }
1132
1133 Key &access(size_t i)
1134 {
1135 return select(i);
1136 }
1137
1138 bool verify() const
1139 {
1140 return tree.verify() and check_bst(tree.getRoot());
1141 }
1142
1143 private:
1144 template <class Key_Op>
1145 struct Node_Op
1146 {
1148
1150 { /* empty */
1151 }
1152
1154 {
1155 /* empty */
1156 }
1157
1159 {
1160 assert(root != nullptr);
1161 key_op(KEY(root));
1162 }
1163 };
1164
1165 public:
1190 template <class Key_Op>
1191 void for_each_preorder(Key_Op & key_op) const
1192 {
1193 Node *root = static_cast<Node *>(tree.getRoot());
1194
1195 Node_Op<Key_Op> node_op(const_cast<Key_Op &>(key_op));
1196
1198 }
1199
1207 template <class Key_Op>
1208 void for_each_preorder(Key_Op && key_op = Key_Op()) const
1209 {
1211 }
1212
1237 template <class Key_Op>
1238 void for_each_inorder(Key_Op & key_op) const
1239 {
1240 Node *root = static_cast<Node *>(tree.getRoot());
1241
1242 Node_Op<Key_Op> node_op(const_cast<Key_Op &>(key_op));
1243
1245 }
1246
1254 template <class Key_Op>
1255 void for_each_inorder(Key_Op && key_op = Key_Op()) const
1256 {
1258 }
1259
1284 template <class Key_Op>
1285 void for_each_postorder(Key_Op & key_op) const
1286 {
1287 Node *root = static_cast<Node *>(tree.getRoot());
1288
1289 Node_Op<Key_Op> node_op(const_cast<Key_Op &>(key_op));
1290
1292 }
1293
1301 template <class Key_Op>
1302 void for_each_postorder(Key_Op && key_op = Key_Op()) const
1303 {
1305 }
1306
1320 {
1321 tree.join(t.tree, dup.tree);
1322 t.tree.getRoot() = Node::NullPtr;
1323 t.num_nodes = 0;
1325 dup.num_nodes = compute_cardinality_rec(dup.tree.getRoot());
1326 return *this;
1327 }
1328
1339 {
1340 return join(t, dup);
1341 }
1342
1356 {
1357 tree.join_dup(t.tree);
1358 t.num_nodes = 0;
1359 t.tree.getRoot() = Node::NullPtr;
1361 return *this;
1362 }
1363
1379 bool split_key(const Key & key, DynSetTree & l, DynSetTree & r)
1380 {
1381 if (not tree.split_key(key, l.tree, r.tree))
1382 return false;
1383
1384 tree.getRoot() = Node::NullPtr;
1385 num_nodes = 0;
1386 l.num_nodes = compute_cardinality_rec(l.tree.getRoot());
1387 r.num_nodes = compute_cardinality_rec(r.tree.getRoot());
1388
1389 return true;
1390 }
1391
1404 void split_pos(const size_t pos, DynSetTree & l, DynSetTree & r)
1405 {
1407 << "split_pos is not supported by underlying tree";
1408
1410 << "split_pos position out of range";
1411
1412 // Underlying split_pos splits at [0, pos) and [pos, N)
1413 // But we want [0, pos] and (pos, N), so we split at pos+1
1414 call_split_pos(tree, pos + 1, l.tree, r.tree, 0);
1415 tree.getRoot() = Node::NullPtr;
1416 num_nodes = 0;
1417 l.num_nodes = compute_cardinality_rec(l.tree.getRoot());
1418 r.num_nodes = compute_cardinality_rec(r.tree.getRoot());
1419 }
1420
1433 void split_key_dup(const Key & key, DynSetTree & l, DynSetTree & r)
1434 {
1435 tree.split_key_dup(key, l.tree, r.tree);
1436 tree.getRoot() = Node::NullPtr;
1437 num_nodes = 0;
1438 l.num_nodes = compute_cardinality_rec(l.tree.getRoot());
1439 r.num_nodes = compute_cardinality_rec(r.tree.getRoot());
1440 }
1441
1443 {
1444 using Base = typename Tree_Type::Iterator;
1445
1447
1450
1452 { /* empty */
1453 }
1454
1456 {
1457 return Base::get_curr_ne()->get_key();
1458 }
1459
1460 Key &get_curr_ne() noexcept { return Base::get_curr_ne()->get_key(); }
1461
1462 const Key &get_curr() const { return Base::get_curr()->get_key(); }
1463
1464 Key &get_curr() { return Base::get_curr()->get_key(); }
1465 };
1466
1481 template <class Operation>
1483 {
1484 return Aleph::traverse(tree.getRoot(), [&op](Node *p)
1485 {
1486 return op(p->get_key());
1487 });
1488 }
1489
1490 template <class Operation>
1492 {
1493 return traverse<Operation>(op);
1494 }
1495
1496 template <class Operation>
1497 bool traverse(Operation & op) const
1498 {
1499 return Aleph::traverse(tree.getRoot(), [&op](Node *p)
1500 {
1501 return op(p->get_key());
1502 });
1503 }
1504
1505 template <class Operation>
1506 bool traverse(Operation && op = Operation()) const
1507 {
1508 return traverse<Operation>(op);
1509 }
1510 };
1511
1512
1513# define SETTREE_ITOR(Name, Key, Cmp) \
1514 class Iterator : public DynSetTree<Key, Name, Cmp>::Iterator \
1515 { \
1516 public: \
1517 Iterator() : DynSetTree<Key, Name, Cmp>::Iterator() \
1518 { /* empty */ } \
1519 \
1520 Iterator(DynSetTree<Key, Name, Cmp> & tree) \
1521 : DynSetTree<Key, Name, Cmp>::Iterator(tree) \
1522 { /* empty */ } \
1523 };
1524
1525
1532 template <typename Key, class Compare = Aleph::less<Key>>
1533 class DynSetBinTree : public DynSetTree<Key, BinTree, Compare>
1534 {
1535 public:
1537 using Base::Base;
1538 };
1539
1540
1547 template <typename Key, class Compare = Aleph::less<Key>>
1548 class DynSetAvlTree : public DynSetTree<Key, Avl_Tree, Compare>
1549 {
1550 public:
1552 using Base::Base;
1553 };
1554
1555
1562 template <typename Key, class Compare = Aleph::less<Key>>
1563 class DynSetSplayTree : public DynSetTree<Key, Splay_Tree, Compare>
1564 {
1565 public:
1567 using Base::Base;
1568 };
1569
1570
1584 template <typename Key, class Compare = Aleph::less<Key>>
1585 class DynSetSplayRkTree : public DynSetTree<Key, Splay_Tree_Rk, Compare>
1586 {
1587 public:
1589 using Base::Base;
1591 };
1592
1593
1600 template <typename Key, class Compare = Aleph::less<Key>>
1601 class DynSetRandTree : public DynSetTree<Key, Rand_Tree, Compare>
1602 {
1603 public:
1605 using Base::Base;
1606
1607 class Iterator : public DynSetTree<Key, Rand_Tree, Compare>::Iterator
1608 {
1609 public:
1611 { /* empty */
1612 }
1613
1615 : DynSetTree<Key, Rand_Tree, Compare>::Iterator(tree)
1616 { /* empty */
1617 }
1618 };
1619 };
1620
1621
1628 template <typename Key, class Compare = Aleph::less<Key>>
1629 class DynSetTreap : public DynSetTree<Key, Treap, Compare>
1630 {
1631 public:
1633 using Base::Base;
1634 };
1635
1642 template <typename Key, class Compare = Aleph::less<Key>>
1643 class DynSetTreapRk : public DynSetTree<Key, Treap_Rk, Compare>
1644 {
1645 public:
1647 using Base::Base;
1648 SETTREE_ITOR(Treap_Rk, Key, Compare);
1649 };
1650
1651
1660 template <typename Key, class Compare = Aleph::less<Key>>
1661 class DynSetAvlRkTree : public DynSetTree<Key, Avl_Tree_Rk, Compare>
1662 {
1663 public:
1665 using Base::Base;
1667 };
1668
1669
1676 template <typename Key, class Compare = Aleph::less<Key>>
1677 class DynSetRbTree : public DynSetTree<Key, Rb_Tree, Compare>
1678 {
1679 public:
1681 using Base::Base;
1682 };
1683
1684
1695 template <typename Key, class Compare = Aleph::less<Key>>
1696 class DynSetTdRbTree : public DynSetTree<Key, TdRbTree, Compare>
1697 {
1698 public:
1700 using Base::Base;
1701 };
1702
1703
1712 template <typename Key, class Compare = Aleph::less<Key>>
1713 class DynSetRbRkTree : public DynSetTree<Key, Rb_Tree_Rk, Compare>
1714 {
1715 public:
1717 using Base::Base;
1718 SETTREE_ITOR(Rb_Tree_Rk, Key, Compare);
1719 };
1720
1721
1731 template <typename Key, class Compare = Aleph::less<Key>>
1732 class DynSetTdRbRkTree : public DynSetTree<Key, TdRbTreeRk, Compare>
1733 {
1734 public:
1736 using Base::Base;
1737 SETTREE_ITOR(TdRbTreeRk, Key, Compare);
1738 };
1739
1740
1754 template <typename Key, class Compare = Aleph::less<Key>>
1755 class DynSetHtdRbTree : public DynSetTree<Key, HtdRbTree, Compare>
1756 {
1757 public:
1759 using Base::Base;
1760 SETTREE_ITOR(HtdRbTree, Key, Compare);
1761 };
1762
1763
1777 template <typename Key, class Compare = Aleph::less<Key>>
1778 class DynSetHtdRbRkTree : public DynSetTree<Key, HtdRbTreeRk, Compare>
1779 {
1780 public:
1782 using Base::Base;
1784 };
1785
1786
1787 template <typename T, class Op, class C>
1788 DynSetTree<T> set_unify(const C & c, Op op)
1789 {
1791 for (auto it = c.get_it(); it.has_curr(); it.next_ne())
1792 ret.insert(op(it.get_curr()));
1793 return ret;
1794 }
1795} // end namespace Aleph
1796
1797# endif /* TPL_DYNSETTREE_H */
Memory arena for fast bulk allocations.
Variadic constructor macros for containers.
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:1423
T & insert(const T &item)
Insert a new item by copy.
Definition htlist.H:1502
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.
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
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)
NodeType< Key > Node
Hybrid top-down/bottom-up red-black tree with rank support.
Hybrid top-down/bottom-up red-black tree.
Definition tpl_hRbTree.H:84
Top-down red-black tree with rank (no virtual destructor).
Equality test for containers.
Definition ah-dry.H:1534
Common methods to the Aleph-w ( ) containers.
Definition ah-dry.H:548
Aleph::DynList< __T > maps(Operation &op) const
Map the elements of the container.
Definition ah-dry.H:904
Common sequential searching methods on containers.
Definition ah-dry.H:164
Mixin that adds STL begin()/end() and cbegin()/cend() to Aleph containers.
iterator end() noexcept
Return an STL-compatible end iterator.
iterator begin() noexcept
Return an STL-compatible iterator to the first element.
__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
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:107
DynList< T > maps(const C &c, Op op)
Classic map operation.
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:1424
AVL binary search tree with nodes without virtual destructor.
Definition tpl_avl.H:704
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
Iterator on nodes of the tree.
Red-Black binary search tree with nodes without virtual destructor and with subtree counters for sele...
Definition tpl_rbRk.H:1544
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:1501
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