Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_binNodeUtils.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
43# ifndef TPL_BINNODEUTILS_H
44# define TPL_BINNODEUTILS_H
45
46# include <ahFunction.H>
47# include <tpl_arrayStack.H>
48# include <tpl_arrayQueue.H>
49# include <tpl_dynListQueue.H>
50# include <bitArray.H>
51# include <tpl_dynDlist.H>
52# include <tpl_binNode.H>
53# include <ah-errors.H>
54
55namespace Aleph
56{
57 template <class Node>
58 inline static
59 void inorder_rec_helper(Node *node, const int & level, int & position,
60 void (*visitFct)(Node *, int, int))
61 {
62 if (node == Node::NullPtr)
63 return;
64
65 inorder_rec_helper(LLINK(node), level + 1, position, visitFct);
66
67 (*visitFct)(node, level, position);
68 ++position;
69
70 inorder_rec_helper(RLINK(node), level + 1, position, visitFct);
71 }
72
95 template <class Node>
96 inline
97 int inOrderRec(Node *root, void (*visitFct)(Node *, int, int))
98 {
99 int position = 0;
100 inorder_rec_helper(root, 0, position, visitFct);
101 return position;
102 }
103
104 template <class Node>
105 inline static
106 void preorder_rec_helper(Node *p, const int & level, int & position,
107 void (*visitFct)(Node *, int, int))
108 {
109 if (p == Node::NullPtr)
110 return;
111
112 (*visitFct)(p, level, position);
113 ++position;
114
115 preorder_rec_helper(LLINK(p), level + 1, position, visitFct);
116 preorder_rec_helper(RLINK(p), level + 1, position, visitFct);
117 }
118
141 template <class Node>
142 inline
143 int preOrderRec(Node *root, void (*visitFct)(Node *, int, int))
144 {
145 int position = 0;
146 preorder_rec_helper(root, 0, position, visitFct);
147 return position;
148 }
149
150 template <class Node>
151 inline static
152 void postorder_rec_helper(Node *node, const int & level, int & position,
153 void (*visitFct)(Node *, int, int))
154 {
155 if (node == Node::NullPtr)
156 return;
157
158 postorder_rec_helper(LLINK(node), level + 1, position, visitFct);
159 postorder_rec_helper(RLINK(node), level + 1, position, visitFct);
160
161 (*visitFct)(node, level, position);
162 ++position;
163 }
164
187 template <class Node>
188 inline
189 int postOrderRec(Node *root, void (*visitFct)(Node *, int, int))
190 {
191 int position = 0;
192 postorder_rec_helper(root, 0, position, visitFct);
193 return position;
194 }
195
211 template <class Node>
213 {
214 template <class Op>
215 static void for_each_inorder(Node *root, Op && op)
216 {
217 if (root == Node::NullPtr)
218 return;
219
220 for_each_inorder(LLINK(root), std::forward<Op>(op));
221 op(root);
222 for_each_inorder(RLINK(root), std::forward<Op>(op));
223 }
224
225 public:
227 template <class Op>
228 void traverse(Node *root, Op && op) const
229 {
230 for_each_inorder(root, std::forward<Op>(op));
231 }
232
234 template <class Op>
235 void operator ()(Node *root, Op & op) const
236 {
238 }
239
241 template <class Op>
242 void operator ()(Node *root, Op && op) const
243 {
244 for_each_inorder(root, std::forward<Op>(op));
245 }
246 };
247
254 template <class Node, class Op>
255 inline
257 {
258 return For_Each_In_Order<Node>().traverse(root, std::forward<Op>(op));
259 }
260
277 template <class Node>
279 {
280 template <class Op>
281 static void preorder(Node *root, Op && op)
282 {
283 if (root == Node::NullPtr)
284 return;
285
286 op(root);
287 preorder(LLINK(root), std::forward<Op>(op));
288 preorder(RLINK(root), std::forward<Op>(op));
289 }
290
291 public:
293 template <class Op>
294 void traverse(Node *root, Op && op) const
295 {
296 return preorder(root, std::forward<Op>(op));
297 }
298
300 template <class Op>
301 void operator ()(Node *root, Op & op) const
302 {
303 preorder(root, op);
304 }
305
307 template <class Op>
308 void operator ()(Node *root, Op && op = Op()) const
309 {
310 preorder(root, std::forward<Op>(op));
311 }
312 };
313
320 template <class Node, class Op>
322 {
323 For_Each_Preorder<Node>().traverse(root, std::forward<Op>(op));
324 }
325
326
342 template <class Node>
344 {
345 template <class Op>
346 static void postorder(Node *root, Op && op)
347 {
348 if (root == Node::NullPtr)
349 return;
350
351 postorder(LLINK(root), std::forward<Op>(op));
352 postorder(RLINK(root), std::forward<Op>(op));
353 op(root);
354 }
355
356 public:
358 template <class Op>
359 void traverse(Node *root, Op && op) const
360 {
361 return postorder(root, std::forward<Op>(op));
362 }
363
365 template <class Op>
366 void operator ()(Node *root, Op & op) const
367 {
368 postorder(root, op);
369 }
370
372 template <class Op>
373 void operator ()(Node *root, Op && op = Op()) const
374 {
375 postorder(root, std::forward<Op>(op));
376 }
377 };
378
385 template <class Node, class Op>
387 {
388 For_Each_Postorder<Node>().traverse(root, std::forward<Op>(op));
389 }
390
391
392 template <class Node>
394 {
395 if (root == Node::NullPtr)
396 return;
397
398 acc.append(root);
399 prefix(LLINK(root), acc);
400 prefix(RLINK(root), acc);
401 }
402
403 template <class Node>
405 {
406 if (root == Node::NullPtr)
407 return;
408
409 infix(LLINK(root), acc);
410 acc.append(root);
411 infix(RLINK(root), acc);
412 }
413
414 template <class Node>
416 {
417 if (root == Node::NullPtr)
418 return;
419
420 suffix(LLINK(root), acc);
421 suffix(RLINK(root), acc);
422 acc.append(root);
423 }
424
432 template <class Node>
439
447 template <class Node>
454
462 template <class Node>
469
470
477 template <class Node>
478 inline
480 {
481 if (root == Node::NullPtr)
482 return 0;
483
484 return compute_cardinality_rec(LLINK(root)) + 1 +
486 }
487
489 template <class Node>
490 inline
491 size_t size(Node *root) noexcept
492 {
494 }
495
502 template <class Node>
503 inline size_t computeHeightRec(Node *root) noexcept
504 {
505 if (root == Node::NullPtr)
506 return 0;
507
508 const size_t left_height = computeHeightRec(LLINK(root));
509 const size_t right_height = computeHeightRec(RLINK(root));
510
511 return 1 + std::max(left_height, right_height);
512 }
513
522 template <class Node>
523 inline
524 void destroyRec(Node *& root) noexcept
525 {
526 if (root == Node::NullPtr)
527 return;
528
531 delete root;
532 root = Node::NullPtr;
533 }
534
547 template <class Node>
548 inline
550 {
551 if (root == Node::NullPtr)
552 return;
553
554 using Key = typename Node::key_type;
555
558 root->get_key().~Key();
559 root = Node::NullPtr;
560 }
561
569 template <class Node>
570 [[nodiscard]] inline
572 {
573 if (root == Node::NullPtr)
574 return Node::NullPtr;
575
576 Node *tgt_root = new Node(*root);
577
578 try
579 {
582 }
583 catch (...)
584 {
585 assert(RLINK(tgt_root) == Node::NullPtr);
586
587 if (LLINK(tgt_root) != Node::NullPtr)
588 destroyRec(LLINK(tgt_root)); // TODO: diff de Node*&
589
590 delete tgt_root;
591
592 throw;
593 }
594
595 return tgt_root;
596 }
597
608 template <class Node>
609 inline
610 bool areSimilar(Node *t1, Node *t2) noexcept
611 {
612 if (t1 == t2) // that include the case when t1 and t2 are the same
613 // or both are Node::NullPtr
614 return true;
615
616 if (t1 == Node::NullPtr or t2 == Node::NullPtr)
617 return false;
618
619 return areSimilar(LLINK(t1), LLINK(t2)) and
621 }
622
634 template <class Node, class Equal>
635 inline
636 bool areEquivalents(Node *t1, Node *t2, Equal & op) noexcept
637 {
638 if (t1 == t2)
639 return true;
640
641 if (t1 == Node::NullPtr or t2 == Node::NullPtr)
642 return false;
643
644 if (not op(KEY(t1), KEY(t2)))
645 return false;
646
647 return areEquivalents(LLINK(t1), LLINK(t2), op) and
649 }
650
652 template <class Node, class Equal = std::equal_to<typename Node::key_type>>
653 inline bool areEquivalents(Node *t1, Node *t2, Equal && op = Equal()) noexcept
654 {
655 return areEquivalents(t1, t2, op);
656 }
657
674 template <class Node>
675 inline
676 void levelOrder(Node *root, void (*visitFct)(Node *, int, bool))
677 {
678 if (root == Node::NullPtr)
679 return;
680
682 queue.put(std::pair<Node *, bool>(root, bool()));
683
684 for (int pos = 0; not queue.is_empty(); pos++)
685 {
686 std::pair<Node *, bool> pr = queue.get();
687 Node *& p = pr.first;
688
689 (*visitFct)(p, pos, pr.second);
690
691 if (LLINK(p) != Node::NullPtr)
692 queue.put(std::pair<Node *, bool>(LLINK(p), true));
693
694 if (RLINK(p) != Node::NullPtr)
695 queue.put(std::pair<Node *, bool>(RLINK(p), false));
696 }
697 }
698
699
715 template <class Node, class Operation>
716 inline
718 {
719 if (root == Node::NullPtr)
720 return true;
721
723 queue.put(root);
724 while (not queue.is_empty())
725 {
726 Node *p = queue.get();
727 if (not operation(p))
728 return false;
729
730 if (LLINK(p) != Node::NullPtr)
731 queue.put(LLINK(p));
732
733 if (RLINK(p) != Node::NullPtr)
734 queue.put(RLINK(p));
735 }
736 return true;
737 }
738
739 template <class Node, class Operation>
740 inline
745
761 template <template <class> class Node, typename Key>
762 inline
764 const DynArray<Key> & inorder, long l_i, long r_i)
765 {
766 if (l_p > r_p)
767 {
768 assert(l_i > r_i);
769 return Node<Key>::NullPtr;
770 }
771
772 assert(r_p - l_p == r_i - l_i);
773
774 auto *root = new Node<Key>(preorder[l_p]);
775 if (r_p == l_p)
776 return root;
777
778 assert(l_i <= r_i);
779
780 // Find root key position in inorder array
781 int i = -1;
782 for (int j = l_i; j <= r_i; ++j)
783 if (inorder[j] == preorder[l_p])
784 {
785 i = j - l_i;
786 break;
787 }
788
789 // Validate that root key was found in inorder array
790 ah_domain_error_if(i < 0)
791 << "build_tree: root key not found in inorder array (corrupted input)";
792
793 assert(i <= r_i - l_i);
794
796 inorder, l_i, l_i + (i - 1));
798 inorder, l_i + i + 1, r_i);
799 return root;
800 }
801
802 template <template <class> class Node, typename Key>
803 inline
805 const DynArray<Key> & in, long li, long ri)
806 {
807 assert(rp - lp == ri - li);
808 if (lp > rp)
809 return Node<Key>::NullPtr;
810
811 auto *root = new Node<Key>(post[rp]);
812
813 // Search in inorder array the index of root
814 int i = li;
815 for (; i <= ri; ++i)
816 if (in[i] == post[rp])
817 break;
818
819 // Validate that root key was found in inorder array
821 << "build_postorder: root key not found in inorder array (corrupted input)";
822
823 assert(i <= ri);
824
826 in, li, i - 1);
828 in, i + 1, ri);
829 return root;
830 }
831
832 template <class Node>
833 inline static void
834 compute_nodes_in_level_helper(Node *root, long level, const long current_level,
836 {
837 if (root == Node::NullPtr)
838 return;
839
840 if (current_level == level)
841 {
843 return; // it is not worth descending further
844 }
845
846 compute_nodes_in_level_helper(LLINK(root), level, current_level + 1, level_list);
847 compute_nodes_in_level_helper(RLINK(root), level, current_level + 1, level_list);
848 }
849
858 template <class Node>
859 inline
861 {
862 DynDlist<Node *> list;
863 compute_nodes_in_level_helper(root, level, 0, list);
864 return list;
865 }
866
887 template <class Node>
888 inline
890 {
891 if (root == Node::NullPtr)
892 return;
893
894 Node *p = root, *r = Node::NullPtr;
895 while (p != Node::NullPtr)
896 {
897 Node *q = LLINK(p);
898 if (q == Node::NullPtr)
899 { // No left branch ==> visit p
900 (*visitFct)(p);
901 r = p;
902 p = RLINK(p);
903 continue;
904 }
905
906 // Move towards the rightmost node of the left branch
907 while (q != r and RLINK(q) != Node::NullPtr)
908 q = RLINK(q);
909
910 if (q != r) // Does p have a predecessor?
911 { // yes ==> leave a thread in order to later come back and visit p
912 RLINK(q) = p; // place the thread here
913 p = LLINK(p); // keep descending on the left
914 continue;
915 }
916
917 (*visitFct)(p);
918
919 RLINK(q) = Node::NullPtr; // delete thread
920 r = p;
921 p = RLINK(p); // advance to the right branch
922 }
923 }
924
945 template <class Node>
946 inline
947 void preOrderThreaded(Node *node, void (*visitFct)(Node *))
948 {
949 if (node == Node::NullPtr)
950 return;
951
952 Node *p = node, *r = Node::NullPtr;
953 while (p != Node::NullPtr)
954 {
955 Node *q = LLINK(p);
956
957 if (q == Node::NullPtr)
958 {
959 (*visitFct)(p);
960 r = p;
961 p = RLINK(p);
962 continue;
963 }
964
965 // advance towards the rightmost node of the left branch
966 while (q != r and RLINK(q) != Node::NullPtr)
967 q = RLINK(q);
968
969 if (q != r)
970 {
971 RLINK(q) = p;
972 (*visitFct)(p);
973 p = LLINK(p);
974 continue;
975 }
976
977 RLINK(q) = Node::NullPtr; /* delete thread */
978 r = p;
979 p = RLINK(p); /* advance to right branch */
980 }
981 }
982
983 template <class Node>
984 inline static
985 size_t internal_path_length_helper(Node *p, const size_t & level) noexcept
986 {
987 if (p == Node::NullPtr)
988 return 0;
989
990 return level + internal_path_length_helper(LLINK(p), level + 1) +
991 internal_path_length_helper(RLINK(p), level + 1);
992 }
993
1001 template <class Node>
1002 inline
1003 size_t internal_path_length(Node *p) noexcept
1004 {
1005 return internal_path_length_helper(p, 0);
1006 }
1007
1021 template <class Node>
1022 inline
1024 {
1025 if (root == Node::NullPtr)
1026 {
1027 array.push(1);
1028 return;
1029 }
1030
1031 array.push(0);
1032 tree_to_bits(LLINK(root), array);
1033 tree_to_bits(RLINK(root), array);
1034 }
1035
1049 template <class Node>
1050 inline
1052 {
1055 return ret_val;
1056 }
1057
1065 template <class Node>
1066 inline std::string code(Node *root)
1067 {
1068 const BitArray bits = tree_to_bits(root);
1069 const size_t n = bits.size();
1070 std::string str;
1071 str.reserve(n);
1072 for (size_t i = 0; i < n; ++i)
1073 str.push_back(bits(i) ? 'b' : 'a');
1074
1075 return str;
1076 }
1077
1078 template <class Node>
1079 static inline
1080 Node * bits_to_tree_helper(const BitArray & array, int & i)
1081 {
1082 // Bounds check: ensure we don't read past the end of the bit array
1083 ah_domain_error_if(i >= static_cast<int>(array.size()))
1084 << "bits_to_tree_helper: bit array index out of bounds (malformed input)";
1085
1086 if (const int bit = array.read_bit(i++); bit == 1)
1087 return Node::NullPtr;
1088
1089 Node *p = new Node;
1090 Node *left = Node::NullPtr;
1091 Node *right = Node::NullPtr;
1092 try
1093 {
1094 left = bits_to_tree_helper<Node>(array, i);
1095 right = bits_to_tree_helper<Node>(array, i);
1096 }
1097 catch (...)
1098 {
1099 destroyRec(left);
1100 destroyRec(right);
1101 delete p;
1102 throw;
1103 }
1104
1105 LLINK(p) = left;
1106 RLINK(p) = right;
1107
1108 return p;
1109 }
1110
1124 template <class Node>
1125 inline
1126 Node * bits_to_tree(const BitArray & array, int idx = 0)
1127 {
1128 return bits_to_tree_helper<Node>(array, idx);
1129 }
1130
1148 template <class Node>
1149 inline
1151 {
1152 if (root == Node::NullPtr)
1153 return;
1154
1155 output << root->get_key() << " ";
1156
1159 }
1160
1171 template <class Node>
1172 inline
1174 {
1175 if (root == Node::NullPtr)
1176 return;
1177
1178 input >> root->get_key();
1179 ah_runtime_error_if(not input) << "load_tree_keys_in_prefix: input stream error";
1180
1183 }
1184
1185
1200 template <class Node>
1201 inline
1202 void save_tree(Node *root, std::ostream & output)
1203 {
1206 prefix.save(output);
1208 }
1209
1210
1222 template <class Node>
1223 inline
1224 Node * load_tree(std::istream & input)
1225 {
1227 prefix.load(input);
1229 try
1230 {
1232 }
1233 catch (...)
1234 {
1235 destroyRec(root); // Cleanup partially loaded tree on exception
1236 throw;
1237 }
1238 return root;
1239 }
1240
1241
1242 template <class Node, class Get_Key>
1243 inline
1244 void put_tree_keys_in_array(Node *root, std::ostream & out)
1245 {
1246 if (root == Node::NullPtr)
1247 return;
1248
1249 const std::string str = Get_Key()(root);
1250 out << "\"";
1251 for (const char ch : str)
1252 {
1253 switch (ch)
1254 {
1255 case '\n': out << "\\n"; break;
1256 case '\t': out << "\\t"; break;
1257 case '\\': out << "\\\\"; break;
1258 case '"': out << "\\\""; break;
1259 default: out << ch; break;
1260 }
1261 }
1262 out << "\", ";
1263
1266 }
1267
1268
1269 template <class Node, class Load_Key>
1270 inline
1271 void load_tree_keys_from_array(Node *root, const char *keys[], int & idx)
1272 {
1273 if (root == Node::NullPtr)
1274 return;
1275
1276 if (Load_Key()(root, keys[idx]))
1277 ++idx;
1278
1281 }
1282
1311 template <class Node, class Get_Key>
1312 inline
1314 const std::string & array_name,
1315 std::ostream & output)
1316 {
1319 prefix.save_in_array_of_chars(array_name + "_cdp", output);
1320 output << "const char * " << array_name << "_k[] = { " << '\n';
1322 output << "nullptr };" << '\n';
1323 }
1324
1325
1355 template <class Node, class Load_Key>
1356 inline
1357 Node * load_tree_from_array(const unsigned char bits[],
1358 const size_t & num_bits,
1359 const char *keys[])
1360 {
1362 prefix.load_from_array_of_chars(bits, num_bits);
1364 int i = 0;
1366 return root;
1367 }
1368
1369
1370 template <class Node, class Compare>
1371 static inline
1373 const typename Node::key_type *min_key,
1374 const typename Node::key_type *max_key,
1375 const Compare & cmp)
1376 {
1377 if (p == Node::NullPtr)
1378 return true;
1379
1380 const auto & key = KEY(p);
1381 if (min_key != nullptr and not less_or_equal_than(*min_key, key, cmp))
1382 return false;
1383 if (max_key != nullptr and not less_or_equal_than(key, *max_key, cmp))
1384 return false;
1385
1388 }
1389
1399 template <class Node,
1401 inline
1402 bool check_bst(Node *p, const Compare & cmp = Compare())
1403 {
1404 return check_bst_range<Node, Compare>(p, nullptr, nullptr, cmp);
1405 }
1406
1407
1419 template <class Node,
1421 inline Node *
1423 const Compare & cmp = Compare())
1424 {
1425 if (l > r)
1426 return Node::NullPtr;
1427
1428 Node *root = new Node(preorder[l]);
1429
1430 if (l == r)
1431 return root;
1432
1433 int first_greater = l + 1;
1435 ++first_greater;
1436
1438 first_greater - 1, cmp);
1440 cmp);
1441
1442 return root;
1443 }
1444
1446 enum ThreeWayCmp : int
1447 {
1448 CmpLess = -1,
1450 CmpGreater = 1
1452
1464 template <typename T, class Compare = Aleph::less<T>>
1465 inline ThreeWayCmp three_way_compare(const T & a, const T & b,
1466 const Compare & cmp = Compare()) noexcept
1467 {
1468 if (cmp(a, b))
1469 return CmpLess;
1470 if (cmp(b, a))
1471 return CmpGreater;
1472 return CmpEqual;
1473 }
1474
1489 template <class Node,
1491 [[nodiscard]] inline
1492 Node * searchInBinTree(Node *root, const typename Node::key_type & key,
1493 const Compare & cmp = Compare()) noexcept
1494 {
1495 Node *candidate = nullptr; // Tracks potential match when going right
1496
1497 while (root != Node::NullPtr)
1498 {
1499 const bool go_left = cmp(key, KEY(root)); // key < root ?
1500
1501 Node *next = go_left ? LLINK(root) : RLINK(root);
1502
1503 // Prefetch only the branch that follows (best for caching)
1504 if (next != Node::NullPtr)
1505 __builtin_prefetch(next, 0, 3);
1506
1507 if (not go_left)
1508 candidate = root;
1509 root = next;
1510 }
1511
1512 // Optimistic check: if candidate exists and key == candidate, return it
1513 if (candidate != nullptr and not cmp(KEY(candidate), key)) [[unlikely]]
1514 return candidate;
1515
1516 return Node::NullPtr;
1517 }
1518
1527 template <class Node>
1528 [[nodiscard]] inline
1529 Node * find_min(Node *root) noexcept
1530 {
1531 assert(root != Node::NullPtr && "find_min called on empty tree");
1532 while (LLINK(root) != Node::NullPtr)
1533 root = LLINK(root);
1534
1535 return root;
1536 }
1537
1546 template <class Node>
1547 [[nodiscard]] inline
1548 Node * find_max(Node *root) noexcept
1549 {
1550 assert(root != Node::NullPtr && "find_max called on empty tree");
1551 while (RLINK(root) != Node::NullPtr)
1552 root = RLINK(root);
1553
1554 return root;
1555 }
1556
1565 template <class Node>
1566 inline
1567 Node * find_successor(Node *p, Node *& pp) noexcept
1568 {
1569 assert(p != Node::NullPtr);
1570 assert(RLINK(p) != Node::NullPtr);
1571
1572 pp = p;
1573 p = RLINK(p);
1574 while (LLINK(p) != Node::NullPtr)
1575 {
1576 pp = p;
1577 p = LLINK(p);
1578 }
1579
1580 return p;
1581 }
1582
1591 template <class Node>
1592 inline
1593 Node * find_predecessor(Node *p, Node *& pp) noexcept
1594 {
1595 assert(p != Node::NullPtr);
1596 assert(LLINK(p) != Node::NullPtr);
1597
1598 pp = p;
1599 p = LLINK(p);
1600
1601 while (RLINK(p) != Node::NullPtr)
1602 {
1603 pp = p;
1604 p = RLINK(p);
1605 }
1606
1607 return p;
1608 }
1609
1622 template <class Node,
1624 inline
1625 Node * search_parent(Node *root, const typename Node::key_type & key,
1626 Node *& parent, const Compare & cmp = Compare()) noexcept
1627 {
1628 assert((LLINK(parent) == root) or (RLINK(parent) == root));
1629 assert(root != Node::NullPtr);
1630
1631 while (true)
1632 {
1633 const auto c = three_way_compare(key, KEY(root), cmp);
1634 if (c == CmpLess) [[likely]]
1635 {
1636 if (LLINK(root) == Node::NullPtr)
1637 return root;
1638
1639 parent = root;
1640 root = LLINK(root);
1641 }
1642 else if (c == CmpGreater) [[likely]]
1643 {
1644 if (RLINK(root) == Node::NullPtr)
1645 return root;
1646
1647 parent = root;
1648 root = RLINK(root);
1649 }
1650 else [[unlikely]]
1651 return root;
1652 }
1653 }
1654
1673 template <class Node,
1675 inline Node *
1676 search_rank_parent(Node *root, const typename Node::key_type & key,
1677 const Compare & cmp = Compare()) noexcept
1678 {
1679 assert(root != Node::NullPtr);
1680
1681 while (true)
1682 if (const auto & root_key = KEY(root); cmp(key, root_key))
1683 {
1684 if (LLINK(root) == Node::NullPtr)
1685 return root;
1686
1687 root = LLINK(root);
1688 }
1689 else if (cmp(root_key, key))
1690 {
1691 if (RLINK(root) == Node::NullPtr)
1692 return root;
1693
1694 root = RLINK(root);
1695 }
1696 else
1697 return root;
1698 }
1699
1712 template <class Node,
1714 inline
1715 Node * insert_in_bst(Node *& r, Node *p, const Compare & cmp = Compare()) noexcept
1716 {
1717 if (r == Node::NullPtr) [[unlikely]]
1718 return r = p;
1719
1720 const auto & pk = KEY(p);
1721 const auto & rk = KEY(r);
1722
1723 if (cmp(pk, rk))
1724 return insert_in_bst<Node, Compare>(LLINK(r), p, cmp);
1725 if (cmp(rk, pk))
1726 return insert_in_bst<Node, Compare>(RLINK(r), p, cmp);
1727
1728 [[unlikely]] return Node::NullPtr;
1729 }
1730
1743 template <class Node,
1745 inline
1746 Node * insert_dup_in_bst(Node *& root, Node *p, const Compare & cmp = Compare())
1747 noexcept
1748 {
1749 if (root == Node::NullPtr) [[unlikely]]
1750 return root = p;
1751
1752 const auto & pk = KEY(p);
1753 const auto & rk = KEY(root);
1754
1755 if (cmp(pk, rk))
1756 return insert_dup_in_bst(LLINK(root), p, cmp);
1757
1758 return insert_dup_in_bst(RLINK(root), p, cmp);
1759 }
1760
1775 template <class Node,
1777 inline
1778 Node * search_or_insert_in_bst(Node *& r, Node *p, const Compare & cmp = Compare())
1779 noexcept
1780 {
1781 if (r == Node::NullPtr) [[unlikely]]
1782 return r = p;
1783
1784 const auto & pk = KEY(p);
1785 const auto & rk = KEY(r);
1786
1787 if (cmp(pk, rk))
1789 if (cmp(rk, pk))
1791
1792 [[unlikely]] return r;
1793 }
1794
1795
1796 template <class Node, class Compare>
1797 static inline
1798 bool split_key_rec_helper(Node *root, const typename Node::key_type & key,
1799 Node *& ts, Node *& tg, Compare & cmp) noexcept
1800 {
1801 if (root == Node::NullPtr)
1802 { // key is not in the tree ==> split will succeed
1803 ts = tg = Node::NullPtr;
1804 return true;
1805 }
1806
1807 if (cmp(key, KEY(root)))
1808 {
1810 {
1811 tg = root;
1812 return true;
1813 }
1814 return false;
1815 }
1816
1817 if (cmp(KEY(root), key))
1819 {
1820 ts = root;
1821 return true;
1822 }
1823
1824 return false; // key exists in the tree
1825 }
1826
1827
1847 template <class Node,
1849 inline
1850 bool split_key_rec(Node *& root, const typename Node::key_type & key,
1851 Node *& ts, Node *& tg, const Compare & cmp = Compare()) noexcept
1852 {
1853 const bool ret = split_key_rec_helper(root, key, ts, tg, cmp);
1854 if (ret)
1855 root = Node::NullPtr;
1856 return ret;
1857 }
1858
1859
1860 template <class Node, class Compare>
1861 static inline
1862 void split_key_dup_rec_helper(Node *root, const typename Node::key_type & key,
1863 Node *& ts, Node *& tg, Compare & cmp) noexcept
1864 {
1865 if (root == Node::NullPtr)
1866 {
1867 ts = tg = Node::NullPtr;
1868 return;
1869 }
1870
1871 if (cmp(KEY(root), key))
1872 {
1874 ts = root;
1875 }
1876 else
1877 {
1879 tg = root;
1880 }
1881 }
1882
1883
1898 template <class Node,
1900 inline
1901 void split_key_dup_rec(Node *& root, const typename Node::key_type & key,
1902 Node *& ts, Node *& tg, const Compare & cmp = Compare()) noexcept
1903 {
1905 root = Node::NullPtr;
1906 }
1907
1908
1922 template <class Node>
1923 inline
1924 Node * join_exclusive(Node *& ts, Node *& tg) noexcept
1925 {
1926 if (ts == Node::NullPtr)
1927 return tg;
1928
1929 if (tg == Node::NullPtr)
1930 return ts;
1931
1933
1934 RLINK(ts) = tg;
1935 Node *ret_val = ts;
1936 ts = tg = Node::NullPtr; // empty the trees
1937
1938 return ret_val;
1939 }
1940
1952 template <class Node,
1954 inline
1955 Node * remove_from_bst(Node *& root, const typename Node::key_type & key,
1956 const Compare & cmp = Compare()) noexcept
1957 {
1958 if (root == Node::NullPtr)
1959 return Node::NullPtr;
1960
1961 if (cmp(key, KEY(root)))
1962 return remove_from_bst(LLINK(root), key, cmp);
1963 if (cmp(KEY(root), key))
1964 return remove_from_bst(RLINK(root), key, cmp);
1965
1966 Node *ret_val = root; // save root that is going to be removed
1968
1969 ret_val->reset();
1970
1971 return ret_val;
1972 }
1973
1988 template <class Node,
1990 inline
1991 Node * insert_root(Node *& root, Node *p, const Compare & cmp = Compare()) noexcept
1992 {
1993 Node *l = Node::NullPtr, *r = Node::NullPtr;
1994
1995 if (not split_key_rec(root, KEY(p), l, r, cmp))
1996 return Node::NullPtr;
1997
1998 LLINK(p) = l;
1999 RLINK(p) = r;
2000 root = p;
2001
2002 return root;
2003 }
2004
2015 template <class Node,
2017 inline
2018 Node * insert_dup_root(Node *& root, Node *p, const Compare & cmp = Compare()) noexcept
2019 {
2020 split_key_dup_rec(root, KEY(p), LLINK(p), RLINK(p), cmp);
2021 return root = p;
2022 }
2023
2024
2038 template <class Node,
2040 inline
2042 const Compare & cmp = Compare()) noexcept
2043 {
2044 if (t2 == Node::NullPtr)
2045 return t1;
2046
2047 Node *l = LLINK(t2);
2048 Node *r = RLINK(t2);
2049
2050 t2->reset();
2051
2052 if (insert_in_bst(t1, t2, cmp) == Node::NullPtr)
2053 insert_in_bst(dup, t2, cmp); // insertion has failed
2054
2055 join_preorder(t1, l, dup, cmp);
2056 join_preorder(t1, r, dup, cmp);
2057
2058 return t1;
2059 }
2060
2075 template <class Node,
2077 inline
2078 Node * join(Node *t1, Node *t2, Node *& dup, const Compare & cmp = Compare())
2079 noexcept
2080 {
2081 if (t1 == Node::NullPtr)
2082 return t2;
2083
2084 if (t2 == Node::NullPtr)
2085 return t1;
2086
2087 Node *l = LLINK(t1);
2088 Node *r = RLINK(t1);
2089
2090 t1->reset();
2091
2092 while (t1 != Node::NullPtr and insert_root(t2, t1, cmp) == Node::NullPtr)
2093 {
2094 Node *p = remove_from_bst(t1, KEY(t1), cmp);
2095
2096 assert(p != Node::NullPtr);
2097
2098 insert_in_bst(dup, p, cmp);
2099 }
2100
2101 LLINK(t2) = join(l, LLINK(t2), dup, cmp);
2102 RLINK(t2) = join(r, RLINK(t2), dup, cmp);
2103
2104 return t2;
2105 }
2106
2112 template <class Node>
2113 inline
2115 {
2116 assert(p != Node::NullPtr);
2117
2118 Node *q = LLINK(p);
2119 LLINK(p) = RLINK(q);
2120 RLINK(q) = p;
2121
2122 return q;
2123 }
2124
2132 template <class Node>
2133 inline
2135 {
2136 assert(p != Node::NullPtr);
2137 assert(pp != Node::NullPtr);
2138 assert(LLINK(pp) == p or RLINK(pp) == p);
2139
2140 Node *q = LLINK(p);
2141 LLINK(p) = RLINK(q);
2142 RLINK(q) = p;
2143
2144 if (LLINK(pp) == p) // update the parent
2145 LLINK(pp) = q;
2146 else
2147 RLINK(pp) = q;
2148
2149 return q;
2150 }
2151
2157 template <class Node>
2158 inline
2159 Node * rotate_to_left(Node *p) noexcept
2160 {
2161 assert(p != Node::NullPtr);
2162
2163 Node *q = RLINK(p);
2164 RLINK(p) = LLINK(q);
2165 LLINK(q) = p;
2166
2167 return q;
2168 }
2169
2176 template <class Node>
2177 inline
2178 Node * rotate_to_left(Node *p, Node *pp) noexcept
2179 {
2180 assert(p != Node::NullPtr);
2181 assert(pp != Node::NullPtr);
2182 assert(LLINK(pp) == p or RLINK(pp) == p);
2183
2184 Node *q = RLINK(p);
2185 RLINK(p) = LLINK(q);
2186 LLINK(q) = p;
2187
2188 // update the parent
2189 if (LLINK(pp) == p)
2190 LLINK(pp) = q;
2191 else
2192 RLINK(pp) = q;
2193
2194 return q;
2195 }
2196
2211 template <class Node, class Key,
2213 inline
2214 void split_key(Node *& root, const Key & key, Node *& l, Node *& r,
2215 const Compare & cmp = Compare()) noexcept
2216 {
2217 assert(l == Node::NullPtr and r == Node::NullPtr);
2218 if (root == Node::NullPtr)
2219 {
2220 l = r = Node::NullPtr;
2221 return;
2222 }
2223
2224 Node **current_parent = nullptr;
2225 Node **pending_child = nullptr;
2226 bool current_is_right = true;
2227 if (cmp(key, KEY(root)))
2228 {
2229 r = root;
2230 pending_child = &l;
2231 }
2232 else
2233 {
2234 l = root;
2235 pending_child = &r;
2236 current_is_right = false;
2237 }
2238
2239 Node *current = root;
2240 while (current != Node::NullPtr)
2241 {
2242 if (cmp(key, KEY(current)))
2243 { /* current must be in right side */
2245 {
2247 *pending_child = *current_parent; /* change of side */
2249 }
2250 current_parent = &LLINK(current);
2251 }
2252 else
2253 { /* current must be in left side */
2254 if (current_is_right)
2255 {
2257 *pending_child = *current_parent; /* change of side */
2259 }
2260 current_parent = &RLINK(current);
2261 }
2262 current = *current_parent;
2263 }
2264 *pending_child = Node::NullPtr;
2265 root = Node::NullPtr;
2266 }
2267
2277 template <class Node>
2278 inline
2279 void swap_node_with_successor(Node *p, // Node for swapping
2280 Node *& pp, // parent of p
2281 Node *q, // Successor inorder of p
2282 Node *& pq) // parent of q
2283 noexcept
2284 {
2285 assert(p != Node::NullPtr and q != Node::NullPtr and
2286 pp != Node::NullPtr and pq != Node::NullPtr);
2287 assert(LLINK(pp) == p or RLINK(pp) == p);
2288 assert(LLINK(pq) == q or RLINK(pq) == q);
2289 assert(LLINK(q) == Node::NullPtr);
2290
2291 /* Set of pp to its new son q */
2292 if (LLINK(pp) == p)
2293 LLINK(pp) = q;
2294 else
2295 RLINK(pp) = q;
2296
2297 LLINK(q) = LLINK(p);
2298 LLINK(p) = Node::NullPtr;
2299
2300 /* Checks if successor is right child of p. In this case, p will
2301 become q's son. This situation happens when p's son does not have
2302 a left branch */
2303 if (RLINK(p) == q)
2304 {
2305 RLINK(p) = RLINK(q);
2306 RLINK(q) = p;
2307 pq = pp;
2308 pp = q;
2309 return;
2310 }
2311
2312 /* In this case, successor is the leftmost node descending from
2313 right son of p */
2314 Node *qr = RLINK(q);
2315 RLINK(q) = RLINK(p);
2316 LLINK(pq) = p;
2317 RLINK(p) = qr;
2318
2319 std::swap(pp, pq);
2320 }
2321
2331 template <class Node>
2332 inline
2333 void swap_node_with_predecessor(Node *p, // Node for swapping
2334 Node *& pp, // p's parent
2335 Node *q, // Predecessor inorder of p
2336 Node *& pq) // q's parent
2337 noexcept
2338 {
2339 assert((p != Node::NullPtr) and (q != Node::NullPtr) and
2340 (pp != Node::NullPtr) and (pq != Node::NullPtr));
2341 assert((RLINK(pp) == p) or (LLINK(pp) == p));
2342 assert((RLINK(pq) == q) or (LLINK(pq) == q));
2343 assert(RLINK(q) == Node::NullPtr);
2344
2345 /* Set of pp to its new son q */
2346 if (RLINK(pp) == p)
2347 RLINK(pp) = q;
2348 else
2349 LLINK(pp) = q;
2350
2351 RLINK(q) = RLINK(p);
2352 RLINK(p) = Node::NullPtr;
2353
2354 /* Checks if predecessor is left child of p. In this case, p will
2355 become q's son. This situation happens when p's son does not have
2356 a right branch */
2357 if (LLINK(p) == q)
2358 {
2359 LLINK(p) = LLINK(q);
2360 LLINK(q) = p;
2361 pq = pp;
2362 pp = q;
2363 return;
2364 }
2365
2366 /* In this case, predecessor is the rightmost node descending from
2367 right son of p */
2368 Node *ql = LLINK(q);
2369 LLINK(q) = LLINK(p);
2370 RLINK(pq) = p;
2371 LLINK(p) = ql;
2372 std::swap(pp, pq);
2373 }
2374
2388 template <class Node, class Key = typename Node::key_type,
2390 inline
2392 const Compare & cmp = Compare()) noexcept
2393 {
2394 if (root == Node::NullPtr)
2395 return p; /* insertion in an empty tree */
2396
2397 if (cmp(KEY(p), KEY(root)))
2398 { /* insert in the left subtree */
2400 if (left_branch == Node::NullPtr)
2401 return Node::NullPtr;
2402
2405 }
2406 else if (cmp(KEY(root), KEY(p)))
2407 { /* insert in the right subtree */
2409 if (right_branch == Node::NullPtr)
2410 return Node::NullPtr;
2411
2414 }
2415 else
2416 return Node::NullPtr; /* duplicated key */
2417
2418 return root;
2419 }
2420
2431 template <class Node, class Key = typename Node::key_type,
2433 inline
2435 const Compare & cmp = Compare()) noexcept
2436 {
2437 if (root == Node::NullPtr)
2438 return p; // insertion in empty tree
2439
2440 if (cmp(KEY(p), KEY(root)))
2441 { // insert in left subtree
2443 if (left_branch == p)
2444 {
2447 return p;
2448 }
2449
2450 return left_branch;
2451 }
2452 if (cmp(KEY(root), KEY(p)))
2453 { // insert in right subtree
2455 if (right_branch == p)
2456 {
2459 return p;
2460 }
2461
2462 return right_branch;
2463 }
2464
2465 return root;
2466 }
2467
2468
2476 template <class Node>
2478 {
2479 Node *root = nullptr;
2480 Node *curr = Node::NullPtr;
2482
2483 public:
2485 void swap(BinNodePrefixIterator & it) noexcept
2486 {
2487 std::swap(root, it.root);
2488 std::swap(curr, it.curr);
2489 s.swap(it.s);
2490 }
2491
2493
2497 : root(r), curr(root), s(Node::MaxHeight)
2498 {
2499 // empty
2500 }
2501
2503 : root(it.root), curr(it.curr), s(it.s)
2504 {
2505 // empty
2506 }
2507
2509 {
2510 swap(it);
2511 }
2512
2515 {
2516 curr = root;
2517 s.empty();
2518 }
2519
2520 private:
2521 // Helper function for finding last node
2522 static Node * last(Node *p) noexcept
2523 {
2524 if (RLINK(p) != Node::NullPtr)
2525 return last(RLINK(p));
2526
2527 if (LLINK(p) != Node::NullPtr)
2528 return last(LLINK(p));
2529
2530 return p;
2531 }
2532
2533 public:
2536 {
2537 s.empty();
2538 if (root == Node::NullPtr)
2539 {
2540 curr = Node::NullPtr;
2541 return;
2542 }
2543
2544 curr = last(root);
2545 }
2546
2549 {
2550 curr = Node::NullPtr;
2551 s.empty();
2552 }
2553
2555 {
2556 if (this == &it)
2557 return *this;
2558
2559 root = it.root;
2560 curr = it.curr;
2561 s = it.s;
2562 return *this;
2563 }
2564
2566 {
2567 swap(it);
2568 return *this;
2569 }
2570
2572 [[nodiscard]] bool has_curr() const noexcept { return curr != Node::NullPtr; }
2573
2576
2578 Node * get_curr() const
2579 {
2580 ah_overflow_error_if(not has_curr()) << "Iterator overflow";
2581 return get_curr_ne();
2582 }
2583
2587 {
2588 auto l = LLINK(curr), r = RLINK(curr);
2589 if (l != Node::NullPtr)
2590 {
2591 curr = l;
2592 if (r != Node::NullPtr)
2593 s.push(r);
2594 return;
2595 }
2596
2597 if (r != Node::NullPtr)
2598 {
2599 curr = r;
2600 return;
2601 }
2602
2603 if (s.is_empty())
2604 curr = Node::NullPtr;
2605 else
2606 curr = s.pop();
2607 }
2608
2610 void next()
2611 {
2612 ah_overflow_error_if(not has_curr()) << "Iterator overflow";
2613 next_ne();
2614 }
2615 };
2616
2640 template <class Node, class Op>
2642 {
2643 for (BinNodePrefixIterator<Node> it(root); it.has_curr(); it.next_ne())
2644 if (not op(it.get_curr()))
2645 return false;
2646 return true;
2647 }
2648
2649
2668 template <class Node, class Op>
2670 {
2671 for (BinNodePrefixIterator<Node> it(root); it.has_curr(); it.next_ne())
2672 op(it.get_curr());
2673 }
2674
2675
2683 template <class Node>
2685 {
2686 mutable Node *root = Node::NullPtr;
2687 Node *curr = Node::NullPtr;
2688 long pos = 0;
2690
2691 Node * advance_to_min(Node *r) noexcept
2692 {
2693 while (LLINK(r) != Node::NullPtr)
2694 {
2695 s.push(r);
2696 r = LLINK(r);
2697 }
2698 return r;
2699 }
2700
2701 static Node * advance_to_max(Node *r) noexcept
2702 {
2703 while (RLINK(r) != Node::NullPtr)
2704 r = RLINK(r);
2705
2706 return r;
2707 }
2708
2710 {
2711 if (root != Node::NullPtr)
2713 pos = 0;
2714 }
2715
2716 public:
2719 {
2720 return curr != Node::NullPtr and LLINK(curr) == Node::NullPtr and s.is_empty();
2721 }
2722
2724 {
2725 return curr != Node::NullPtr and RLINK(curr) == Node::NullPtr and s.is_empty();
2726 }
2727
2728 void swap(BinNodeInfixIterator & it) noexcept
2729 {
2730 std::swap(root, it.root);
2731 std::swap(curr, it.curr);
2732 std::swap(pos, it.pos);
2733 s.swap(it.s);
2734 }
2735
2737
2740 : root(r), s(Node::MaxHeight)
2741 {
2742 init();
2743 }
2744
2746 : root(it.root), curr(it.curr), pos(it.pos), s(it.s)
2747 {
2748 // empty
2749 }
2750
2752
2755 {
2756 s.empty();
2757 init();
2758 }
2759
2762 {
2763 s.empty();
2764 if (root == Node::NullPtr)
2765 {
2766 curr = Node::NullPtr;
2767 pos = 0;
2768 return;
2769 }
2770
2772 pos = static_cast<long>(size(root)) - 1;
2773 }
2774
2776 {
2777 s.empty();
2778 curr = Node::NullPtr;
2779 pos = 0;
2780 }
2781
2783 {
2784 if (this == &it)
2785 return *this;
2786
2787 root = it.root;
2788 curr = it.curr;
2789 pos = it.pos;
2790 s = it.s;
2791 return *this;
2792 }
2793
2795 noexcept
2796 {
2797 swap(it);
2798 return *this;
2799 }
2800
2802 bool has_curr() const noexcept { return curr != Node::NullPtr; }
2803
2806
2808 Node * get_curr() const
2809 {
2810 ah_overflow_error_if(not has_curr()) << "Iterator overflow";
2811 return curr;
2812 }
2813
2815 size_t get_pos() const { return pos; }
2816
2818 {
2819 ++pos;
2820 curr = RLINK(curr);
2821 if (curr != Node::NullPtr)
2822 {
2824 return;
2825 }
2826
2827 if (s.is_empty())
2828 curr = Node::NullPtr;
2829 else
2830 curr = s.pop();
2831 }
2832
2835 void next()
2836 {
2837 ah_overflow_error_if(not has_curr()) << "Iterator overflow";
2838 next_ne();
2839 }
2840 };
2841
2865 template <class Node, class Op>
2867 {
2868 for (BinNodeInfixIterator<Node> it(root); it.has_curr(); it.next_ne())
2869 if (not op(it.get_curr()))
2870 return false;
2871 return true;
2872 }
2873
2878 template <class Node, class Op>
2880 {
2881 return infix_traverse(root, op);
2882 }
2883
2902 template <class Node, class Op>
2904 {
2905 for (BinNodeInfixIterator<Node> it(root); it.has_curr(); it.next_ne())
2906 op(it.get_curr());
2907 }
2908} // end Aleph
2909
2910# endif // TPL_BINNODEUTILS_H
Exception handling system with formatted messages for Aleph-w.
#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_runtime_error_if(C)
Throws std::runtime_error if condition holds.
Definition ah-errors.H:266
Standard functor implementations and comparison objects.
WeightedDigraph::Node Node
Space-efficient bit array implementation.
@ KEY
Definition btreepic.C:169
EepicNode< long > * build_tree()
Definition btreepic.C:1435
Stack implemented with simple dynamic array and with bounds verification.
void swap(ArrayStack &s) noexcept
Swap this with s
void empty() noexcept
Empty the stack.
bool is_empty() const noexcept
Return true if stack is empty.
T pop()
Extract the last more recently inserted element.
T & push(const T &data)
Push into stack a copy of data
Inorder iterator on the nodes of a binary tree.
Node * get_curr_ne() const noexcept
Return the current link guaranteeing no exception. Be careful.
void next()
Move the iterator one position forward.
void reset_last() noexcept
Reset the iterator to the first node inorder.
Node * get_curr() const
Return the current node. Throw overflow_error if there is no current.
BinNodeInfixIterator(const BinNodeInfixIterator &it)
bool is_last() const noexcept
bool has_curr() const noexcept
Return true the iterator has current node.
BinNodeInfixIterator(Node *r) noexcept
Initialize an iterator on the first node inorder.
bool is_in_first() const noexcept
Return true if the iterator is on the first node.
BinNodeInfixIterator(BinNodeInfixIterator &&it) noexcept
BinNodeInfixIterator & operator=(const BinNodeInfixIterator &it)
Node * advance_to_min(Node *r) noexcept
static Node * advance_to_max(Node *r) noexcept
size_t get_pos() const
Return the current position of iterator. Only valid if has_curr() == true.
void swap(BinNodeInfixIterator &it) noexcept
void reset_first() noexcept
Reset the iterator to the first node inorder.
Preorder iterator on the nodes of a binary tree.
void next_ne() noexcept
Move the iterator one position forward guaranteeing no exception.
Node * get_curr_ne() const noexcept
Return the current link guaranteeing no exception. Be careful.
bool has_curr() const noexcept
Return true if iterator has current node.
BinNodePrefixIterator(BinNodePrefixIterator &&it) noexcept
Node * get_curr() const
Return a pointer to current node.
void reset_first() noexcept
Reset the iterator to the first node in preorder sense.
void reset_last() noexcept
Reset the iterator to the last node in preorder.
BinNodePrefixIterator(Node *r) noexcept
Initialize an iterator on the first node in preorder for the tree with root r
void next()
Move the iterator one position forward.
void swap(BinNodePrefixIterator &it) noexcept
Swap thiswith it
BinNodePrefixIterator & operator=(const BinNodePrefixIterator &it)
void end() noexcept
Put the iterator in end state.
BinNodePrefixIterator(const BinNodePrefixIterator &it)
static Node * last(Node *p) noexcept
Contiguous array of bits.
Definition bitArray.H:189
int read_bit(const size_t i) const
Read bit i.
Definition bitArray.H:377
void load_from_array_of_chars(const unsigned char str[], const size_t num_bits)
Reads an array of bits saved in a character array.
Definition bitArray.H:687
void load(std::istream &input)
Loads an array of bits from a file.
Definition bitArray.H:590
void push(const unsigned int value)
Inserts the value at the end of the array.
Definition bitArray.H:450
constexpr size_t size() const noexcept
Returns the dimension of the bit array.
Definition bitArray.H:334
Dynamic doubly linked list with O(1) size and bidirectional access.
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 singly linked list with functional programming support.
Definition htlist.H:1423
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
Generic inorder traversal of a binary tree.
void traverse(Node *root, Op &&op) const
Invoke to traversal from root node.
static void for_each_inorder(Node *root, Op &&op)
void operator()(Node *root, Op &op) const
Generic postorder traversal of a binary tree.
void operator()(Node *root, Op &op) const
static void postorder(Node *root, Op &&op)
void traverse(Node *root, Op &&op) const
Invoke the traversal.
Generic preorder traversal of a binary tree.
static void preorder(Node *root, Op &&op)
void traverse(Node *root, Op &&op) const
Invoke the traversal.
void operator()(Node *root, Op &op) const
void reset() noexcept
Definition htlist.H:516
__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
bool prefix_traverse(Node *root, Op op)
Traverse a tree in preorder via its iterator and performs a conditioned operation on each item.
int postOrderRec(Node *root, void(*visitFct)(Node *, int, int))
Traverse recursively in postorder a binary tree.
size_t compute_cardinality_rec(Node *root) noexcept
Count the number of nodes of a binary tree.
Node * rotate_to_left(Node *p) noexcept
Rotate to the left the tree with root p
int preOrderRec(Node *root, void(*visitFct)(Node *, int, int))
Traverse recursively in preorder a binary tree.
void save_tree_in_array_of_chars(Node *root, const std::string &array_name, std::ostream &output)
Generate C++ array declarations for a binary tree.
Node * search_rank_parent(Node *root, const typename Node::key_type &key, const Compare &cmp=Compare()) noexcept
Rank search of a key in a binary search tree.
void save_tree_keys_in_prefix(Node *root, std::ostream &output)
Store in output stream the tree keys in preorder.
void load_tree_keys_in_prefix(Node *root, std::istream &input)
Load the keys stored in preorder from an input stream.
bool level_traverse(Node *root, Operation &operation)
Level traverse a tree and execute an operation.
DynDlist< Node * > compute_nodes_in_level(Node *root, const int &level)
Count the number of nodes in a specific tree level.
Node * join_preorder(Node *t1, Node *t2, Node *&dup, const Compare &cmp=Compare()) noexcept
Union of two binary search trees.
void swap_node_with_successor(Node *p, Node *&pp, Node *q, Node *&pq) noexcept
Swap a node with its successor inorder.
Node * remove_from_bst(Node *&root, const typename Node::key_type &key, const Compare &cmp=Compare()) noexcept
Remove a key from a binary search tree.
void for_each_in_order(Node *root, Op &&op)
Execute an operation in order sense for each node of tree.
Node * find_predecessor(Node *p, Node *&pp) noexcept
Find the inorder predecessor of p
Node * load_tree_from_array(const unsigned char bits[], const size_t &num_bits, const char *keys[])
Build a binary tree from two arrays.
Node * search_parent(Node *root, const typename Node::key_type &key, Node *&parent, const Compare &cmp=Compare()) noexcept
Search a key and find its node and parent.
Node * find_min(Node *root) noexcept
Return the minimum key contained in a binary search tree.
Node * rotate_to_right(Node *p) noexcept
Rotate to the right the tree with root p
bool split_key_rec(Node *&root, const typename Node::key_type &key, Node *&ts, Node *&tg, const Compare &cmp=Compare()) noexcept
Split recursively according to a key.
Node * find_successor(Node *p, Node *&pp) noexcept
Find the inorder successor of p
Node * copyRec(Node *root)
Copy recursively a tree.
void for_each_postorder(Node *root, Op &&op)
Execute an operation in postorder sense for each node of tree.
Node * load_tree(std::istream &input)
Load and build a binary tree from a stream.
void for_each_preorder(Node *root, Op &&op)
Execute an operation in preorder sense for each node of tree.
Node * search_or_insert_in_bst(Node *&r, Node *p, const Compare &cmp=Compare()) noexcept
Search or insert a node in a binary search tree.
void save_tree(Node *root, std::ostream &output)
Store a binary tree in a stream.
void split_key_dup_rec(Node *&root, const typename Node::key_type &key, Node *&ts, Node *&tg, const Compare &cmp=Compare()) noexcept
Split a tree according to a key value.
ThreeWayCmp three_way_compare(const T &a, const T &b, const Compare &cmp=Compare()) noexcept
Three-way comparison using a binary comparator.
bool check_bst(Node *p, const Compare &cmp=Compare())
Return true if p is a binary search tree.
constexpr Node *& RLINK(Node *p) noexcept
Return the right tree of p.
Node * bits_to_tree(const BitArray &array, int idx=0)
Build a binary tree given its bits code.
Node * insert_in_bst(Node *&r, Node *p, const Compare &cmp=Compare()) noexcept
Insert a node p in a binary search tree.
void tree_to_bits(Node *root, BitArray &array)
Compute a bit code for the binary tree.
size_t internal_path_length(Node *p) noexcept
Compute the internal path length.
void preOrderThreaded(Node *node, void(*visitFct)(Node *))
Traverse preorder a binary tree without recursion and without stack.
void inOrderThreaded(Node *root, void(*visitFct)(Node *))
Traverse inorder a binary tree without recursion and without stack.
Node * preorder_to_bst(DynArray< typename Node::key_type > &preorder, int l, int r, const Compare &cmp=Compare())
Build a binary search tree from its preorder traversal.
void levelOrder(Node *root, void(*visitFct)(Node *, int, bool))
Traverse a binary tree by levels.
int inOrderRec(Node *root, void(*visitFct)(Node *, int, int))
Traverse recursively inorder a binary tree.
Node * join_exclusive(Node *&ts, Node *&tg) noexcept
Exclusive join of two binary trees.
void destroyRec(Node *&root) noexcept
Free recursively all the memory occupied by the tree root
Node * searchInBinTree(Node *root, const typename Node::key_type &key, const Compare &cmp=Compare()) noexcept
Search a key in a binary search tree.
Node * search_or_insert_root_rec(Node *root, Node *p, const Compare &cmp=Compare()) noexcept
Search and eventually insert p as root in a binary search tree.
Node * insert_dup_in_bst(Node *&root, Node *p, const Compare &cmp=Compare()) noexcept
Insert a node p in a binary search tree.
Node * insert_root(Node *&root, Node *p, const Compare &cmp=Compare()) noexcept
Insert the node p as root of a binary search tree.
Node * insert_dup_root(Node *&root, Node *p, const Compare &cmp=Compare()) noexcept
Insert node p as root of a binary search tree.
void swap_node_with_predecessor(Node *p, Node *&pp, Node *q, Node *&pq) noexcept
Swap a node with its predecessor inorder.
constexpr Node *& LLINK(Node *p) noexcept
Return a pointer to left subtree.
Node * insert_root_rec(Node *root, Node *p, const Compare &cmp=Compare()) noexcept
Insert a node as root in a binary search tree.
bool infix_traverse(Node *root, Op op)
Traverse a tree in inorder via its iterator and performs a conditioned operation on each item.
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.
void split_key(Node *&root, const Key &key, Node *&l, Node *&r, const Compare &cmp=Compare()) noexcept
Split a binary search tree according to a key.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
size_t size(Node *root) noexcept
static Node * bits_to_tree_helper(const BitArray &array, int &i)
static void infix(Node *root, DynList< Node * > &acc)
bool traverse(Node *root, Op op)
static void suffix(Node *root, DynList< Node * > &acc)
void infix_for_each(Node *root, Op op)
Traverse all the container and performs an operation on each element.
void load_tree_keys_from_array(Node *root, const char *keys[], int &idx)
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:107
std::string code(Node *root)
Compute a string with the Lukasiewicz`s word of a tree.
static void prefix(Node *root, DynList< Node * > &acc)
static void compute_nodes_in_level_helper(Node *root, long level, const long current_level, DynDlist< Node * > &level_list)
static void postorder_rec_helper(Node *node, const int &level, int &position, void(*visitFct)(Node *, int, int))
static void split_key_dup_rec_helper(Node *root, const typename Node::key_type &key, Node *&ts, Node *&tg, Compare &cmp) noexcept
static bool split_key_rec_helper(Node *root, const typename Node::key_type &key, Node *&ts, Node *&tg, Compare &cmp) noexcept
bool less_or_equal_than(const T &op1, const T &op2, Compare &cmp)
Determines if op1 is less than or equal to op2 using a comparison operator.
Definition ahFunction.H:877
void put_tree_keys_in_array(Node *root, std::ostream &out)
Node< Key > * build_postorder(const DynArray< Key > &post, long lp, long rp, const DynArray< Key > &in, long li, long ri)
ThreeWayCmp
Constants for three-way comparison results.
@ CmpGreater
First argument is greater than second.
@ CmpLess
First argument is less than second.
@ CmpEqual
Arguments are equal.
bool areEquivalents(Node *t1, Node *t2, Equal &op) noexcept
Return true if trees are equivalents.
static void preorder_rec_helper(Node *p, const int &level, int &position, void(*visitFct)(Node *, int, int))
std::ostream & join(const C &c, const std::string &sep, std::ostream &out)
Join elements of an Aleph-style container into a stream.
void next()
Advance all underlying iterators (bounds-checked).
Definition ah-zip.H:175
bool areSimilar(Node *t1, Node *t2) noexcept
Return true if both trees are similar.
static bool check_bst_range(Node *p, const typename Node::key_type *min_key, const typename Node::key_type *max_key, const Compare &cmp)
static void inorder_rec_helper(Node *node, const int &level, int &position, void(*visitFct)(Node *, int, int))
static size_t internal_path_length_helper(Node *p, const size_t &level) noexcept
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.
void prefix_for_each(Node *root, Op op)
Traverse in preorder all the container and performs an operation on each element.
bool traverse(Operation &operation) noexcept(traverse_is_noexcept< Operation >())
Traverse the container via its iterator and performs a conditioned operation on each item.
Definition ah-dry.H:95
Circular queue implementations backed by arrays.
Stack implementations backed by dynamic or fixed arrays.
Basic binary tree node definitions.
Dynamic doubly linked list implementation.
Dynamic queue implementation based on linked lists.
DynList< int > l
void preorder(int v[], int n, int i)
Write preorder traversal of heap.
Definition writeHeap.C:222
ofstream output
Definition writeHeap.C:213
void inorder(int v[], int n, int i)
Write inorder traversal of heap.
Definition writeHeap.C:242