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
256 void for_each_in_order(Node *root, Op && op)
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>
321 void for_each_preorder(Node *root, Op && 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>
386 void for_each_postorder(Node *root, Op && 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 {
842 level_list.append(root);
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
1386 return check_bst_range<Node, Compare>(LLINK(p), min_key, &key, cmp) and
1387 check_bst_range<Node, Compare>(RLINK(p), &key, max_key, cmp);
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 {
1501
1502 if (cmp(key, KEY(root))) // key < root: go left
1503 root = LLINK(root);
1504 else // key >= root: go right, mark as candidate
1505 {
1506 candidate = root;
1507 root = RLINK(root);
1508 }
1509 }
1510
1511 // Optimistic check: if candidate exists and key == candidate, return it
1512 if (candidate != nullptr and not cmp(KEY(candidate), key)) [[unlikely]]
1513 return candidate;
1514
1515 return Node::NullPtr;
1516 }
1517
1526 template <class Node>
1527 [[nodiscard]] inline
1528 Node * find_min(Node *root) noexcept
1529 {
1530 assert(root != Node::NullPtr && "find_min called on empty tree");
1531 while (LLINK(root) != Node::NullPtr)
1532 root = LLINK(root);
1533
1534 return root;
1535 }
1536
1545 template <class Node>
1546 [[nodiscard]] inline
1547 Node * find_max(Node *root) noexcept
1548 {
1549 assert(root != Node::NullPtr && "find_max called on empty tree");
1550 while (RLINK(root) != Node::NullPtr)
1551 root = RLINK(root);
1552
1553 return root;
1554 }
1555
1564 template <class Node>
1565 inline
1566 Node * find_successor(Node *p, Node *& pp) noexcept
1567 {
1568 assert(p != Node::NullPtr);
1569 assert(RLINK(p) != Node::NullPtr);
1570
1571 pp = p;
1572 p = RLINK(p);
1573 while (LLINK(p) != Node::NullPtr)
1574 {
1575 pp = p;
1576 p = LLINK(p);
1577 }
1578
1579 return p;
1580 }
1581
1590 template <class Node>
1591 inline
1592 Node * find_predecessor(Node *p, Node *& pp) noexcept
1593 {
1594 assert(p != Node::NullPtr);
1595 assert(LLINK(p) != Node::NullPtr);
1596
1597 pp = p;
1598 p = LLINK(p);
1599
1600 while (RLINK(p) != Node::NullPtr)
1601 {
1602 pp = p;
1603 p = RLINK(p);
1604 }
1605
1606 return p;
1607 }
1608
1621 template <class Node,
1623 inline
1624 Node * search_parent(Node *root, const typename Node::key_type & key,
1625 Node *& parent, const Compare & cmp = Compare()) noexcept
1626 {
1627 assert((LLINK(parent) == root) or (RLINK(parent) == root));
1628 assert(root != Node::NullPtr);
1629
1630 while (true)
1631 {
1632 const auto c = three_way_compare(key, KEY(root), cmp);
1633 if (c == CmpLess) [[likely]]
1634 {
1635 if (LLINK(root) == Node::NullPtr)
1636 return root;
1637
1638 parent = root;
1639 root = LLINK(root);
1640 }
1641 else if (c == CmpGreater) [[likely]]
1642 {
1643 if (RLINK(root) == Node::NullPtr)
1644 return root;
1645
1646 parent = root;
1647 root = RLINK(root);
1648 }
1649 else [[unlikely]]
1650 return root;
1651 }
1652 }
1653
1672 template <class Node,
1674 inline Node *
1675 search_rank_parent(Node *root, const typename Node::key_type & key,
1676 const Compare & cmp = Compare()) noexcept
1677 {
1678 assert(root != Node::NullPtr);
1679
1680 while (true)
1681 if (const auto & root_key = KEY(root); cmp(key, root_key))
1682 {
1683 if (LLINK(root) == Node::NullPtr)
1684 return root;
1685
1686 root = LLINK(root);
1687 }
1688 else if (cmp(root_key, key))
1689 {
1690 if (RLINK(root) == Node::NullPtr)
1691 return root;
1692
1693 root = RLINK(root);
1694 }
1695 else
1696 return root;
1697 }
1698
1711 template <class Node,
1713 inline
1714 Node * insert_in_bst(Node *& r, Node *p, const Compare & cmp = Compare()) noexcept
1715 {
1716 if (r == Node::NullPtr) [[unlikely]]
1717 return r = p;
1718
1719 const auto & pk = KEY(p);
1720 const auto & rk = KEY(r);
1721
1722 if (cmp(pk, rk))
1724 if (cmp(rk, pk))
1726
1727 [[unlikely]] return Node::NullPtr;
1728 }
1729
1742 template <class Node,
1744 inline
1745 Node * insert_dup_in_bst(Node *& root, Node *p, const Compare & cmp = Compare())
1746 noexcept
1747 {
1748 if (root == Node::NullPtr) [[unlikely]]
1749 return root = p;
1750
1751 const auto & pk = KEY(p);
1752 const auto & rk = KEY(root);
1753
1754 if (cmp(pk, rk))
1755 return insert_dup_in_bst(LLINK(root), p, cmp);
1756
1757 return insert_dup_in_bst(RLINK(root), p, cmp);
1758 }
1759
1774 template <class Node,
1776 inline
1777 Node * search_or_insert_in_bst(Node *& r, Node *p, const Compare & cmp = Compare())
1778 noexcept
1779 {
1780 if (r == Node::NullPtr) [[unlikely]]
1781 return r = p;
1782
1783 const auto & pk = KEY(p);
1784 const auto & rk = KEY(r);
1785
1786 if (cmp(pk, rk))
1788 if (cmp(rk, pk))
1790
1791 [[unlikely]] return r;
1792 }
1793
1794
1795 template <class Node, class Compare>
1796 static inline
1797 bool split_key_rec_helper(Node *root, const typename Node::key_type & key,
1798 Node *& ts, Node *& tg, Compare & cmp) noexcept
1799 {
1800 if (root == Node::NullPtr)
1801 { // key is not in the tree ==> split will succeed
1802 ts = tg = Node::NullPtr;
1803 return true;
1804 }
1805
1806 if (cmp(key, KEY(root)))
1807 {
1809 {
1810 tg = root;
1811 return true;
1812 }
1813 return false;
1814 }
1815
1816 if (cmp(KEY(root), key))
1818 {
1819 ts = root;
1820 return true;
1821 }
1822
1823 return false; // key exists in the tree
1824 }
1825
1826
1846 template <class Node,
1848 inline
1849 bool split_key_rec(Node *& root, const typename Node::key_type & key,
1850 Node *& ts, Node *& tg, const Compare & cmp = Compare()) noexcept
1851 {
1852 const bool ret = split_key_rec_helper(root, key, ts, tg, cmp);
1853 if (ret)
1854 root = Node::NullPtr;
1855 return ret;
1856 }
1857
1858
1859 template <class Node, class Compare>
1860 static inline
1861 void split_key_dup_rec_helper(Node *root, const typename Node::key_type & key,
1862 Node *& ts, Node *& tg, Compare & cmp) noexcept
1863 {
1864 if (root == Node::NullPtr)
1865 {
1866 ts = tg = Node::NullPtr;
1867 return;
1868 }
1869
1870 if (cmp(KEY(root), key))
1871 {
1873 ts = root;
1874 }
1875 else
1876 {
1878 tg = root;
1879 }
1880 }
1881
1882
1897 template <class Node,
1899 inline
1900 void split_key_dup_rec(Node *& root, const typename Node::key_type & key,
1901 Node *& ts, Node *& tg, const Compare & cmp = Compare()) noexcept
1902 {
1904 root = Node::NullPtr;
1905 }
1906
1907
1921 template <class Node>
1922 inline
1923 Node * join_exclusive(Node *& ts, Node *& tg) noexcept
1924 {
1925 if (ts == Node::NullPtr)
1926 return tg;
1927
1928 if (tg == Node::NullPtr)
1929 return ts;
1930
1932
1933 RLINK(ts) = tg;
1934 Node *ret_val = ts;
1935 ts = tg = Node::NullPtr; // empty the trees
1936
1937 return ret_val;
1938 }
1939
1951 template <class Node,
1953 inline
1954 Node * remove_from_bst(Node *& root, const typename Node::key_type & key,
1955 const Compare & cmp = Compare()) noexcept
1956 {
1957 if (root == Node::NullPtr)
1958 return Node::NullPtr;
1959
1960 if (cmp(key, KEY(root)))
1961 return remove_from_bst(LLINK(root), key, cmp);
1962 if (cmp(KEY(root), key))
1963 return remove_from_bst(RLINK(root), key, cmp);
1964
1965 Node *ret_val = root; // save root that is going to be removed
1967
1968 ret_val->reset();
1969
1970 return ret_val;
1971 }
1972
1987 template <class Node,
1989 inline
1990 Node * insert_root(Node *& root, Node *p, const Compare & cmp = Compare()) noexcept
1991 {
1992 Node *l = Node::NullPtr, *r = Node::NullPtr;
1993
1994 if (not split_key_rec(root, KEY(p), l, r, cmp))
1995 return Node::NullPtr;
1996
1997 LLINK(p) = l;
1998 RLINK(p) = r;
1999 root = p;
2000
2001 return root;
2002 }
2003
2014 template <class Node,
2016 inline
2017 Node * insert_dup_root(Node *& root, Node *p, const Compare & cmp = Compare()) noexcept
2018 {
2019 split_key_dup_rec(root, KEY(p), LLINK(p), RLINK(p), cmp);
2020 return root = p;
2021 }
2022
2023
2037 template <class Node,
2039 inline
2041 const Compare & cmp = Compare()) noexcept
2042 {
2043 if (t2 == Node::NullPtr)
2044 return t1;
2045
2046 Node *l = LLINK(t2);
2047 Node *r = RLINK(t2);
2048
2049 t2->reset();
2050
2051 if (insert_in_bst(t1, t2, cmp) == Node::NullPtr)
2052 insert_in_bst(dup, t2, cmp); // insertion has failed
2053
2054 join_preorder(t1, l, dup, cmp);
2055 join_preorder(t1, r, dup, cmp);
2056
2057 return t1;
2058 }
2059
2074 template <class Node,
2076 inline
2077 Node * join(Node *t1, Node *t2, Node *& dup, const Compare & cmp = Compare())
2078 noexcept
2079 {
2080 if (t1 == Node::NullPtr)
2081 return t2;
2082
2083 if (t2 == Node::NullPtr)
2084 return t1;
2085
2086 Node *l = LLINK(t1);
2087 Node *r = RLINK(t1);
2088
2089 t1->reset();
2090
2091 while (t1 != Node::NullPtr and insert_root(t2, t1, cmp) == Node::NullPtr)
2092 {
2093 Node *p = remove_from_bst(t1, KEY(t1), cmp);
2094
2095 assert(p != Node::NullPtr);
2096
2097 insert_in_bst(dup, p, cmp);
2098 }
2099
2100 LLINK(t2) = join(l, LLINK(t2), dup, cmp);
2101 RLINK(t2) = join(r, RLINK(t2), dup, cmp);
2102
2103 return t2;
2104 }
2105
2111 template <class Node>
2112 inline
2114 {
2115 assert(p != Node::NullPtr);
2116
2117 Node *q = LLINK(p);
2118 LLINK(p) = RLINK(q);
2119 RLINK(q) = p;
2120
2121 return q;
2122 }
2123
2131 template <class Node>
2132 inline
2134 {
2135 assert(p != Node::NullPtr);
2136 assert(pp != Node::NullPtr);
2137 assert(LLINK(pp) == p or RLINK(pp) == p);
2138
2139 Node *q = LLINK(p);
2140 LLINK(p) = RLINK(q);
2141 RLINK(q) = p;
2142
2143 if (LLINK(pp) == p) // update the parent
2144 LLINK(pp) = q;
2145 else
2146 RLINK(pp) = q;
2147
2148 return q;
2149 }
2150
2156 template <class Node>
2157 inline
2158 Node * rotate_to_left(Node *p) noexcept
2159 {
2160 assert(p != Node::NullPtr);
2161
2162 Node *q = RLINK(p);
2163 RLINK(p) = LLINK(q);
2164 LLINK(q) = p;
2165
2166 return q;
2167 }
2168
2175 template <class Node>
2176 inline
2177 Node * rotate_to_left(Node *p, Node *pp) noexcept
2178 {
2179 assert(p != Node::NullPtr);
2180 assert(pp != Node::NullPtr);
2181 assert(LLINK(pp) == p or RLINK(pp) == p);
2182
2183 Node *q = RLINK(p);
2184 RLINK(p) = LLINK(q);
2185 LLINK(q) = p;
2186
2187 // update the parent
2188 if (LLINK(pp) == p)
2189 LLINK(pp) = q;
2190 else
2191 RLINK(pp) = q;
2192
2193 return q;
2194 }
2195
2210 template <class Node, class Key,
2212 inline
2213 void split_key(Node *& root, const Key & key, Node *& l, Node *& r,
2214 const Compare & cmp = Compare()) noexcept
2215 {
2216 assert(l == Node::NullPtr and r == Node::NullPtr);
2217 if (root == Node::NullPtr)
2218 {
2219 l = r = Node::NullPtr;
2220 return;
2221 }
2222
2223 Node **current_parent = nullptr;
2224 Node **pending_child = nullptr;
2225 bool current_is_right = true;
2226 if (cmp(key, KEY(root)))
2227 {
2228 r = root;
2229 pending_child = &l;
2230 }
2231 else
2232 {
2233 l = root;
2234 pending_child = &r;
2235 current_is_right = false;
2236 }
2237
2238 Node *current = root;
2239 while (current != Node::NullPtr)
2240 {
2241 if (cmp(key, KEY(current)))
2242 { /* current must be in right side */
2244 {
2246 *pending_child = *current_parent; /* change of side */
2248 }
2249 current_parent = &LLINK(current);
2250 }
2251 else
2252 { /* current must be in left side */
2253 if (current_is_right)
2254 {
2256 *pending_child = *current_parent; /* change of side */
2258 }
2259 current_parent = &RLINK(current);
2260 }
2261 current = *current_parent;
2262 }
2263 *pending_child = Node::NullPtr;
2264 root = Node::NullPtr;
2265 }
2266
2276 template <class Node>
2277 inline
2278 void swap_node_with_successor(Node *p, // Node for swapping
2279 Node *& pp, // parent of p
2280 Node *q, // Successor inorder of p
2281 Node *& pq) // parent of q
2282 noexcept
2283 {
2284 assert(p != Node::NullPtr and q != Node::NullPtr and
2285 pp != Node::NullPtr and pq != Node::NullPtr);
2286 assert(LLINK(pp) == p or RLINK(pp) == p);
2287 assert(LLINK(pq) == q or RLINK(pq) == q);
2288 assert(LLINK(q) == Node::NullPtr);
2289
2290 /* Set of pp to its new son q */
2291 if (LLINK(pp) == p)
2292 LLINK(pp) = q;
2293 else
2294 RLINK(pp) = q;
2295
2296 LLINK(q) = LLINK(p);
2297 LLINK(p) = Node::NullPtr;
2298
2299 /* Checks if successor is right child of p. In this case, p will
2300 become q's son. This situation happens when p's son does not have
2301 a left branch */
2302 if (RLINK(p) == q)
2303 {
2304 RLINK(p) = RLINK(q);
2305 RLINK(q) = p;
2306 pq = pp;
2307 pp = q;
2308 return;
2309 }
2310
2311 /* In this case, successor is the leftmost node descending from
2312 right son of p */
2313 Node *qr = RLINK(q);
2314 RLINK(q) = RLINK(p);
2315 LLINK(pq) = p;
2316 RLINK(p) = qr;
2317
2318 std::swap(pp, pq);
2319 }
2320
2330 template <class Node>
2331 inline
2332 void swap_node_with_predecessor(Node *p, // Node for swapping
2333 Node *& pp, // p's parent
2334 Node *q, // Predecessor inorder of p
2335 Node *& pq) // q's parent
2336 noexcept
2337 {
2338 assert((p != Node::NullPtr) and (q != Node::NullPtr) and
2339 (pp != Node::NullPtr) and (pq != Node::NullPtr));
2340 assert((RLINK(pp) == p) or (LLINK(pp) == p));
2341 assert((RLINK(pq) == q) or (LLINK(pq) == q));
2342 assert(RLINK(q) == Node::NullPtr);
2343
2344 /* Set of pp to its new son q */
2345 if (RLINK(pp) == p)
2346 RLINK(pp) = q;
2347 else
2348 LLINK(pp) = q;
2349
2350 RLINK(q) = RLINK(p);
2351 RLINK(p) = Node::NullPtr;
2352
2353 /* Checks if predecessor is left child of p. In this case, p will
2354 become q's son. This situation happens when p's son does not have
2355 a right branch */
2356 if (LLINK(p) == q)
2357 {
2358 LLINK(p) = LLINK(q);
2359 LLINK(q) = p;
2360 pq = pp;
2361 pp = q;
2362 return;
2363 }
2364
2365 /* In this case, predecessor is the rightmost node descending from
2366 right son of p */
2367 Node *ql = LLINK(q);
2368 LLINK(q) = LLINK(p);
2369 RLINK(pq) = p;
2370 LLINK(p) = ql;
2371 std::swap(pp, pq);
2372 }
2373
2387 template <class Node, class Key = typename Node::key_type,
2389 inline
2391 const Compare & cmp = Compare()) noexcept
2392 {
2393 if (root == Node::NullPtr)
2394 return p; /* insertion in an empty tree */
2395
2396 if (cmp(KEY(p), KEY(root)))
2397 { /* insert in the left subtree */
2399 if (left_branch == Node::NullPtr)
2400 return Node::NullPtr;
2401
2404 }
2405 else if (cmp(KEY(root), KEY(p)))
2406 { /* insert in the right subtree */
2408 if (right_branch == Node::NullPtr)
2409 return Node::NullPtr;
2410
2413 }
2414 else
2415 return Node::NullPtr; /* duplicated key */
2416
2417 return root;
2418 }
2419
2430 template <class Node, class Key = typename Node::key_type,
2432 inline
2434 const Compare & cmp = Compare()) noexcept
2435 {
2436 if (root == Node::NullPtr)
2437 return p; // insertion in empty tree
2438
2439 if (cmp(KEY(p), KEY(root)))
2440 { // insert in left subtree
2442 if (left_branch == p)
2443 {
2446 return p;
2447 }
2448
2449 return left_branch;
2450 }
2451 if (cmp(KEY(root), KEY(p)))
2452 { // insert in right subtree
2454 if (right_branch == p)
2455 {
2458 return p;
2459 }
2460
2461 return right_branch;
2462 }
2463
2464 return root;
2465 }
2466
2467
2475 template <class Node>
2477 {
2478 Node *root = nullptr;
2479 Node *curr = Node::NullPtr;
2481
2482 public:
2484 void swap(BinNodePrefixIterator & it) noexcept
2485 {
2486 std::swap(root, it.root);
2487 std::swap(curr, it.curr);
2488 s.swap(it.s);
2489 }
2490
2492
2496 : root(r), curr(root), s(Node::MaxHeight)
2497 {
2498 // empty
2499 }
2500
2502 : root(it.root), curr(it.curr), s(it.s)
2503 {
2504 // empty
2505 }
2506
2508 {
2509 swap(it);
2510 }
2511
2514 {
2515 curr = root;
2516 s.empty();
2517 }
2518
2519 private:
2520 // Helper function for finding last node
2521 static Node * last(Node *p) noexcept
2522 {
2523 if (RLINK(p) != Node::NullPtr)
2524 return last(RLINK(p));
2525
2526 if (LLINK(p) != Node::NullPtr)
2527 return last(LLINK(p));
2528
2529 return p;
2530 }
2531
2532 public:
2535 {
2536 s.empty();
2537 if (root == Node::NullPtr)
2538 {
2539 curr = Node::NullPtr;
2540 return;
2541 }
2542
2543 curr = last(root);
2544 }
2545
2548 {
2549 curr = Node::NullPtr;
2550 s.empty();
2551 }
2552
2554 {
2555 if (this == &it)
2556 return *this;
2557
2558 root = it.root;
2559 curr = it.curr;
2560 s = it.s;
2561 return *this;
2562 }
2563
2565 {
2566 swap(it);
2567 return *this;
2568 }
2569
2571 [[nodiscard]] bool has_curr() const noexcept { return curr != Node::NullPtr; }
2572
2575
2577 Node * get_curr() const
2578 {
2579 ah_overflow_error_if(not has_curr()) << "Iterator overflow";
2580 return get_curr_ne();
2581 }
2582
2586 {
2587 auto l = LLINK(curr), r = RLINK(curr);
2588 if (l != Node::NullPtr)
2589 {
2590 curr = l;
2591 if (r != Node::NullPtr)
2592 s.push(r);
2593 return;
2594 }
2595
2596 if (r != Node::NullPtr)
2597 {
2598 curr = r;
2599 return;
2600 }
2601
2602 if (s.is_empty())
2603 curr = Node::NullPtr;
2604 else
2605 curr = s.pop();
2606 }
2607
2609 void next()
2610 {
2611 ah_overflow_error_if(not has_curr()) << "Iterator overflow";
2612 next_ne();
2613 }
2614 };
2615
2639 template <class Node, class Op>
2641 {
2642 for (BinNodePrefixIterator<Node> it(root); it.has_curr(); it.next_ne())
2643 if (not op(it.get_curr()))
2644 return false;
2645 return true;
2646 }
2647
2648
2667 template <class Node, class Op>
2669 {
2670 for (BinNodePrefixIterator<Node> it(root); it.has_curr(); it.next_ne())
2671 op(it.get_curr());
2672 }
2673
2674
2682 template <class Node>
2684 {
2685 mutable Node *root = Node::NullPtr;
2686 Node *curr = Node::NullPtr;
2687 long pos = 0;
2689
2691 {
2692 while (LLINK(r) != Node::NullPtr)
2693 {
2694 s.push(r);
2695 r = LLINK(r);
2696 }
2697 return r;
2698 }
2699
2700 static Node * advance_to_max(Node *r) noexcept
2701 {
2702 while (RLINK(r) != Node::NullPtr)
2703 r = RLINK(r);
2704
2705 return r;
2706 }
2707
2709 {
2710 if (root != Node::NullPtr)
2712 pos = 0;
2713 }
2714
2715 public:
2718 {
2719 return curr != Node::NullPtr and LLINK(curr) == Node::NullPtr and s.is_empty();
2720 }
2721
2723 {
2724 return curr != Node::NullPtr and RLINK(curr) == Node::NullPtr and s.is_empty();
2725 }
2726
2727 void swap(BinNodeInfixIterator & it) noexcept
2728 {
2729 std::swap(root, it.root);
2730 std::swap(curr, it.curr);
2731 std::swap(pos, it.pos);
2732 s.swap(it.s);
2733 }
2734
2736
2739 : root(r), s(Node::MaxHeight)
2740 {
2741 init();
2742 }
2743
2745 : root(it.root), curr(it.curr), pos(it.pos), s(it.s)
2746 {
2747 // empty
2748 }
2749
2751
2754 {
2755 s.empty();
2756 init();
2757 }
2758
2761 {
2762 s.empty();
2763 if (root == Node::NullPtr)
2764 {
2765 curr = Node::NullPtr;
2766 pos = 0;
2767 return;
2768 }
2769
2771 pos = static_cast<long>(size(root)) - 1;
2772 }
2773
2775 {
2776 s.empty();
2777 curr = Node::NullPtr;
2778 pos = 0;
2779 }
2780
2782 {
2783 if (this == &it)
2784 return *this;
2785
2786 root = it.root;
2787 curr = it.curr;
2788 pos = it.pos;
2789 s = it.s;
2790 return *this;
2791 }
2792
2794 noexcept
2795 {
2796 swap(it);
2797 return *this;
2798 }
2799
2801 bool has_curr() const noexcept { return curr != Node::NullPtr; }
2802
2805
2807 Node * get_curr() const
2808 {
2809 ah_overflow_error_if(not has_curr()) << "Iterator overflow";
2810 return curr;
2811 }
2812
2814 size_t get_pos() const { return pos; }
2815
2817 {
2818 ++pos;
2819 curr = RLINK(curr);
2820 if (curr != Node::NullPtr)
2821 {
2823 return;
2824 }
2825
2826 if (s.is_empty())
2827 curr = Node::NullPtr;
2828 else
2829 curr = s.pop();
2830 }
2831
2834 void next()
2835 {
2836 ah_overflow_error_if(not has_curr()) << "Iterator overflow";
2837 next_ne();
2838 }
2839 };
2840
2864 template <class Node, class Op>
2866 {
2867 for (BinNodeInfixIterator<Node> it(root); it.has_curr(); it.next_ne())
2868 if (not op(it.get_curr()))
2869 return false;
2870 return true;
2871 }
2872
2877 template <class Node, class Op>
2878 bool traverse(Node *root, Op op)
2879 {
2880 return infix_traverse(root, op);
2881 }
2882
2901 template <class Node, class Op>
2903 {
2904 for (BinNodeInfixIterator<Node> it(root); it.has_curr(); it.next_ne())
2905 op(it.get_curr());
2906 }
2907} // end Aleph
2908
2909# 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:1155
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
__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.
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.
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
and
Check uniqueness with explicit hash + equality functors.
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)
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:105
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.
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
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.
#define RLINK(i, n)
int keys[]
#define LLINK(i, n)
DynArray< int > preorder
DynArray< int > postorder
DynArray< int > inorder
gsl_rng * r
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
ofstream output
Definition writeHeap.C:215