Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_hRbTree.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
45# ifndef TPL_HTDRBTREE_H
46# define TPL_HTDRBTREE_H
47
48# ifdef DEBUG
49# include <cmath>
50# endif
51# include <tpl_binNode.H>
52# include <tpl_binNodeUtils.H>
53# include <tpl_arrayStack.H>
54# include <rbNode.H>
55# include <ah-concepts.H>
56
57namespace Aleph
58{
59
83 template <class Key, class Compare = Aleph::less<Key>>
86 {
87 public:
89 using Color = unsigned char;
90
93
94 private:
95
96 private:
100
105
107
108 size_t node_count = 0;
109
110 Compare cmp;
111
113 static Node * getSibling(Node *p, Node *fp) noexcept
114 {
115 assert(LLINK(fp) == p || RLINK(fp) == p);
116 return LLINK(fp) == p ? RLINK(fp) : LLINK(fp);
117 }
118
119 // ===================== INSERTION ROUTINES =====================
120
132 Node *& fp,
133 Node *ffp,
134 Node *fffp)
135 {
136 /* Sanity checks */
137 assert(LLINK(fp) == p || RLINK(fp) == p);
138 assert(COLOR(fp) == RED);
139 assert(COLOR(p) == RED);
140
141 if (fp == root)
142 {
143 COLOR(fp) = BLACK;
144 return;
145 }
146
147 assert(LLINK(ffp) == fp || RLINK(ffp) == fp);
148 assert(COLOR(ffp) == BLACK);
149 assert(LLINK(fffp) == ffp || RLINK(fffp) == ffp);
150
151 COLOR(ffp) = RED;
152
153 if (LLINK(fp) == p && LLINK(ffp) == fp)
154 {
155 COLOR(fp) = BLACK;
157 }
158 else if (RLINK(fp) == p && RLINK(ffp) == fp)
159 {
160 COLOR(fp) = BLACK;
162 }
163 else
164 {
165 COLOR(p) = BLACK;
166 if (RLINK(fp) == p)
167 {
168 rotate_to_left(fp, ffp);
170 }
171 else
172 {
173 rotate_to_right(fp, ffp);
175 }
176 fp = fffp;
177 }
178 }
179
187 static void flipColors(Node *p) noexcept
188 {
189 assert(p != Node::NullPtr);
190 assert(COLOR(p) == BLACK);
191 assert(COLOR(LLINK(p)) == RED && COLOR(RLINK(p)) == RED);
192
193 COLOR(p) = RED;
194 COLOR(LLINK(p)) = COLOR(RLINK(p)) = BLACK;
195 }
196
206 {
207 assert(q != Node::NullPtr);
209 assert(COLOR(q) == RED);
211
212 const Key & qk = KEY(q);
213
214 Node *p = root; // Current node
215 Node *fp = head; // p's parent
216 Node *ffp = fHead; // p's grand parent
217 Node *fffp = ffHead; // p's great grand parent
218 Node *nextNode;
219
220 while (true)
221 {
222 const Key & pk = KEY(p);
223
225 return nullptr; /* Duplicated key, insertion is not possible */
226
227 if (COLOR(p) == BLACK && COLOR(LLINK(p)) == RED
228 && COLOR(RLINK(p)) == RED)
229 {
230 flipColors(p); // Rends p red
231 if (COLOR(fp) == RED) // violation of red condition
232 {
235 }
236 }
237
238 if (cmp(qk, pk))
239 {
240 if (LLINK(p) == Node::NullPtr)
241 break;
242 nextNode = LLINK(p);
243 }
244 else
245 {
246 if (RLINK(p) == Node::NullPtr)
247 break;
248 nextNode = RLINK(p);
249 }
250
251 fffp = ffp;
252 ffp = fp;
253 fp = p;
254 p = nextNode;
255 }
256
257 ++node_count;
258
259 /* Insertion act */
260 const Key & pk = KEY(p);
261 if (cmp(qk, pk))
262 LLINK(p) = q;
263
264 else
265 RLINK(p) = q;
266
267 if (COLOR(p) == RED) // Violation of red condition
268 restoreRedCondition(q, p, fp, ffp);
269
270 return q;
271 }
272
275 {
276 assert(q != Node::NullPtr);
278 assert(COLOR(q) == RED);
280
281 const Key & qk = KEY(q);
282
283 Node *p = root; // Current node
284 Node *fp = head; // p's parent
285 Node *ffp = fHead; // p's grand parent
286 Node *fffp = ffHead; // p's great grand parent
287 Node *nextNode;
288
289 while (true)
290 {
291 const Key & pk = KEY(p);
292
293 if (COLOR(p) == BLACK && COLOR(LLINK(p)) == RED
294 && COLOR(RLINK(p)) == RED)
295 {
296 flipColors(p); // Rends p red
297 if (COLOR(fp) == RED) // violation of red condition
298 {
301 }
302 }
303
304 if (cmp(qk, pk))
305 {
306 if (LLINK(p) == Node::NullPtr)
307 break;
308 nextNode = LLINK(p);
309 }
310 else
311 {
312 if (RLINK(p) == Node::NullPtr)
313 break;
314 nextNode = RLINK(p);
315 }
316
317 fffp = ffp;
318 ffp = fp;
319 fp = p;
320 p = nextNode;
321 }
322
323 ++node_count;
324
325 const Key & pk = KEY(p);
326 if (cmp(qk, pk))
327 LLINK(p) = q;
328 else
329 RLINK(p) = q;
330
331 if (COLOR(p) == RED) // Violation of red condition
332 restoreRedCondition(q, p, fp, ffp);
333
334 return q;
335 }
336
337 // ===================== DELETION ROUTINES =====================
338
347 Node * searchAndBuildPath(const Key & key) noexcept
348 {
350
351 Node *p = root;
352 path.push(head);
353
354 while (true)
355 {
356 path.push(p);
357
358 const Key & pk = KEY(p);
359
361 {
362# ifdef DEBUG
363 assert(path.size() - 1.0 <= 2*log(node_count + 1)/log(2));
364# endif
365 return p;
366 }
367
368 if (cmp(key, pk))
369 {
370 if (LLINK(p) == Node::NullPtr)
371 {
372# ifdef DEBUG
373 assert(path.size() - 1.0 <= 2*log(node_count + 1)/log(2));
374# endif
375 return p;
376 }
377
378 p = LLINK(p);
379 continue;
380 }
381
382 if (RLINK(p) == Node::NullPtr)
383 {
384# ifdef DEBUG
385 assert(path.size() - 1.0 <= 2*log(node_count + 1)/log(2));
386# endif
387 return p;
388 }
389
390 p = RLINK(p);
391 }
392 }
393
402 void findSuccAndSwap(Node *p, Node *& fp) noexcept
403 {
404 assert(p != Node::NullPtr);
406 assert(fp != Node::NullPtr);
407 assert(LLINK(fp) == p || RLINK(fp) == p);
408
409 /*
410 We save a reference to current stack content because p will be
411 swapped and p's position in stack should be occupied by
412 successor of p
413 */
415
417
418 /* Find succesor while updating searchPath */
419 Node *fSucc = p; // succesor's parent
420 Node *succ = RLINK(p); // Searching starts from p's right child
421
422 path.push(succ);
423 while (LLINK(succ) != Node::NullPtr) // go down to leftmost
424 {
425 fSucc = succ;
426 succ = LLINK(succ);
427 path.push(succ);
428 }
429# ifdef DEBUG
430 assert(path.size() - 1.0 <= 2*log(node_count + 1)/log(2));
431# endif
432
433 /*
434 update old stack entry occupied by p These operations are
435 equivalents to swap old top with current top
436 */
437 refToSearchPath = succ;
438 path.top() = p;
439
440 /* Setting of parent of p to its new child (succ) */
441 if (LLINK(fp) == p)
442 LLINK(fp) = succ;
443 else
444 RLINK(fp) = succ;
445
446 /* Swaps left branches */
447 LLINK(succ) = LLINK(p);
448 LLINK(p) = Node::NullPtr;
449
450 /* For right branches there are two cases */
451 if (RLINK(p) == succ)
452 { /* successor is just right's child of p */
453 RLINK(p) = RLINK(succ);
454 RLINK(succ) = p;
455 fp = succ;
456 }
457 else
458 { /*
459 successor is the leftmost nodo descending from right child of p
460 */
461 Node *succr = RLINK(succ);
462 RLINK(succ) = RLINK(p);
463 LLINK(fSucc) = p;
464 RLINK(p) = succr;
465 fp = fSucc;
466 }
467
468 // Swap of colors
469 Color tmp = COLOR(succ);
470 COLOR(succ) = COLOR(p);
471 COLOR(p) = tmp;
472 }
473
474
485 void balanceDownAndColor(Node *p, Node *& fp, Node *& sp) noexcept
486 {
487 assert(LLINK(fp) == p || RLINK(fp) == p);
488 assert(LLINK(fp) == sp || RLINK(fp) == sp);
489 assert(COLOR(fp) == BLACK);
490 assert(COLOR(sp) == RED);
491 assert(COLOR(p) == BLACK);
492 assert(!path.is_empty());
493
494 /* needed by rotation for links' update. We save a reference to search
495 stack because stack's head will cahnge after rotation */
496 Node *& ffp = path.top();
497
498 assert(LLINK(ffp) == fp || RLINK(ffp) == fp);
499
500 /* balancing down of p, update of out parameters and update of stack
501 entry corresponding to fp */
502 if (LLINK(fp) == p)
503 {
504 sp = LLINK(sp);
505 ffp = rotate_to_left(fp, ffp);
506 }
507 else
508 {
509 sp = RLINK(sp);
510 ffp = rotate_to_right(fp, ffp);
511 }
512
513 assert(LLINK(fp) == sp || RLINK(fp) == sp);
514 assert(COLOR(ffp) == RED);
515
516 /* coloring for ensuring to apply sibling black cases */
517 COLOR(ffp) = BLACK;
518 COLOR(fp) = RED;
519 }
520
531 void rotateNephewAndColor(Node *fp, Node *sp, Node *np) noexcept
532 {
533 assert(LLINK(fp) == sp || RLINK(fp) == sp);
534 assert(LLINK(sp) == np || RLINK(sp) == np);
535 assert(COLOR(sp) == BLACK);
536 assert(COLOR(np) == RED);
537 assert(!path.is_empty());
538
539 Node *ffp = path.top();
540
541 assert(LLINK(ffp) == fp || RLINK(ffp) == fp);
542
543 /* rotation for downing low fp */
544 if (RLINK(sp) == np)
545 rotate_to_left(fp, ffp);
546 else
547 rotate_to_right(fp, ffp);
548
549 /* coloring for fixing up red black conditions */
550 COLOR(sp) = COLOR(fp);
551 COLOR(fp) = BLACK;
552 COLOR(np) = BLACK;
553 }
554
566 {
567 assert(LLINK(fp) == sp || RLINK(fp) == sp);
568 assert(LLINK(sp) == snp || RLINK(sp) == snp);
569 assert(COLOR(sp) == BLACK);
570 assert(COLOR(snp) == RED);
571 assert(!path.is_empty());
572
573 Node *ffp = path.top();
574
575 assert(LLINK(ffp) == fp || RLINK(ffp) == fp);
576
577 /* double rotation for raising up of snp. snp becomes the new root of
578 sub tree fp */
579 if (LLINK(sp) == snp)
580 {
581 rotate_to_right(sp, fp);
582 rotate_to_left(fp, ffp);
583 }
584 else
585 {
586 rotate_to_left(sp, fp);
587 rotate_to_right(fp, ffp);
588 }
589
590 /* coloring for restoring all red black tree conditions */
591 COLOR(snp) = COLOR(fp);
592 COLOR(fp) = BLACK;
593 }
594
601 static void colorSiblingAsRed(Node *sp) noexcept
602 {
603 assert(COLOR(sp) == BLACK);
604 COLOR(sp) = RED;
605 }
606
614 static void colorParentAndSibling(Node *fp, Node *sp) noexcept
615 {
616 assert(LLINK(fp) == sp || RLINK(fp) == sp);
617 assert(COLOR(fp) == RED);
618 assert(COLOR(sp) == BLACK);
619
620 COLOR(fp) = BLACK;
621 COLOR(sp) = RED;
622 }
623
632 {
633 assert(path.top() == q);
634
635 /* look at second item after stack's head. We cannot pop it because
636 successor finding would require stack pushing */
637 Node *fq = path.top(1);
638 Node *p; /* Saves the new child of fp after p has been deleted, this
639 node can be a violating black condition black node */
640
642 assert(LLINK(fq) == q || RLINK(fq) == q);
643
644 /* Deletion step: by pass if there is a Node::NullPtr link or swap
645 with successor */
646 while (1)
647 {
648 if (LLINK(q) == Node::NullPtr) // by pass to the left side
649 {
650 if (LLINK(fq) == q)
651 p = LLINK(fq) = RLINK(q);
652 else
653 p = RLINK(fq) = RLINK(q);
654 break;
655 }
656
657 if (RLINK(q) == Node::NullPtr) // by pass to the right side
658 {
659 if (LLINK(fq) == q)
660 p = LLINK(fq) = LLINK(q);
661 else
662 p = RLINK(fq) = LLINK(q);
663 break;
664 }
665
667 }
668
669 /* if color of deleted node is red, then all red black conditions are
670 met and adjust is not necessary */
671 if (COLOR(q) == RED)
672 {
673 assert(COLOR(p) == BLACK);
674 path.empty();
675 return;
676 }
677
678 /* if color of p is black, then it misses a black node and four condition
679 is violated. However, if p's child is red we can recoloring it black
680 for restoring the missing black node */
681 if (COLOR(p) == RED)
682 {
683 COLOR(p) = BLACK;
684 path.empty();
685 return;
686 }
687
688 /* Bad luck we must do recoloring and/or balancing for restoring the
689 four condition */
690 // p's sibling
691 Node *np, *snp; // p's nephew and nephewg's sibling
692 Node *fp = fq; // we process in function of p
693
694 path.popn(2); // pops deleted node and fp
695
696 /* we examine p and we restore red black properties */
697 while (true)
698 {
699 if (p == root)
700 break;
701
702 Node *sp = getSibling(p, fp);
703
704 /* if sibling is red, we rotate down for assuring that p' sibling
705 to be black */
706 if (COLOR(sp) == RED)
707 balanceDownAndColor(p, fp, sp);
708
709 assert(COLOR(sp) == BLACK);
710
711 /* Compute nephews */
712 if (LLINK(fp) == p)
713 {
714 np = RLINK(sp);
715 snp = LLINK(sp);
716 }
717 else
718 {
719 np = LLINK(sp);
720 snp = RLINK(sp);
721 }
722
723 if (COLOR(np) == RED)
724 {
726 break;
727 }
728
729 if (COLOR(snp) == RED)
730 {
732 break;
733 }
734
735 if (COLOR(fp) == RED)
736 {
738 break;
739 }
740
741 /* color and restart process with fp */
743 p = fp;
744 fp = path.pop(); // colorSiblingAsRed(sp) does not pop it
745 }
746 path.empty();
747 }
748
749 public:
751 using key_type = Key;
752
754 Compare & key_comp() noexcept { return cmp; }
755
757 const Compare & key_comp() const noexcept { return cmp; }
758
760 Compare & get_compare() noexcept { return cmp; }
761
763 [[nodiscard]] constexpr const Compare & get_compare() const noexcept { return cmp; }
764
766 HtdRbTree(Compare __cmp = Compare()) noexcept
767 : head(&headNode),
770 root(headNode.getR()),
771 cmp(__cmp)
772 {
773 RLINK(fHead) = head;
774 RLINK(ffHead) = fHead;
776 COLOR(head) = BLACK;
777 COLOR(fHead) = BLACK;
778 COLOR(ffHead) = BLACK;
779 }
780
782 void swap(HtdRbTree & tree) noexcept
783 {
784 std::swap(root, tree.root);
785 std::swap(node_count, tree.node_count);
786 std::swap(cmp, tree.cmp);
787 }
788
791 : head(&headNode),
794 root(headNode.getR()),
796 node_count(0),
797 cmp()
798 {
799 RLINK(fHead) = head;
800 RLINK(ffHead) = fHead;
802 COLOR(head) = BLACK;
803 COLOR(fHead) = BLACK;
804 COLOR(ffHead) = BLACK;
805 swap(tree);
806 }
807
809 HtdRbTree & operator=(HtdRbTree && tree) noexcept
810 {
811 swap(tree);
812 return *this;
813 }
814
816 HtdRbTree(const HtdRbTree &) = delete;
817
819 HtdRbTree & operator=(const HtdRbTree &) = delete;
820
822 virtual ~HtdRbTree() = default;
823
825 [[nodiscard]] constexpr bool is_empty() const noexcept { return root == Node::NullPtr; }
826
828 [[nodiscard]] constexpr size_t size() const noexcept { return node_count; }
829
832 {
834 node_count = 0;
835 }
836
842 Node * insert(Node *p) noexcept
843 {
844 assert(p != Node::NullPtr);
845 assert(COLOR(p) == RED);
847
848 if (root == Node::NullPtr) [[unlikely]]
849 {
850 root = p;
851 ++node_count;
852 return p;
853 }
854
856 }
857
864 {
865 assert(p != Node::NullPtr);
866 assert(COLOR(p) == RED);
868
869 if (root == Node::NullPtr) [[unlikely]]
870 {
871 root = p;
872 ++node_count;
873 return p;
874 }
875
876 const Key & pk = KEY(p);
877 Node *found = search(pk);
878 if (found != nullptr) [[unlikely]]
879 return found;
880
881 return insert(p);
882 }
883
889 Node * insert_dup(Node *p) noexcept
890 {
891 assert(p != Node::NullPtr);
892 assert(COLOR(p) == RED);
894
895 if (root == Node::NullPtr) [[unlikely]]
896 {
897 root = p;
898 ++node_count;
899 return p;
900 }
901
903 }
904
910 Node * search(const Key & key) const noexcept
911 {
913 return retVal == Node::NullPtr ? nullptr : retVal;
914 }
915
921 Node * remove(const Key & key) noexcept
922 {
923 if (root == Node::NullPtr) [[unlikely]]
924 return nullptr;
925
926 Node *p = searchAndBuildPath(key);
927
928 if (no_equals<Key, Compare>(KEY(p), key, cmp))
929 {
930 path.empty();
931 return nullptr;
932 }
933
935
936 assert(node_count > 0);
937 --node_count;
938
939 p->reset();
940
941 return p;
942 }
943
944
946 Node *& getRoot() noexcept { return root; }
947
950
951 private:
961 static void blackHeight(Node *p, int & max, int bh = 0) noexcept
962 {
963 if (COLOR(p) == BLACK)
964 bh++; // Another seen black node
965
966 /* if a leaf is reached, we must verify max with current bh (number of
967 visited black nodes */
968 if (LLINK(p) == Node::NullPtr && RLINK(p) == Node::NullPtr)
969 {
970 if (max == -1) // This is onbly for the first leaf reached
971 max = bh;
972 assert(bh == max);
973 return;
974 }
975
976 if (LLINK(p) != Node::NullPtr) /* continue counting in the left side */
977 blackHeight(LLINK(p), max, bh);
978
979 if (RLINK(p) != Node::NullPtr) /* continue counting in the right side */
980 blackHeight(RLINK(p), max, bh);
981 }
982
984 static void testNode(Node *p) noexcept
985 {
986 /* verify red condition */
987 COND_assert(COLOR(p) == RED,
988 COLOR(LLINK(p)) == BLACK && COLOR(RLINK(p)) == BLACK);
989
990 int max = -1;
991 int bh = 0;
992
993 blackHeight(p, max, bh);
994 }
995
996 public:
1002 void verifyRedBlack() const
1003 {
1005 }
1006
1012 {
1013 return is_red_black_bst(const_cast<Node *>(root),
1014 const_cast<HtdRbTree *>(this)->cmp);
1015 }
1016
1018 struct Iterator : public BinNodeInfixIterator<Node>
1019 {
1022
1024 : BinNodeInfixIterator<Node>(const_cast<HtdRbTree &>(t).getRoot()) {}
1025 };
1026 };
1027
1032 template <class Key, class Compare = Aleph::less<Key>>
1034 class HtdRbTreeVtl : public HtdRbTree<Key, Compare>
1035 {
1036 public:
1038 using Node = typename Base::Node;
1039 using Base::Base; // Inherit constructors
1040 };
1041
1042} // namespace Aleph
1043
1044#endif /* TPL_HTDRBTREE_H */
C++20 concepts for constraining comparison functors.
@ KEY
Definition btreepic.C:169
Inorder iterator on the nodes of a binary tree.
Fixed length stack.
size_t size() const noexcept
Return the number of elements stored in the stack.
T popn(const int &n) noexcept
Perform in constant time n pops.
bool is_empty() const noexcept
Return true if stack is empty.
T pop() noexcept
Pop by moving the top of stack.
T & top() noexcept
Return a modifiable reference to stack's top.
void empty() noexcept
Empty the stack.
T & push(const T &data) noexcept(std::is_nothrow_copy_assignable_v< T >)
Push a copy of data
Hybrid red-black tree with virtual node destructor.
typename Base::Node Node
Hybrid top-down/bottom-up red-black tree.
Definition tpl_hRbTree.H:86
HtdRbTree(const HtdRbTree &)=delete
Copy constructor deleted.
Compare cmp
Comparison functor.
static void colorParentAndSibling(Node *fp, Node *sp) noexcept
Recolor parent and sibling to fix violation.
Node * fHead
Pointer to head's parent.
Node * getRoot() const noexcept
Get root pointer (const)
Node * searchFlipColorsAndInsert(Node *q) noexcept
Search for insertion point with proactive color flipping.
HtdRbTree & operator=(HtdRbTree &&tree) noexcept
Move assignment.
static Node * getSibling(Node *p, Node *fp) noexcept
Returns sibling of p given its parent fp.
static void flipColors(Node *p) noexcept
Flip colors of a black node with two red children.
unsigned char Color
Color type for red-black nodes.
Definition tpl_hRbTree.H:89
Node *& root
Reference to root (right child of head)
bool verify() const noexcept
Verify tree is a valid red-black BST.
Node * insert(Node *p) noexcept
Insert a node into the tree.
Node * remove(const Key &key) noexcept
Remove node with given key.
void restoreRedCondition(Node *p, Node *&fp, Node *ffp, Node *fffp)
Restore red-black condition after insertion.
Node * search(const Key &key) const noexcept
Search for a key.
Key key_type
The key type stored in nodes.
static void testNode(Node *p) noexcept
Verify red condition and black height for a node.
Compare & key_comp() noexcept
Returns a reference to the comparison functor.
size_t node_count
Number of nodes in tree.
static void colorSiblingAsRed(Node *sp) noexcept
Color sibling red to propagate violation upward.
Node *& getRoot() noexcept
Get reference to root pointer.
Node * head
Pointer to head node.
void reset() noexcept
Reset tree (does not free nodes)
void doubleRotateNephewAndColor(Node *fp, Node *sp, Node *snp) noexcept
Double rotation and recolor to fix violation.
Node * searchAndBuildPath(const Key &key) noexcept
Search for key while building path stack.
HtdRbTree & operator=(const HtdRbTree &)=delete
Copy assignment deleted.
Compare & get_compare() noexcept
Alias for key_comp()
Node headParent
Auxiliary node, grandparent of root.
Definition tpl_hRbTree.H:98
Node headNode
Auxiliary node, parent of root.
Definition tpl_hRbTree.H:97
RbNode< Key > Node
The node type used by this tree.
Definition tpl_hRbTree.H:92
HtdRbTree(Compare __cmp=Compare()) noexcept
Default constructor.
constexpr const Compare & get_compare() const noexcept
FixedStack< Node * > path
Stack for deletion path.
HtdRbTree(HtdRbTree &&tree) noexcept
Move constructor.
Node * search_or_insert(Node *p) noexcept
Search for key or insert if not found.
Node * searchFlipColorsAndInsertDup(Node *q) noexcept
Like searchFlipColorsAndInsert but allows duplicate keys.
static void blackHeight(Node *p, int &max, int bh=0) noexcept
Verify black height consistency.
constexpr size_t size() const noexcept
Get number of nodes in tree.
Node * insert_dup(Node *p) noexcept
Insert allowing duplicate keys.
void balanceDownAndColor(Node *p, Node *&fp, Node *&sp) noexcept
Balance down a violating black node.
Node * ffHead
Pointer to head's grandparent.
Node headGrandParent
Auxiliary node, great-grandparent of root.
Definition tpl_hRbTree.H:99
constexpr bool is_empty() const noexcept
Check if tree is empty.
virtual ~HtdRbTree()=default
Virtual destructor.
void findSuccAndSwap(Node *p, Node *&fp) noexcept
Find successor and swap with node to delete.
void rotateNephewAndColor(Node *fp, Node *sp, Node *np) noexcept
Rotate nephew up and recolor to fix violation.
void swap(HtdRbTree &tree) noexcept
Swap contents with another tree.
void removeAndFixBlackCondition(Node *q) noexcept
Remove node and fix any black-height violations.
void verifyRedBlack() const
Verify red-black tree invariants (DEBUG mode).
const Compare & key_comp() const noexcept
Declare RbNode type with 128-byte pool allocation.
Definition rbNode.H:112
static RbNode *const NullPtr
Definition rbNode.H:112
void reset() noexcept
Definition rbNode.H:112
RbNode *& getR() noexcept
Definition rbNode.H:112
static const size_t MaxHeight
Definition rbNode.H:112
__gmp_expr< typename __gmp_resolve_expr< T, V >::value_type, __gmp_binary_expr< __gmp_expr< T, U >, __gmp_expr< V, W >, __gmp_max_function > > max(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4110
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_log_function > > log(const __gmp_expr< T, U > &expr)
Definition gmpfrxx.h:4063
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.
Node * rotate_to_right(Node *p) noexcept
Rotate to the right the tree with root p
Node * searchInBinTree(Node *root, const typename Node::key_type &key, const Compare &cmp=Compare()) noexcept
Search a key in a binary search tree.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
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.
#define COLOR(p)
Definition quadnode.H:58
Red-Black tree node definition and validation utilities.
bool is_red_black_bst(Node *node, Compare &cmp)
Verify that tree is both a valid RB tree and valid BST.
Definition rbNode.H:211
#define BLACK
Black color constant.
Definition rbNode.H:76
#define RED
Red color constant (newly inserted nodes are red)
Definition rbNode.H:73
Iterator(HtdRbTree &t) noexcept
Iterator(const HtdRbTree &t) noexcept
#define RLINK(i, n)
#define LLINK(i, n)
Stack implementations backed by dynamic or fixed arrays.
Utility functions for binary tree operations.
Basic binary tree node definitions.