Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_interval_tree.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
58# ifndef TPL_INTERVAL_TREE_H
59# define TPL_INTERVAL_TREE_H
60
61# include <gsl/gsl_rng.h>
62
63# include <cassert>
64# include <ctime>
65# include <type_traits>
66
67# include <ahFunction.H>
68# include <tpl_binNodeUtils.H>
69# include <treapNode.H>
70# include <tpl_binTreeOps.H>
71# include <ah-errors.H>
72# include <ah-concepts.H>
73# include <ah-dry.H>
74# include <ahDry.H>
75# include <htlist.H>
76# include <utility>
77# include <memory>
78
79namespace Aleph
80{
89 template <typename T>
90 struct Interval
91 {
94
101
107 Interval(const T & lo, const T & hi)
108 noexcept(std::is_nothrow_copy_constructible_v<T>)
109 : low(lo), high(hi) {}
110
116 Interval(T && lo, T && hi)
117 noexcept(std::is_nothrow_move_constructible_v<T>)
118 : low(std::move(lo)), high(std::move(hi)) {}
119
125 static Interval point(const T & p)
126 noexcept(std::is_nothrow_copy_constructible_v<T>)
127 {
128 return {p, p};
129 }
130
138 template <class Compare = Aleph::less<T>>
140 const Compare & cmp = Compare()) const
142 {
143 // [a,b] overlaps [c,d] iff a <= d and c <= b
144 return not cmp(other.high, low) and not cmp(high, other.low);
145 }
146
154 template <class Compare = Aleph::less<T>>
155 [[nodiscard]] bool contains(const T & p,
156 const Compare & cmp = Compare()) const
158 {
159 return not cmp(p, low) and not cmp(high, p);
160 }
161
168 template <class Compare = Aleph::less<T>>
169 [[nodiscard]] bool is_valid(const Compare & cmp = Compare()) const
171 {
172 return not cmp(high, low);
173 }
174
180 bool operator ==(const Interval & other) const
181 noexcept(noexcept(std::declval<const T &>() == std::declval<const T &>()))
182 {
183 return low == other.low and high == other.high;
184 }
185
191 bool operator !=(const Interval & other) const
192 noexcept(noexcept(*this == other))
193 {
194 return not (*this == other);
195 }
196 };
197
204 template <typename T, class Compare = Aleph::less<T>>
206 {
207 Compare cmp;
208
213 Interval_Less(const Compare & c = Compare())
215 : cmp(c) {}
216
223 bool operator ()(const Interval<T> & a, const Interval<T> & b) const
224 noexcept(std::is_nothrow_invocable_v<const Compare &, const T &, const T &>)
225 {
226 if (cmp(a.low, b.low))
227 return true;
228 if (cmp(b.low, a.low))
229 return false;
230 return cmp(a.high, b.high);
231 }
232 };
233
237 template <typename Key>
239
241 template <typename T>
243 {
244 using type = T;
245 };
246
247 template <typename Key>
249
258 template <typename T>
260 {
261 unsigned long priority;
263
264 public:
268
270 noexcept(std::is_nothrow_default_constructible_v<T>)
272
273 unsigned long &getPriority() noexcept { return priority; }
274
277
278 static void reset() noexcept
279 { /* empty */
280 }
281 };
282
292 template <typename Key>
294 : public Interval_Tree_Node_Data<interval_endpoint_t<Key>>
295 {
296 public:
299
300 static constexpr size_t MaxHeight = 80;
302
303 using key_type = Key;
304 using Key_Type = Key;
305
306 private:
307 Key key = Key();
310
311 // sentinel node
313
314 public:
315 Key &get_key() noexcept { return key; }
316 const Key &get_key() const noexcept { return key; }
317
322
325 {
326 this->getMaxEndpoint() = k.high;
327 }
328
330 noexcept(std::is_nothrow_move_constructible_v<Key>)
331 : key(std::move(k)), lLink(NullPtr), rLink(NullPtr)
332 {
333 this->getMaxEndpoint() = key.high;
334 }
335
337 : Data(node),
338 key(node.key), lLink(NullPtr), rLink(NullPtr)
339 {
340 /* empty */
341 }
342
344 noexcept(std::is_nothrow_move_constructible_v<Key> and
345 std::is_nothrow_move_constructible_v<Data>)
346 : Data(std::move(static_cast<Data &>(node))),
347 key(std::move(node.key)), lLink(NullPtr), rLink(NullPtr)
348 {
349 /* empty */
350 }
351
354 {
355 /* empty */
356 }
357
359 {
360 Data::reset();
361 this->getMaxEndpoint() = key.high;
362 rLink = lLink = NullPtr;
363 }
364
365 private:
366 // sentinel constructor
369 {
370 /* empty - links set to nullptr will be fixed when NullPtr is initialized */
371 }
372 };
373
375 template <typename Key>
377
378 template <typename Key>
381
386 template <typename Key>
388 : public Interval_Tree_Node_Data<interval_endpoint_t<Key>>
389 {
390 public:
393
394 static constexpr size_t MaxHeight = 80;
396
397 using key_type = Key;
398 using Key_Type = Key;
399
400 private:
401 Key key = Key();
404
406
407 public:
408 Key &get_key() noexcept { return key; }
409 const Key &get_key() const noexcept { return key; }
410
415
418 {
419 this->getMaxEndpoint() = k.high;
420 }
421
423 noexcept(std::is_nothrow_move_constructible_v<Key>)
424 : key(std::move(k)), lLink(NullPtr), rLink(NullPtr)
425 {
426 this->getMaxEndpoint() = key.high;
427 }
428
430 : Data(node),
431 key(node.key), lLink(NullPtr), rLink(NullPtr)
432 {
433 /* empty */
434 }
435
437 noexcept(std::is_nothrow_move_constructible_v<Key> and
438 std::is_nothrow_move_constructible_v<Data>)
439 : Data(std::move(static_cast<Data &>(node))),
440 key(std::move(node.key)), lLink(NullPtr), rLink(NullPtr)
441 {
442 /* empty */
443 }
444
447 {
448 /* empty */
449 }
450
452 virtual ~Interval_Tree_NodeVtl() = default;
453
455 {
456 Data::reset();
457 this->getMaxEndpoint() = key.high;
458 rLink = lLink = NullPtr;
459 }
460
461 private:
467 };
468
470 template <typename Key>
472
473 template <typename Key>
476
478 template <class Node>
479 inline auto &MAX_EP(Node *p) noexcept { return p->getMaxEndpoint(); }
480
481 template <class Node>
482 inline const auto &MAX_EP(const Node *p) noexcept
483 {
484 return p->getMaxEndpoint();
485 }
486
509 template <template <typename> class NodeType,
510 typename T,
511 class Compare = Aleph::less<T>>
514 {
515 public:
519
520 private:
525 Compare cmp;
526 size_t num_nodes;
527
528 void init(const unsigned int seed)
529 {
532 ah_bad_alloc_if(r == nullptr);
534 }
535
537 static void update_max(Node *p, const Compare & cmp)
538 {
539 auto & mx = MAX_EP(p);
540 mx = KEY(p).high;
541 if (LLINK(p) != Node::NullPtr)
542 if (cmp(mx, MAX_EP(LLINK(p))))
543 mx = MAX_EP(LLINK(p));
544 if (RLINK(p) != Node::NullPtr)
545 if (cmp(mx, MAX_EP(RLINK(p))))
546 mx = MAX_EP(RLINK(p));
547 }
548
550 static Node * rotate_to_right_it(Node *p, const Compare & cmp)
551 {
552 assert(p != Node::NullPtr);
553 Node *q = LLINK(p);
554 LLINK(p) = RLINK(q);
555 RLINK(q) = p;
556 update_max(p, cmp); // old parent first (now child)
557 update_max(q, cmp); // new parent (depends on updated p)
558 return q;
559 }
560
562 static Node * rotate_to_left_it(Node *p, const Compare & cmp)
563 {
564 assert(p != Node::NullPtr);
565 Node *q = RLINK(p);
566 RLINK(p) = LLINK(q);
567 LLINK(q) = p;
568 update_max(p, cmp);
569 update_max(q, cmp);
570 return q;
571 }
572
574 {
575 if (root == Node::NullPtr)
576 return p;
577
578 const Key & pk = KEY(p);
579 const Key & rk = KEY(root);
581 Node *result = nullptr;
582 if (interval_cmp(pk, rk))
583 {
584 result = insert(LLINK(root), p);
585 if (result == Node::NullPtr)
586 return Node::NullPtr;
587 LLINK(root) = result;
589 if (PRIO(LLINK(root)) < PRIO(root))
590 return rotate_to_right_it(root, cmp);
591 return root;
592 }
593 if (interval_cmp(rk, pk))
594 {
595 result = insert(RLINK(root), p);
596 if (result == Node::NullPtr)
597 return Node::NullPtr;
598 RLINK(root) = result;
600 if (PRIO(RLINK(root)) < PRIO(root))
601 return rotate_to_left_it(root, cmp);
602 return root;
603 }
604
605 return Node::NullPtr; // duplicate
606 }
607
609 {
610 if (root == Node::NullPtr)
611 return p;
612
613 const Key & pk = KEY(p);
614 const Key & rk = KEY(root);
616 if (interval_cmp(pk, rk))
617 {
620 if (PRIO(LLINK(root)) < PRIO(root))
621 return rotate_to_right_it(root, cmp);
622 return root;
623 }
626 if (PRIO(RLINK(root)) < PRIO(root))
627 return rotate_to_left_it(root, cmp);
628 return root;
629 }
630
632 const Compare & cmp)
633 {
634 if (t1 == Node::NullPtr)
635 return t2;
636 if (t2 == Node::NullPtr)
637 return t1;
638
639 if (PRIO(t1) < PRIO(t2))
640 {
642 update_max(t1, cmp);
643 return t1;
644 }
646 update_max(t2, cmp);
647 return t2;
648 }
649
650 Node * remove(Node *& root, const Key & key)
651 {
652 if (root == Node::NullPtr)
653 return Node::NullPtr;
654
655 const Key & rk = KEY(root);
657 Node *ret_val;
658 if (interval_cmp(key, rk))
659 ret_val = remove(LLINK(root), key);
660 else if (interval_cmp(rk, key))
661 ret_val = remove(RLINK(root), key);
662 else
663 {
664 ret_val = root;
666 return ret_val;
667 }
668
669 if (ret_val == Node::NullPtr)
670 return Node::NullPtr;
671
673 return ret_val;
674 }
675
677 template <class Op>
678 static void all_overlaps(Node *root, const Key & query,
679 Op & op, const Compare & cmp)
680 {
681 if (root == Node::NullPtr)
682 return;
683
684 // Prune: if max_endpoint < query.low, no overlap in this subtree
685 if (cmp(MAX_EP(root), query.low))
686 return;
687
688 // Recurse left
689 all_overlaps(LLINK(root), query, op, cmp);
690
691 // Check current node
692 if (KEY(root).overlaps(query, cmp))
693 op(KEY(root));
694
695 // Prune right: if root.low > query.high, no overlap in right subtree
696 if (cmp(query.high, KEY(root).low))
697 return;
698
699 // Recurse right
700 all_overlaps(RLINK(root), query, op, cmp);
701 }
702
704 static bool check_max(Node *root, const Compare & cmp)
705 {
706 if (root == Node::NullPtr)
707 return true;
708
709 T expected = KEY(root).high;
710 if (LLINK(root) != Node::NullPtr)
711 if (cmp(expected, MAX_EP(LLINK(root))))
713 if (RLINK(root) != Node::NullPtr)
714 if (cmp(expected, MAX_EP(RLINK(root))))
716
718 return false; // MAX_EP(root) != expected
719
721 }
722
723 static size_t count_nodes(Node *root) noexcept
724 {
725 if (root == Node::NullPtr)
726 return 0;
727 return 1 + count_nodes(LLINK(root)) + count_nodes(RLINK(root));
728 }
729
730 public:
732 void set_seed(const unsigned long seed) noexcept { gsl_rng_set(r, seed); }
733
736
738 const Compare & endpoint_comp() const noexcept { return cmp; }
739
741 const Compare & get_compare() const noexcept { return endpoint_comp(); }
742
745 noexcept(noexcept(std::swap(tree_root, tree.tree_root)) and
746 noexcept(std::swap(cmp, tree.cmp)) and
747 noexcept(std::swap(r, tree.r)) and
748 noexcept(std::swap(num_nodes, tree.num_nodes)))
749 {
750 std::swap(tree_root, tree.tree_root);
751 std::swap(cmp, tree.cmp);
752 std::swap(r, tree.r);
753 std::swap(num_nodes, tree.num_nodes);
754 }
755
761 Gen_Interval_Tree(const unsigned long seed,
762 const Compare & _cmp = Compare())
764 cmp(_cmp), num_nodes(0)
765 {
766 init(seed);
767 }
768
773 Gen_Interval_Tree(const Compare & _cmp = Compare())
775 {
776 /* empty */
777 }
778
787
789 {
790 if (r != nullptr)
792 }
793
796
799
801 const Node * getRoot() const { return tree_root; }
802
804 [[nodiscard]] size_t size() const noexcept { return num_nodes; }
805
807 [[nodiscard]] bool is_empty() const noexcept { return num_nodes == 0; }
808
811
817 const Node * search(const Key & key) const
818 {
820 return ret_val == Node::NullPtr ? nullptr : ret_val;
821 }
822
829 {
830 assert(p != Node::NullPtr);
831 PRIO(p) = gsl_rng_get(r);
832 p->getMaxEndpoint() = KEY(p).high;
833 Node *result = insert(tree_root, p);
834 if (result == Node::NullPtr)
835 return nullptr;
836 tree_root = result;
837 ++num_nodes;
838 return p;
839 }
840
847 {
848 assert(p != Node::NullPtr);
849 PRIO(p) = gsl_rng_get(r);
850 p->getMaxEndpoint() = KEY(p).high;
852 ++num_nodes;
853 return p;
854 }
855
861 Node * remove(const Key & key)
862 {
863 Node *ret_val = remove(tree_root, key);
864 if (ret_val == Node::NullPtr)
865 return nullptr;
866 ret_val->reset();
867 --num_nodes;
868 return ret_val;
869 }
870
878 const Node * overlap_search(const Key & query) const
879 {
880 Node *x = tree_root;
881 while (x != Node::NullPtr)
882 {
883 if (KEY(x).overlaps(query, cmp))
884 return x;
885
886 if (LLINK(x) != Node::NullPtr and
887 not cmp(MAX_EP(LLINK(x)), query.low))
888 x = LLINK(x);
889 else
890 x = RLINK(x);
891 }
892 return nullptr;
893 }
894
902 template <class Op>
903 void all_overlaps(const Key & query, Op && op) const
904 {
905 all_overlaps(tree_root, query, op, cmp);
906 }
907
914 {
915 DynList<Key> result;
916 all_overlaps(query, [&result](const Key & iv) { result.append(iv); });
917 return result;
918 }
919
928 template <class Op>
929 void stab(const T & p, Op && op) const
930 {
932 all_overlaps(point_iv, std::forward<Op>(op));
933 }
934
940 [[nodiscard]] DynList<Key> find_stab(const T & p) const
941 {
942 return find_all_overlaps(Key::point(p));
943 }
944
949 [[nodiscard]] bool verify() const
950 {
952 return false;
954 return false;
956 return false;
958 return false;
959 return true;
960 }
961
970 };
971
978 template <typename T, class Compare = Aleph::less<T>>
981 : public Gen_Interval_Tree<Interval_Tree_Node, T, Compare>
982 {
984 using Base::Base;
985 };
986
993 template <typename T, class Compare = Aleph::less<T>>
996 : public Gen_Interval_Tree<Interval_Tree_NodeVtl, T, Compare>
997 {
999 using Base::Base;
1000 };
1001
1028 template <typename T, class Compare = Aleph::less<T>>
1031 : public EqualToMethod<DynIntervalTree<T, Compare>>,
1032 public FunctionalMethods<DynIntervalTree<T, Compare>, Interval<T>>,
1033 public GenericKeys<DynIntervalTree<T, Compare>, Interval<T>>,
1034 public StlAlephIterator<DynIntervalTree<T, Compare>>
1035 {
1036 public:
1039 using Key_Type = Key;
1042
1043 private:
1045
1046 void copy_from(const DynIntervalTree & src)
1047 {
1048 src.for_each([this](const Key & iv) { append(iv); });
1049 }
1050
1052 {
1055 }
1056
1057 public:
1061 DynIntervalTree(const Compare & cmp = Compare()) : tree(cmp) {}
1062
1067 DynIntervalTree(const unsigned long seed,
1068 const Compare & cmp = Compare())
1069 : tree(seed, cmp) {}
1070
1075 : tree(src.tree.endpoint_comp())
1076 {
1078 tmp.copy_from(src);
1079 this->swap(tmp);
1080 }
1081
1092 : tree(src.tree.endpoint_comp())
1093 {
1094 tree.swap(src.tree);
1095 }
1096
1102 {
1103 if (this == &src)
1104 return *this;
1105 DynIntervalTree tmp(src);
1106 swap(tmp);
1107 return *this;
1108 }
1109
1115 noexcept(noexcept(std::declval<Tree &>().swap(std::declval<Tree &>())))
1116 {
1117 if (this == &src)
1118 return *this;
1119 destroy_tree();
1120 tree.swap(src.tree);
1121 return *this;
1122 }
1123
1126
1131 noexcept(noexcept(std::declval<Tree &>().swap(std::declval<Tree &>())))
1132 {
1133 tree.swap(other.tree);
1134 }
1135
1137
1145 Key &insert(const Key & iv)
1146 {
1148 << "Invalid interval: low > high";
1149 std::unique_ptr<Node> p(new Node(iv));
1150 Node *result = tree.insert(p.get());
1151 if (result == nullptr)
1152 ah_domain_error() << "Duplicate interval";
1153
1154 p.release();
1155 return KEY(result);
1156 }
1157
1166 {
1168 << "Invalid interval: low > high";
1169 std::unique_ptr<Node> p(new Node(std::move(iv)));
1170 Node *result = tree.insert(p.get());
1171 if (result == nullptr)
1172 ah_domain_error() << "Duplicate interval";
1173
1174 p.release();
1175 return KEY(result);
1176 }
1177
1185 Key &insert(const T & lo, const T & hi)
1186 {
1187 return insert(Key(lo, hi));
1188 }
1189
1197 {
1199 << "Invalid interval: low > high";
1200 std::unique_ptr<Node> p(new Node(iv));
1201 tree.insert_dup(p.get());
1202 return KEY(p.release());
1203 }
1204
1210 Key &append(const Key & iv) { return insert_dup(iv); }
1211
1217 bool remove(const Key & iv)
1218 {
1219 Node *p = tree.remove(iv);
1220 if (p == nullptr)
1221 return false;
1222 delete p;
1223 return true;
1224 }
1225
1232 bool remove(const T & lo, const T & hi)
1233 {
1234 return remove(Key(lo, hi));
1235 }
1236
1243 const Key * search(const Key & iv) const noexcept
1244 {
1245 auto *p = tree.search(iv);
1246 return p != nullptr ? &KEY(p) : nullptr;
1247 }
1248
1255 const Key * overlap_search(const Key & query) const
1256 {
1257 auto *p = tree.overlap_search(query);
1258 return p != nullptr ? &KEY(p) : nullptr;
1259 }
1260
1266 const Key * overlap_search(const T & lo, const T & hi) const
1267 {
1268 return overlap_search(Key(lo, hi));
1269 }
1270
1278 template <class Op>
1279 void all_overlaps(const Key & query, Op && op) const
1280 {
1281 tree.all_overlaps(query, std::forward<Op>(op));
1282 }
1283
1290 {
1291 return tree.find_all_overlaps(query);
1292 }
1293
1300 const T & hi) const
1301 {
1302 return find_all_overlaps(Key(lo, hi));
1303 }
1304
1311 template <class Op>
1312 void stab(const T & p, Op && op) const
1313 {
1314 tree.stab(p, std::forward<Op>(op));
1315 }
1316
1321 [[nodiscard]] DynList<Key> find_stab(const T & p) const
1322 {
1323 return tree.find_stab(p);
1324 }
1325
1330 [[nodiscard]] size_t size() const noexcept { return tree.size(); }
1331
1337
1342 [[nodiscard]] bool empty() const noexcept { return is_empty(); }
1343
1347 [[nodiscard]] bool verify() const { return tree.verify(); }
1348
1358 template <class Operation>
1360 {
1361 return Aleph::traverse(tree.getRoot(), [&op](const Node *p)
1362 {
1363 return op(p->get_key());
1364 });
1365 }
1366
1373 template <class Operation>
1375 {
1376 return traverse<Operation>(op);
1377 }
1378
1385 template <class Operation>
1386 bool traverse(Operation & op) const
1387 {
1388 return Aleph::traverse(tree.getRoot(), [&op](const Node *p)
1389 {
1390 return op(p->get_key());
1391 });
1392 }
1393
1400 template <class Operation>
1401 bool traverse(Operation && op = Operation()) const
1402 {
1403 return traverse<Operation>(op);
1404 }
1405
1411 {
1413
1414 public:
1417
1422
1426 [[nodiscard]] bool has_curr() const noexcept { return it.has_curr(); }
1427
1432 const Key &get_curr() const
1433 {
1434 return KEY(static_cast<const Node*>(it.get_curr()));
1435 }
1436
1442 {
1443 return KEY(static_cast<const Node*>(it.get_curr_ne()));
1444 }
1445
1449 void next() { it.next(); }
1450
1455
1459 void prev() { it.prev(); }
1460
1465
1469 void end() noexcept { it.end(); }
1470
1475 [[nodiscard]] size_t get_pos() const { return it.get_pos(); }
1476 };
1477 };
1478} // end namespace Aleph
1479
1480# endif // TPL_INTERVAL_TREE_H
C++20 concepts for constraining comparison functors.
Container traversal and functional operation mixins.
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error()
Throws std::domain_error unconditionally.
Definition ah-errors.H:554
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
#define ah_bad_alloc_if(C)
Throws std::bad_alloc if condition holds.
Definition ah-errors.H:429
SentinelCtor
Tag type for sentinel node construction.
Definition ahDefs.H:81
@ sentinelCtor
Definition ahDefs.H:81
DRY (Don't Repeat Yourself) utilities and macros.
#define Special_Ctors(Set_Type, Type)
Generates special constructors for containers.
Definition ahDry.H:113
Standard functor implementations and comparison objects.
WeightedDigraph::Node Node
@ KEY
Definition btreepic.C:169
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.
Node * get_curr() const
Return the current node. Throw overflow_error if there is no current.
bool has_curr() const noexcept
Return true the iterator has current node.
size_t get_pos() const
Return the current position of iterator. Only valid if has_curr() == true.
void reset_first() noexcept
Reset the iterator to the first node inorder.
Inorder iterator yielding Interval<T> keys.
bool has_curr() const noexcept
Check if there is a current element.
void end() noexcept
Move to the position after the last element.
size_t get_pos() const
Return the 0-indexed current position.
const Key & get_curr_ne() const noexcept
Return the current interval (no check).
void reset_first() noexcept
Reset to the first element in traversal order.
void next()
Advance to the next element.
Iterator() noexcept=default
Default constructor.
void prev()
Go back to the previous element.
void next_ne() noexcept
Advance to the next element (no check).
const Key & get_curr() const
Return the current interval.
High-level interval tree with automatic memory management.
Key & insert(const T &lo, const T &hi)
Insert an interval given endpoints (unique).
DynList< Key > find_all_overlaps(const Key &query) const
Find all overlapping intervals.
DynIntervalTree(const unsigned long seed, const Compare &cmp=Compare())
Construct with explicit seed for the internal RNG.
DynList< Key > find_stab(const T &p) const
Find all intervals containing point p.
DynList< Key > find_all_overlaps(const T &lo, const T &hi) const
Overload of find_all_overlaps() using endpoints.
bool is_empty() const noexcept
Return true if the tree contains no intervals.
Key & insert_dup(const Key &iv)
Insert interval, allowing duplicates.
void copy_from(const DynIntervalTree &src)
Key & insert(const Key &iv)
Insert an interval (unique).
const Key * overlap_search(const T &lo, const T &hi) const
Overload of overlap_search() using endpoints.
const Key * overlap_search(const Key &query) const
Find any interval overlapping query.
void all_overlaps(const Key &query, Op &&op) const
Apply op to every overlapping interval.
bool traverse(Operation &&op=Operation()) const
Const rvalue overload of traverse().
void swap(DynIntervalTree &other) noexcept(noexcept(std::declval< Tree & >().swap(std::declval< Tree & >())))
Swap state with another tree in O(1).
DynIntervalTree & operator=(const DynIntervalTree &src)
Copy assignment.
bool verify() const
Verify all tree invariants (BST, Treap, MaxEndpoint).
Key & append(const Key &iv)
Append an interval (alias for insert_dup).
DynIntervalTree(DynIntervalTree &&src)
Move constructor.
bool empty() const noexcept
Return true if the tree contains no intervals (STL compatible).
bool traverse(Operation &&op=Operation())
Overload of traverse() for rvalue callbacks.
bool traverse(Operation &op)
Traverse all intervals in inorder (sorted by low endpoint).
void stab(const T &p, Op &&op) const
Apply op to every interval containing point p.
size_t size() const noexcept
Return the number of intervals in the tree.
bool remove(const T &lo, const T &hi)
Remove an interval given endpoints.
bool traverse(Operation &op) const
Const overload of traverse().
Key & insert(Key &&iv)
Insert an interval (move version, unique).
bool remove(const Key &iv)
Remove an interval from the tree.
typename Interval_Tree< T, Compare >::Node Node
DynIntervalTree(const Compare &cmp=Compare())
Default constructor.
DynIntervalTree(const DynIntervalTree &src)
Copy constructor.
const Key * search(const Key &iv) const noexcept
Search for an exact interval.
Dynamic singly linked list with functional programming support.
Definition htlist.H:1155
T & append(const T &item)
Definition htlist.H:1271
Augmented treap storing intervals with overlap/stabbing queries.
Node * insert(Node *root, Node *p)
Node * insert_dup(Node *p)
Insert a node (duplicates allowed).
DynList< Key > find_all_overlaps(const Key &query) const
Find all intervals overlapping query.
static void update_max(Node *p, const Compare &cmp)
Recalculate max_endpoint from node's own high and children.
size_t size() const noexcept
Return the number of nodes.
Gen_Interval_Tree(const unsigned long seed, const Compare &_cmp=Compare())
Construct with explicit seed and comparator.
bool verify() const
Verify BST, heap, and max_endpoint invariants.
const Node * search(const Key &key) const
Search for an exact interval in the tree.
void set_seed(const unsigned long seed) noexcept
Set the random number generator seed.
Interval_Less< T, Compare > IntervalCmp
const Compare & endpoint_comp() const noexcept
Return the endpoint comparison functor (const)
const Compare & get_compare() const noexcept
Backwards-compatible accessor for the endpoint comparator.
Node * remove(const Key &key)
Remove an interval from the tree.
void stab(const T &p, Op &&op) const
Apply op to every interval containing point p.
Node *& getRoot() noexcept
Return the tree's root.
static Node * rotate_to_left_it(Node *p, const Compare &cmp)
Rotate left with augmented field update.
void swap(Gen_Interval_Tree &tree) noexcept(noexcept(std::swap(tree_root, tree.tree_root)) and noexcept(std::swap(cmp, tree.cmp)) and noexcept(std::swap(r, tree.r)) and noexcept(std::swap(num_nodes, tree.num_nodes)))
Swap all state with tree in O(1)
IntervalCmp key_comp() const noexcept
Return the interval comparison functor (over Interval<T> keys)
static void all_overlaps(Node *root, const Key &query, Op &op, const Compare &cmp)
Recursive: find all intervals overlapping query.
Node * insert(Node *p)
Insert a node (no duplicates).
Gen_Interval_Tree(const Compare &_cmp=Compare())
Construct with default seed (from system time).
static Node * rotate_to_right_it(Node *p, const Compare &cmp)
Rotate right with augmented field update.
Gen_Interval_Tree & operator=(const Gen_Interval_Tree &)=delete
Deleted copy assignment.
void init(const unsigned int seed)
Gen_Interval_Tree(const Gen_Interval_Tree &)=delete
Deleted copy constructor.
bool is_empty() const noexcept
Return true if the tree is empty.
void reset_num_nodes() noexcept
Reset the node count (used after manual tree destruction)
const Node * overlap_search(const Key &query) const
Find any interval that overlaps with query (CLRS algorithm).
static bool check_max(Node *root, const Compare &cmp)
Verify max_endpoint invariant.
gsl_rng * gsl_rng_object() const noexcept
Get a pointer to the GSL random number generator.
static Node * join_exclusive(Node *t1, Node *t2, const Compare &cmp)
void all_overlaps(const Key &query, Op &&op) const
Apply op to every interval overlapping query.
Node * remove(Node *&root, const Key &key)
static size_t count_nodes(Node *root) noexcept
DynList< Key > find_stab(const T &p) const
Find all intervals containing point p.
Node * insert_dup(Node *root, Node *p)
Gen_Interval_Tree(Gen_Interval_Tree &&)=delete
Deleted move constructor.
const Node * getRoot() const
Return the tree's root (const)
Interval tree node with virtual destructor.
virtual ~Interval_Tree_NodeVtl()=default
Virtual destructor.
const Interval_Tree_NodeVtl * getL() const noexcept
interval_endpoint_t< Key > Endpoint
static Interval_Tree_NodeVtl *const NullPtr
const Key & get_key() const noexcept
Interval_Tree_NodeVtl(Key &&k) noexcept(std::is_nothrow_move_constructible_v< Key >)
Interval_Tree_NodeVtl *& getL() noexcept
Interval_Tree_NodeVtl * rLink
Interval_Tree_NodeVtl(const Interval_Tree_NodeVtl &node)
Interval_Tree_NodeVtl * lLink
Interval_Tree_NodeVtl *& getR() noexcept
static Interval_Tree_NodeVtl sentinel_node
The sentinel node instance (virtual version).
Interval_Tree_NodeVtl(Interval_Tree_NodeVtl &&node) noexcept(std::is_nothrow_move_constructible_v< Key > and std::is_nothrow_move_constructible_v< Data >)
const Interval_Tree_NodeVtl * getR() const noexcept
static constexpr size_t MaxHeight
Data portion of an interval tree node.
Interval_Tree_Node_Data() noexcept(std::is_nothrow_default_constructible_v< T >)
const T & getMaxEndpoint() const noexcept
unsigned long & getPriority() noexcept
Interval_Tree_Node_Data(SentinelCtor) noexcept(std::is_nothrow_default_constructible_v< T >)
Interval tree node with sentinel support.
Interval_Tree_Node *& getR() noexcept
const Interval_Tree_Node * getR() const noexcept
const Key & get_key() const noexcept
static constexpr size_t MaxHeight
static Interval_Tree_Node *const NullPtr
interval_endpoint_t< Key > Endpoint
static Interval_Tree_Node sentinel_node
The sentinel node instance.
Interval_Tree_Node(Interval_Tree_Node &&node) noexcept(std::is_nothrow_move_constructible_v< Key > and std::is_nothrow_move_constructible_v< Data >)
Interval_Tree_Node(Key &&k) noexcept(std::is_nothrow_move_constructible_v< Key >)
Interval_Tree_Node * lLink
Interval_Tree_Node *& getL() noexcept
const Interval_Tree_Node * getL() const noexcept
Interval_Tree_Node(const Interval_Tree_Node &node)
Interval_Tree_Node * rLink
Equality test for containers.
Definition ah-dry.H:1826
Common methods to the Aleph-w ( ) containers.
Definition ah-dry.H:642
void for_each(Operation &operation)
Traverse all the container and performs an operation on each element.
Definition ah-dry.H:779
Mixin that adds STL begin()/end() and cbegin()/cend() to Aleph containers.
Strict weak ordering constraint for BST comparators.
Definition ah-concepts.H:84
__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 check_bst(Node *p, const Compare &cmp=Compare())
Return true if p is a binary search tree.
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.
unsigned long & PRIO(Node *p) noexcept
Access the priority of a treap node.
Definition treapNode.H:120
Singly linked list implementations with head-tail access.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
and
Check uniqueness with explicit hash + equality functors.
typename interval_endpoint< Key >::type interval_endpoint_t
auto & MAX_EP(Node *p) noexcept
Access max_endpoint of an interval tree node.
bool is_treap(Node *root) noexcept
Validate that a tree satisfies treap (heap) property.
Definition treapNode.H:144
bool traverse(Node *root, Op op)
static long & low(typename GT::Node *p)
Internal helper: low-link value stored directly in NODE_COOKIE(p).
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
const long Max_Priority
Maximum priority value (used for sentinel/leaves)
Definition treapNode.H:75
const long Min_Priority
Minimum priority value.
Definition treapNode.H:78
static std::atomic< bool > init
Definition hash-fct.C:53
STL namespace.
Inorder iterator over nodes.
BST comparator for intervals: order by (low, then high).
bool operator()(const Interval< T > &a, const Interval< T > &b) const noexcept(std::is_nothrow_invocable_v< const Compare &, const T &, const T & >)
Comparison operator.
Interval_Less(const Compare &c=Compare()) noexcept(std::is_nothrow_copy_constructible_v< Compare >)
Constructor.
Interval tree using nodes with virtual destructor.
Interval tree using nodes without virtual destructor.
Closed interval [low, high].
bool operator==(const Interval &other) const noexcept(noexcept(std::declval< const T & >()==std::declval< const T & >()))
Equality operator.
static Interval point(const T &p) noexcept(std::is_nothrow_copy_constructible_v< T >)
Construct a point interval [p, p].
Interval() noexcept(std::is_nothrow_default_constructible_v< T >)
Initializes the interval as [T{}, T{}].
bool contains(const T &p, const Compare &cmp=Compare()) const noexcept(std::is_nothrow_invocable_v< const Compare &, const T &, const T & >)
Return true if this interval contains the point p.
bool is_valid(const Compare &cmp=Compare()) const noexcept(std::is_nothrow_invocable_v< const Compare &, const T &, const T & >)
Return true if low <= high.
bool overlaps(const Interval &other, const Compare &cmp=Compare()) const noexcept(std::is_nothrow_invocable_v< const Compare &, const T &, const T & >)
Return true if this interval overlaps with other.
T low
Lower endpoint.
Interval(T &&lo, T &&hi) noexcept(std::is_nothrow_move_constructible_v< T >)
Construct interval [lo, hi] (move version).
T high
Upper endpoint.
bool operator!=(const Interval &other) const noexcept(noexcept(*this==other))
Inequality operator.
Interval(const T &lo, const T &hi) noexcept(std::is_nothrow_copy_constructible_v< T >)
Construct interval [lo, hi].
Trait to extract endpoint type from Interval<T>.
Generic list of items stored in a container.
Definition ah-dry.H:1714
#define RLINK(i, n)
#define LLINK(i, n)
ValueArg< size_t > seed
Definition testHash.C:48
static int * k
Utility functions for binary tree operations.
Binary tree operations (split, join, rotate).
Treap node definition with BST key and heap priority.