Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_tree_node.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
44# ifndef TPL_TREE_H
45# define TPL_TREE_H
46
47# include <stdexcept>
48# include <dlink.H>
49# include <ahDry.H>
50# include <ah-dry-mixin.H>
51# include <ahIterator.H>
52# include <ahFunction.H>
53# include <ahFunctional.H>
54# include <htlist.H>
55# include <tpl_dynListStack.H>
56# include <tpl_dynListQueue.H>
57# include <tpl_binNode.H>
58# include <ah-errors.H>
59
60# define ISROOT(p) ((p)->is_root())
61# define ISLEAF(p) ((p)->is_leaf())
62# define ISLEFTMOST(p) ((p)->is_leftmost())
63# define ISRIGHTMOST(p) ((p)->is_rightmost())
64
65# define SIBLING_LIST(p) ((p)->get_sibling_list())
66# define CHILD_LIST(p) ((p)->get_child_list())
67# define SIBLING_LINK(p) ((p)->get_sibling_list())
68# define LCHILD(p) ((p)->get_left_child())
69# define RSIBLING(p) ((p)->get_right_sibling())
70# define IS_UNIQUE_SIBLING(p) (RSIBLING(p) == (p))
71
72namespace Aleph
73{
74
84 template <class T>
85 class Tree_Node; // Forward declaration for CRTP
86
87 template <class T>
88 class Tree_Node : public FunctionalMixin<Tree_Node<T>, Tree_Node<T>*>
89 {
93
94 struct Flags
95 {
96 unsigned int is_root : 1;
97 unsigned int is_leaf : 1;
98 unsigned int is_leftmost : 1;
99 unsigned int is_rightmost : 1;
102 };
103
105
108
113
118
123
128
129 public:
130
132
134 T & get_key() noexcept { return get_data(); }
135
136 [[nodiscard]] constexpr const T & get_key() const noexcept { return get_data(); }
137
139 T & get_data() noexcept { return data; }
140
141 [[nodiscard]] constexpr const T & get_data() const noexcept { return data; }
142
144 using key_type = T;
145
147
149
151 [[nodiscard]] constexpr bool is_root() const noexcept { return flags.is_root; }
152
154 [[nodiscard]] constexpr bool is_leaf() const noexcept { return flags.is_leaf; }
155
157 [[nodiscard]] constexpr bool is_leftmost() const noexcept { return flags.is_leftmost; }
158
160 [[nodiscard]] constexpr bool is_rightmost() const noexcept { return flags.is_rightmost; }
161
162 void set_is_root(bool value) noexcept { flags.is_root = value; }
163
164 void set_is_leaf(bool value) noexcept { flags.is_leaf = value; }
165
166 void set_is_leftmost(bool value) noexcept { flags.is_leftmost = value; }
167
168 void set_is_rightmost(bool value) noexcept { flags.is_rightmost = value; }
169
171 Tree_Node() = default;
172
174 Tree_Node(const T & d)
175 : data(d) { /* empty */ }
176
178 : data(std::move(d)) { /* empty */ }
179
182 {
183 if (is_leftmost())
184 return nullptr;
185
186 return left_link();
187 }
188
191 {
192 if (is_rightmost())
193 return nullptr;
194
195 return right_link();
196 }
197
200 {
201 if (is_leaf())
202 return nullptr;
203
204 return lower_link();
205 }
206
209 {
210 if (is_leaf())
211 return nullptr;
212
213 const Tree_Node * left_child = lower_link();
214
216
217 return left_child->left_link();
218 }
219
227 Tree_Node * get_child(const size_t i) const noexcept
228 {
230 for (size_t j = 0; c != nullptr and j < i; ++j)
231 c = c->get_right_sibling();
232
233 return c;
234 }
235
238 {
239 if (is_root())
240 return nullptr;
241
242 auto * p = const_cast<Tree_Node*>(this);
243 while (not ISLEFTMOST(p)) // go down to the leftmost node
244 p = p->left_link();
245
246 assert(not ISROOT(p));
247 assert(not CHILD_LIST(p)->is_empty());
248
249 return p->upper_link();
250 }
251
259 {
260 if (p == nullptr)
261 return;
262
263 assert(CHILD_LIST(p)->is_empty());
264 assert(SIBLING_LIST(p)->is_empty());
265 assert(p->is_rightmost() and p->is_leftmost() and p->is_root() and
266 p->is_leaf());
267
268 p->set_is_root(false);
269 p->set_is_leftmost(false);
270
272 if (old_next_node != nullptr)
273 {
274 assert(not this->is_rightmost());
275 p->set_is_rightmost(false);
276 }
277 else
278 {
279 assert(this->is_rightmost());
280 p->set_is_rightmost(true);
281 }
282
283 this->set_is_rightmost(false);
284 this->sibling.insert(SIBLING_LIST(p));
285 }
286
294 {
295 if (p == nullptr)
296 return;
297
299 << "Cannot insert sibling of a root";
300
301 assert(CHILD_LIST(p)->is_empty());
302 assert(SIBLING_LIST(p)->is_empty());
304 p->is_leaf());
305
306 p->set_is_root(false);
307 p->set_is_rightmost(false);
308
310 if (old_prev_node != nullptr)
311 {
312 assert(not this->is_leftmost());
313 p->set_is_leftmost(false);
314 }
315 else
316 { // this is the leftmost ==> p must become the first child
317 assert(this->is_leftmost());
318
319 Tree_Node * parent = this->get_parent();
320
321 // Find the tree root. To do so, we look for the leaf of this
322 Tree_Node * leaf = this;
323 while (not leaf->is_leaf())
324 {
326 assert(leaf != nullptr);
327 }
328
330 assert(root != nullptr);
331
332 Dlink tree = CHILD_LIST(root)->cut_list(CHILD_LIST(this));
333 tree.del();
334 CHILD_LIST(parent)->insert(CHILD_LIST(p));
335 p->set_is_leftmost(true);
336
337 assert(p->get_parent() == parent);
338 }
339
340 this->set_is_leftmost(false);
341 this->sibling.append(SIBLING_LIST(p));
342 }
343
349 {
350 if (p == nullptr)
351 return;
352
353 assert(CHILD_LIST(p)->is_empty());
354 assert(SIBLING_LIST(p)->is_empty());
355 assert(p->is_rightmost() and p->is_leftmost() and p->is_root() and
356 p->is_leaf());
357
358 p->set_is_root(false);
359 if (this->is_leaf())
360 {
361 this->set_is_leaf(false);
362 CHILD_LIST(this)->insert(CHILD_LIST(p));
363 }
364 else
365 {
368 while (not leaf->is_leaf())
370
373 subtree.del();
374 CHILD_LIST(this)->insert(CHILD_LIST(p));
376 old_left_child->set_is_leftmost(false);
377 p->set_is_rightmost(false);
378 assert(p->get_right_sibling() == old_left_child);
379 assert(old_left_child->get_left_sibling() == p);
380 }
381 assert(p->is_leftmost());
382 }
383
389 {
390 if (p == nullptr)
391 return;
392
393 assert(CHILD_LIST(p)->is_empty());
394 assert(SIBLING_LIST(p)->is_empty());
395 assert(p->is_rightmost() and p->is_leftmost() and p->is_root() and
396 p->is_leaf());
397
398 p->set_is_root(false);
399
400 if (this->is_leaf())
401 {
402 this->set_is_leaf(false);
403 CHILD_LIST(this)->insert(CHILD_LIST(p));
404 }
405 else
406 {
408 old_right_child_node->set_is_rightmost(false);
409 p->set_is_leftmost(false);
411 }
412 }
413
416 {
417 assert(this->is_root());
418 assert(tree != nullptr);
419 assert(tree->is_root() and tree->is_leftmost() and tree->is_rightmost());
420
421 tree->set_is_root(false);
422
423 if (this->is_leaf())
424 {
425 assert(CHILD_LIST(this)->is_empty() and
426 SIBLING_LIST(this)->is_empty());
427 this->set_is_leaf(false);
428 CHILD_LIST(this)->splice(CHILD_LIST(tree));
429 }
430 else
431 {
433 right_child->set_is_rightmost(false);
434 tree->set_is_leftmost(false);
435 SIBLING_LINK(right_child)->splice(SIBLING_LINK(tree));
436 }
437
438 return this;
439 }
440
454 {
455 if (tree == nullptr)
456 return;
457
459 << "\"this\" is not root";
460
461 tree->set_is_leftmost(false);
463 if (old_next_tree != nullptr)
464 {
465 assert(not this->is_rightmost());
466 tree->set_is_rightmost(false);
467 }
468
469 this->set_is_rightmost(false);
470 SIBLING_LIST(this)->insert(SIBLING_LIST(tree));
471 }
472
475 {
476 if (is_leftmost())
477 return nullptr;
479 return left_link();
480 }
481
484 {
485 if (is_rightmost())
486 return nullptr;
487
489 return right_link();
490 }
491
495 {
497 << "\"this\" is not the leftmost tree in the forest";
498
499 return left_link();
500 }
501
503 template <template <typename> class Container = DynList>
505 {
507 for (auto t = const_cast<Tree_Node*>(this); t != nullptr;
508 t = t->get_right_tree())
509 ret.append(t);
510 return ret;
511 }
512
514 template <typename Operation>
515 void for_each_child(Operation & op) const
516 {
517 for (Tree_Node * child = get_left_child(); child != nullptr;
518 child = child->get_right_sibling())
519 op(child);
520 }
521
522 template <typename Operation>
523 void for_each_child(Operation && op = Operation()) const
524 {
526 }
527
529 template <template <typename> class Container = DynList>
531 {
533 this->for_each_child([&ret_val] (Tree_Node * p) { ret_val.append(p); });
534 return ret_val;
535 }
536
538 template <template <typename> class Container = DynList>
540 {
542 this->for_each_child([&ret_val] (Tree_Node * p)
543 {
544 ret_val.append(p->get_key());
545 });
546 return ret_val;
547 }
548
549 private:
550
551 template <class Operation> static
552 bool preorder(const Tree_Node * root, Operation & op)
553 {
554 if (root == nullptr)
555 return true;
556
557 if (not op(root))
558 return false;
559
560 for (Tree_Node * child = root->get_left_child(); child != nullptr;
561 child = child->get_right_sibling())
562 if (not preorder(child, op))
563 return false;
564
565 return true;
566 }
567
568 public:
569
571 template <class Operation>
573 {
574 return preorder(this, op);
575 }
576
577 template <class Operation>
578 bool traverse(Operation op) const
579 {
580 return const_cast<Tree_Node*>(this)->traverse(op);
581 }
582
583 template <class Op> bool level_traverse(Op op)
584 {
586 q.put(this);
587 while (not q.is_empty())
588 {
589 Tree_Node * p = q.get();
590 if (not op(p))
591 return false;
592 p->for_each_child([&q] (auto cptr) { q.put(cptr); });
593 }
594 return true;
595 }
596
597 template <class Op> bool level_traverse(Op op) const
598 {
599 return const_cast<Tree_Node*>(this)->level_traverse(op);
600 }
601
602 // Note: for_each(), all(), exists(), maps(), filter(), foldl(),
603 // fold(), partition(), take(), drop(), rev(), length() are now
604 // provided by FunctionalMixin<Tree_Node<T>, Tree_Node<T>*>
605
610 {
611 Tree_Node * curr = nullptr;
612
613 public:
614
616 : curr(p.get_left_child()) {}
617
619 : curr(p.get_left_child()) {}
620
622 : curr(p->get_left_child()) {}
623
626
627 bool has_curr() const noexcept { return curr != nullptr; }
628
630
632 {
633 ah_overflow_error_if(curr == nullptr) << "Children_Iterator::get_curr()";
634 return get_curr_ne();
635 }
636
638
639 void next()
640 {
641 ah_overflow_error_if(curr == nullptr) << "Children_Iterator::next()";
642 next_ne();
643 }
644 };
645
647 {
648 return Children_Iterator(*this);
649 }
650
651 struct Children_Set // trick to use Pair_Iterator
652 {
656 {
658 };
659 };
660
662 {
663 Tree_Node * root = nullptr;
664 Tree_Node * curr = nullptr;
665 long pos = 0;
667
668 public:
669
671
672 void swap(Iterator & it) noexcept
673 {
674 std::swap(root, it.root);
675 std::swap(curr, it.curr);
676 std::swap(pos, it.pos);
677 s.swap(it.s);
678 }
679
681 : root(r), curr(root)
682 {
683 // empty
684 }
685
687
688 Iterator(const Iterator & it)
689 : root(it.root), curr(it.curr), pos(it.pos), s(it.s)
690 {
691 // empty
692 }
693
695 : root(nullptr), curr(nullptr), pos(0), s()
696 {
697 swap(it);
698 }
699
701 {
702 it.swap(*this);
703 return *this;
704 }
705
707 {
708 s.empty();
709 pos = 0;
710 curr = root;
711 }
712
713 bool has_curr() const noexcept { return curr != nullptr; }
714
716
718 {
719 ah_overflow_error_if(not has_curr()) << "Iterator overflow";
720 return get_curr_ne();
721 }
722
724 {
725 ++pos;
727 if (lchild == nullptr)
728 {
729 if (s.is_empty())
730 curr = nullptr;
731 else
732 curr = s.pop();
733
734 return;
735 }
736
737 for (auto p = curr->get_right_child(); p != lchild;
738 p = p->get_left_sibling())
739 s.push(p);
740
741 curr = lchild;
742 }
743
744 void next()
745 {
746 ah_overflow_error_if(not has_curr()) << "Iterator overflow";
747 next_ne();
748 }
749
750 void end()
751 {
752 curr = nullptr;
753 s.empty();
754 pos = -1;
755 }
756
758 // has_curr() == true
759 size_t get_pos() const { return pos; }
760 };
761
763 {
764 return Iterator(const_cast<Tree_Node*>(this));
765 }
766
768 };
769
770 template <typename T>
771 struct Tree_Node_Vtl : public Tree_Node<T>
772 {
773 virtual ~Tree_Node_Vtl() = default;
774 };
775
776 template <class Node> static inline
777 void clone_tree(Node * src, Node * tgt)
778 {
779 using It = typename Node::Children_Iterator;
780 for (It it(src); it.has_curr(); it.next_ne())
781 tgt->insert_rightmost_child(new Node(it.get_curr()->get_key()));
782
783 using PItor = Pair_Iterator<It>;
784 for (PItor itor{It(*src), It(*tgt)}; itor.has_curr(); itor.next_ne())
785 {
786 auto p = itor.get_curr();
787 clone_tree(p.first, p.second);
788 }
789 }
790
791 template <class Node>
793 {
794 if (root == nullptr)
795 return nullptr;
796 Node * ret = new Node(root->get_key());
798 return ret;
799 }
800
801 template <class Node> static inline
802 void __tree_preorder_traversal(Node * root, const int & level,
803 const int & child_index,
804 void (*visitFct)(Node *, int, int))
805 {
806 (*visitFct)(root, level, child_index);
807 Node * child = root->get_left_child();
808 for (int i = 0; child != nullptr; ++i, child = child->get_right_sibling())
809 __tree_preorder_traversal(child, level + 1, i, visitFct);
810 }
811
834 template <class Node> inline
835 void tree_preorder_traversal(Node * root, void (*visitFct)(Node *, int, int))
836 {
837
838 ah_domain_error_if(not root->is_root())
839 << "root is not root";
840
842 }
843
866 template <class Node> inline
868 void (*visitFct)(Node *, int, int))
869 {
870 ah_domain_error_if(not root->is_root()) << "root is not root";
871
872 for (/* nothing */; root != nullptr; root = root->get_right_tree())
873 {
874 assert(root->is_root());
876 }
877 }
878
879 template <class Node> static inline
880 void __tree_postorder_traversal(Node * node, const int & level,
881 const int & child_index,
882 void (*visitFct)(Node *, int, int))
883 {
884 Node * child = node->get_left_child();
885
886 for (int i = 0; child not_eq nullptr;
887 i++, child = child->get_right_sibling())
888 __tree_postorder_traversal(child, level + 1, i, visitFct);
889
890 (*visitFct)(node, level, child_index);
891 }
892
914 template <class Node> inline
915 void tree_postorder_traversal(Node * root, void (*visitFct)(Node *, int, int))
916 {
918 }
919
943 template <class Node> inline
944 void forest_postorder_traversal(Node * root, void (*visitFct)(Node *, int, int))
945 {
946 ah_domain_error_if(not root->is_leftmost()) << "root is not the leftmost node of forest";
947
948 ah_domain_error_if(not root->is_root()) << "root is not root";
949
950 for (/* nothing */; root not_eq nullptr; root = root->get_right_sibling())
951 {
952 assert(root->is_root());
954 }
955 }
956
961 template <class Node, class Eq>
962 inline bool are_tree_equal(Node * t1, Node * t2, Eq & eq)
963 {
964 if (t1 == nullptr)
965 return t2 == nullptr;
966
967 if (t2 == nullptr)
968 return false;
969
970 if (not eq(t1->get_key(), t2->get_key()))
971 return false;
972
973 try
974 {
975 return zipEq(t1->children_nodes(), t2->children_nodes()).
976 all([&eq] (auto p)
977 {
978 return are_tree_equal(p.first, p.second, eq);
979 });
980 }
981 catch (const std::length_error &)
982 {
983 return false;
984 }
985 }
986
987 template <class Node,
988 class Eq = std::equal_to<typename Node::key_type>>
989 inline bool are_tree_equal(Node * t1, Node * t2, Eq && eq = Eq())
990 {
992 }
993
1002 template <class Node> inline
1004 {
1005 if (root == nullptr)
1006 return;
1007
1009 SIBLING_LIST(root)->del(); // no ==> remove from sibling list
1010
1011 // traverse subtrees from right to left
1012 for (Node * p = static_cast<Node *>(root->get_right_child()); p != nullptr; /* nada */)
1013 {
1014 Node * to_delete = p; // backup subtree to delete
1015 p = static_cast<Node *>(p->get_left_sibling()); // advance to left sibling
1016 destroy_tree(to_delete); // recursively delete tree
1017 }
1018
1019 if (root->is_leftmost()) // remove children list?
1020 CHILD_LIST(root)->del();
1021
1022 delete root;
1023 }
1024
1036 template <class Node> inline
1038 {
1039 if (root == nullptr)
1040 return;
1041
1042 ah_domain_error_if(not root->is_leftmost()) << "root is not the leftmost tree of forest";
1043
1044 ah_domain_error_if(not root->is_root()) << "root is not root";
1045
1046 while (root != nullptr) // traverse trees from left to right
1047 {
1048 Node * to_delete = root; // backup root
1049 root = (Node*) root->get_right_sibling(); // advance to next tree
1050 SIBLING_LIST(to_delete)->del(); // remove from tree list
1051 destroy_tree(to_delete); // delete the tree
1052 }
1053 }
1054
1061 template <class Node>
1063 {
1064 if (root == nullptr)
1065 return 0;
1066
1067 size_t temp_h, max_h = 0;
1068 for (Node * aux = root->get_left_child(); aux != nullptr;
1069 aux = aux->get_right_sibling())
1070 if ((temp_h = compute_height(aux)) > max_h)
1071 max_h = temp_h;
1072
1073 return max_h + 1;
1074 }
1075
1076 template <class Node> static inline
1077 Node * __deway_search(Node * node, int path [],
1078 const int & idx, const size_t & size)
1079 {
1080 if (node == nullptr)
1081 return nullptr;
1082
1083 ah_out_of_range_error_if(static_cast<size_t>(idx) >= size)
1084 << "index out of maximum range";
1085
1086 if (path[idx] < 0) // check whether the node has been reached
1087 return node;
1088 // advance to the next child path[0]
1089 Node * child = node->get_left_child();
1090 for (int i = 0; i < path[idx] and child != nullptr; ++i)
1091 child = child->get_right_sibling();
1092
1093 return __deway_search(child, path, idx + 1, size); // next level
1094 }
1095
1109 template <class Node> inline
1110 Node * deway_search(Node * root, int path [], const size_t & size)
1111 {
1112 for (int i = 0; root != nullptr; i++, root = root->get_right_sibling())
1113 if (path[0] == i)
1114 return __deway_search(root, path, 1, size);
1115
1116 return nullptr;
1117 }
1118
1119 template <class Node, class Equal> inline static
1120 Node * __search_deway(Node * root, const typename Node::key_type & key,
1121 const size_t & current_level, int deway [],
1122 const size_t & size, size_t & n);
1123
1144 template <class Node,
1145 class Equal = Aleph::equal_to<typename Node::key_type> > inline
1146 Node * search_deway(Node * root, const typename Node::key_type & key,
1147 int deway [], const size_t & size, size_t & n)
1148 {
1149 n = 1; // initial length value of the Dewey number
1150
1151 ah_overflow_error_if(size < n) << "there is no enough space for deway array";
1152
1153 for (int i = 0; root != nullptr; i++, root = root->get_right_sibling())
1154 {
1155 deway[0] = i;
1156 Node * result =
1158 if (result != nullptr)
1159 return result;
1160 }
1161
1162 return nullptr;
1163 }
1164
1165 template <class Node, class Equal> inline static
1167 const typename Node::key_type & key,
1168 const size_t & current_level, int deway [],
1169 const size_t & size, size_t & n)
1170 {
1171
1172 ah_overflow_error_if(current_level >= size) << "there is no enough space for deway array";
1173
1174 if (root == nullptr)
1175 return nullptr;
1176
1177 if (Equal()(root->get_key(), key))
1178 {
1179 n = current_level + 1; // length of deway array
1180 return root;
1181 }
1182
1183 Node * child = root->get_left_child();
1184 for (int i = 0; child != nullptr;
1185 i++, child = child->get_right_sibling())
1186 {
1187 ah_overflow_error_if(current_level + 1 >= size)
1188 << "there is no enough space for deway array";
1189 deway[current_level + 1] = i;
1191 (child, key, current_level + 1, deway, size, n);
1192
1193 if (result!= nullptr)
1194 return result;
1195 }
1196
1197 return nullptr;
1198 }
1199
1218 template <class TNode, class BNode>
1220 {
1221 if (root == nullptr)
1222 return BNode::NullPtr;
1223
1224 auto * result = new BNode (root->get_key());
1225 LLINK(result) = static_cast<BNode *>(forest_to_bin<TNode, BNode>(root->get_left_child()));
1226 RLINK(result) = forest_to_bin<TNode, BNode>(root->get_right_sibling());
1227
1228 return result;
1229 }
1230
1231 template <class TNode, class BNode> inline static
1232 void insert_child(BNode * lnode, TNode * tree_node)
1233 {
1234 if (lnode == BNode::NullPtr)
1235 return;
1236
1237 auto * child = new TNode(KEY(lnode));
1238 tree_node->insert_leftmost_child(child);
1239 }
1240
1241 template <class TNode, class BNode> inline static
1242 void insert_sibling(BNode * rnode, TNode * tree_node)
1243 {
1244 if (rnode == BNode::NullPtr)
1245 return;
1246
1247 auto * sibling = new TNode(KEY(rnode));
1248 tree_node->insert_right_sibling(sibling);
1249 }
1250
1251 template <class TNode, class BNode> inline static
1253 {
1254 if (broot == BNode::NullPtr)
1255 return;
1256
1258 TNode * left_child = troot->get_left_child();
1259
1261
1263 TNode * right_sibling = troot->get_right_sibling();
1264
1266 }
1267
1285 template <class TNode, class BNode> inline
1287 {
1288 if (broot == BNode::NullPtr)
1289 return nullptr;
1290
1291 auto * troot = new TNode (KEY(broot));
1293 return troot;
1294 }
1295
1296} // end namespace Aleph
1297
1298# endif // TPL_TREE_H
1299
CRTP Mixins for container functionality (DRY principle).
Exception handling system with formatted messages for Aleph-w.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Definition ah-errors.H:579
#define ah_overflow_error_if(C)
Throws std::overflow_error if condition holds.
Definition ah-errors.H:463
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
#define ah_range_error_if(C)
Throws std::range_error if condition holds.
Definition ah-errors.H:207
DRY (Don't Repeat Yourself) utilities and macros.
Standard functor implementations and comparison objects.
Functional programming utilities for Aleph-w containers.
Iterator traits and STL-compatible iterator wrappers.
#define STL_ALEPH_ITERATOR(Set_Name)
Definition ahIterator.H:208
WeightedDigraph::Node Node
@ KEY
Definition btreepic.C:169
Dynamic queue of elements of generic type T based on single linked list.
T & put(const T &data)
The type of element.
T get()
Remove the oldest item of the queue.
bool is_empty() const noexcept
Return true if this is empty.
Dynamic stack of elements of generic type T based on a singly linked list.
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
CRTP Mixin providing functional programming operations.
Container< __Type > maps(Operation &operation) const
Transform elements using a mapping function.
Iterator that zips two other iterators.
Iterator over the children of this.
Children_Iterator(const Children_Iterator &it) noexcept
Children_Iterator(Tree_Node &p) noexcept
Children_Iterator(const Tree_Node &p) noexcept
Children_Iterator(Tree_Node *p) noexcept
Tree_Node * get_curr_ne() const noexcept
Iterator(const Iterator &it)
bool has_curr() const noexcept
Iterator(Iterator &&it) noexcept
Iterator & operator=(Iterator it)
void swap(Iterator &it) noexcept
DynListStack< Tree_Node * > s
size_t get_pos() const
Return the current position of iterator. Only valid if.
Iterator(Tree_Node *r=nullptr) noexcept
Tree_Node * get_curr() const
Tree_Node * get_curr_ne() const noexcept
Generic m-ary trees.
Tree_Node(const T &d)
Constructor with data value __data.
constexpr bool is_leftmost() const noexcept
Returns true if this is the leftmost node among its siblings.
bool traverse(Operation op)
Preorder traversal over all nodes executing op.
void set_is_root(bool value) noexcept
Dlink * get_sibling_list() noexcept
Tree_Node * left_link() const noexcept
Tree_Node * upper_link() const noexcept
static Tree_Node * sibling_to_Tree_Node(Dlink *link) noexcept
Tree_Node * join(Tree_Node *tree)
join tree as subtree of root this
Tree_Node * get_last_tree() const
Returns the rightmost tree of the forest containing this.
void insert_left_sibling(Tree_Node *p)
Inserts p as the left sibling of this.
Tree_Node * get_left_sibling() const noexcept
Returns the left sibling of this.
Tree_Node()=default
Empty constructor (undefined key).
constexpr const T & get_key() const noexcept
bool level_traverse(Op op) const
constexpr bool is_root() const noexcept
Returns true if this is the root of the general tree.
bool level_traverse(Op op)
T key_type
Generic data type stored in the node.
Tree_Node * get_left_child() const noexcept
Returns the leftmost child of this.
constexpr bool is_rightmost() const noexcept
Returns true if this is the rightmost node among its siblings.
Tree_Node * right_link() const noexcept
static bool preorder(const Tree_Node *root, Operation &op)
static Tree_Node * child_to_Tree_Node(Dlink *link) noexcept
Tree_Node * get_child(const size_t i) const noexcept
Returns the i-th child of this.
Container< Tree_Node * > trees() const
Return a list with all trees belonging to the forrest.
void insert_leftmost_child(Tree_Node *p) noexcept
Inserts p as the leftmost child of this.
constexpr bool is_leaf() const noexcept
Returns true if this is a leaf node.
T & get_data() noexcept
Returns a modifiable reference to the node contents.
Dlink * get_child_list() noexcept
Tree_Node * get_right_sibling() const noexcept
Returns the right sibling of this.
Tree_Node * get_left_tree() const noexcept
Returns the tree to the left of this.
void insert_rightmost_child(Tree_Node *p) noexcept
Inserts p as the rightmost child of this.
Tree_Node * lower_link() const noexcept
Children_Iterator children_it() const
Tree_Node * get_right_tree() const noexcept
Returns the tree to the right of this.
void insert_tree_to_right(Tree_Node *tree)
Insert tree to the right of this
constexpr const T & get_data() const noexcept
Tree_Node * get_parent() const noexcept
Returns the parent of this.
void set_is_leaf(bool value) noexcept
Container< Tree_Node * > children_nodes() const
Returns a list with the child nodes of this.
void for_each_child(Operation &op) const
Visits each child of this and executes the operation on the child node.
bool traverse(Operation op) const
Tree_Node * get_right_child() const noexcept
Returns the rightmost child of this.
void insert_right_sibling(Tree_Node *p) noexcept
Inserts p as the right sibling of this.
T & get_key() noexcept
Returns a modifiable reference to the node contents.
Iterator get_it() const
Container< T > children() const
Returns a list with the contents of the children of this.
void set_is_leftmost(bool value) noexcept
void for_each_child(Operation &&op=Operation()) const
void set_is_rightmost(bool value) noexcept
void deway(Tree_Node< int > *p, int prefix[], const int &len, const size_t &dim)
Recursively compute and print Deway numbering for a tree node.
Definition deway.C:117
__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
void forest_postorder_traversal(Node *root, void(*visitFct)(Node *, int, int))
Postorder traversal of a forest.
void destroy_tree(Node *root)
Destroys (frees memory) the tree whose root is root.
size_t compute_height(Node *root)
Computes the height of the tree root.
void tree_postorder_traversal(Node *root, void(*visitFct)(Node *, int, int))
Postorder traversal of a tree.
TNode * bin_to_forest(BNode *broot)
Converts a binary tree to its equivalent forest.
constexpr Node *& RLINK(Node *p) noexcept
Return the right tree of p.
bool are_tree_equal(Node *t1, Node *t2, Eq &eq)
Returns true if t1 is equal to t2.
void destroy_forest(Node *root)
Destroys (frees memory) the forest whose first tree is root.
void forest_preorder_traversal(Node *root, void(*visitFct)(Node *, int, int))
Preorder traversal of a forest.
constexpr Node *& LLINK(Node *p) noexcept
Return a pointer to left subtree.
void tree_preorder_traversal(Node *root, void(*visitFct)(Node *, int, int))
Preorder traversal of a tree.
Node * search_deway(Node *root, const typename Node::key_type &key, int deway[], const size_t &size, size_t &n)
Searches key in a forest and computes the Dewey number of the node containing the key.
Node * deway_search(Node *root, int path[], const size_t &size)
Returns a node of a forest given its Dewey number.
BNode * forest_to_bin(TNode *root)
Converts a forest to its equivalent binary tree.
Singly linked list implementations with head-tail access.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
static Node * __deway_search(Node *node, int path[], const int &idx, const size_t &size)
static void insert_sibling(BNode *rnode, TNode *tree_node)
bool all(Container &container, Operation &operation)
Return true if all elements satisfy a predicate.
bool eq(const C1 &c1, const C2 &c2, Eq e=Eq())
Check equality of two containers using a predicate.
static void insert_child(BNode *lnode, TNode *tree_node)
static Node * __search_deway(Node *root, const typename Node::key_type &key, const size_t &current_level, int deway[], const size_t &size, size_t &n)
DynList< std::pair< typename Container1::Item_Type, typename Container2::Item_Type > > zipEq(const Container1 &a, const Container2 &b)
Zip two containers; throw if lengths differ.
size_t size(Node *root) noexcept
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:107
static void clone_tree(Node *src, Node *tgt)
static void bin_to_tree(BNode *broot, TNode *troot)
static void __tree_postorder_traversal(Node *node, const int &level, const int &child_index, void(*visitFct)(Node *, int, int))
static void __tree_preorder_traversal(Node *root, const int &level, const int &child_index, void(*visitFct)(Node *, int, int))
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
Children_Set(const Tree_Node &)
Children_Set(const Tree_Node &&)
virtual ~Tree_Node_Vtl()=default
Basic binary tree node definitions.
Dynamic queue implementation based on linked lists.
Dynamic stack implementation based on linked lists.
#define SIBLING_LINK(p)
#define SIBLING_LIST(p)
#define ISROOT(p)
#define CHILD_LIST(p)
#define IS_UNIQUE_SIBLING(p)
#define ISLEFTMOST(p)