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
56namespace Aleph
57{
58
82 template <class Key, class Compare = Aleph::less<Key>>
84 {
85 public:
87 using Color = unsigned char;
88
91
92 private:
93
94 private:
98
103
105
106 size_t node_count = 0;
107
108 Compare cmp;
109
111 static Node * getSibling(Node *p, Node *fp) noexcept
112 {
113 assert(LLINK(fp) == p || RLINK(fp) == p);
114 return LLINK(fp) == p ? RLINK(fp) : LLINK(fp);
115 }
116
117 // ===================== INSERTION ROUTINES =====================
118
130 Node *& fp,
131 Node *ffp,
132 Node *fffp)
133 {
134 /* Sanity checks */
135 assert(LLINK(fp) == p || RLINK(fp) == p);
136 assert(COLOR(fp) == RED);
137 assert(COLOR(p) == RED);
138
139 if (fp == root)
140 {
141 COLOR(fp) = BLACK;
142 return;
143 }
144
145 assert(LLINK(ffp) == fp || RLINK(ffp) == fp);
146 assert(COLOR(ffp) == BLACK);
147 assert(LLINK(fffp) == ffp || RLINK(fffp) == ffp);
148
149 COLOR(ffp) = RED;
150
151 if (LLINK(fp) == p && LLINK(ffp) == fp)
152 {
153 COLOR(fp) = BLACK;
155 }
156 else if (RLINK(fp) == p && RLINK(ffp) == fp)
157 {
158 COLOR(fp) = BLACK;
160 }
161 else
162 {
163 COLOR(p) = BLACK;
164 if (RLINK(fp) == p)
165 {
168 }
169 else
170 {
173 }
174 fp = fffp;
175 }
176 }
177
185 static void flipColors(Node *p) noexcept
186 {
187 assert(p != Node::NullPtr);
188 assert(COLOR(p) == BLACK);
189 assert(COLOR(LLINK(p)) == RED && COLOR(RLINK(p)) == RED);
190
191 COLOR(p) = RED;
192 COLOR(LLINK(p)) = COLOR(RLINK(p)) = BLACK;
193 }
194
204 {
205 assert(q != Node::NullPtr);
207 assert(COLOR(q) == RED);
209
210 const Key & qk = KEY(q);
211
212 Node *p = root; // Current node
213 Node *fp = head; // p's parent
214 Node *ffp = fHead; // p's grand parent
215 Node *fffp = ffHead; // p's great grand parent
216 Node *nextNode;
217
218 while (true)
219 {
220 const Key & pk = KEY(p);
221
223 return nullptr; /* Duplicated key, insertion is not possible */
224
225 if (COLOR(p) == BLACK && COLOR(LLINK(p)) == RED
226 && COLOR(RLINK(p)) == RED)
227 {
228 flipColors(p); // Rends p red
229 if (COLOR(fp) == RED) // violation of red condition
230 {
233 }
234 }
235
236 if (cmp(qk, pk))
237 {
238 if (LLINK(p) == Node::NullPtr)
239 break;
240 nextNode = LLINK(p);
241 }
242 else
243 {
244 if (RLINK(p) == Node::NullPtr)
245 break;
246 nextNode = RLINK(p);
247 }
248
249 fffp = ffp;
250 ffp = fp;
251 fp = p;
252 p = nextNode;
253 }
254
255 ++node_count;
256
257 /* Insertion act */
258 const Key & pk = KEY(p);
259 if (cmp(qk, pk))
260 LLINK(p) = q;
261
262 else
263 RLINK(p) = q;
264
265 if (COLOR(p) == RED) // Violation of red condition
266 restoreRedCondition(q, p, fp, ffp);
267
268 return q;
269 }
270
273 {
274 assert(q != Node::NullPtr);
276 assert(COLOR(q) == RED);
278
279 const Key & qk = KEY(q);
280
281 Node *p = root; // Current node
282 Node *fp = head; // p's parent
283 Node *ffp = fHead; // p's grand parent
284 Node *fffp = ffHead; // p's great grand parent
285 Node *nextNode;
286
287 while (true)
288 {
289 const Key & pk = KEY(p);
290
291 if (COLOR(p) == BLACK && COLOR(LLINK(p)) == RED
292 && COLOR(RLINK(p)) == RED)
293 {
294 flipColors(p); // Rends p red
295 if (COLOR(fp) == RED) // violation of red condition
296 {
299 }
300 }
301
302 if (cmp(qk, pk))
303 {
304 if (LLINK(p) == Node::NullPtr)
305 break;
306 nextNode = LLINK(p);
307 }
308 else
309 {
310 if (RLINK(p) == Node::NullPtr)
311 break;
312 nextNode = RLINK(p);
313 }
314
315 fffp = ffp;
316 ffp = fp;
317 fp = p;
318 p = nextNode;
319 }
320
321 ++node_count;
322
323 const Key & pk = KEY(p);
324 if (cmp(qk, pk))
325 LLINK(p) = q;
326 else
327 RLINK(p) = q;
328
329 if (COLOR(p) == RED) // Violation of red condition
330 restoreRedCondition(q, p, fp, ffp);
331
332 return q;
333 }
334
335 // ===================== DELETION ROUTINES =====================
336
345 Node * searchAndBuildPath(const Key & key) noexcept
346 {
348
349 Node *p = root;
350 path.push(head);
351
352 while (true)
353 {
354 path.push(p);
355
356 const Key & pk = KEY(p);
357
359 {
360# ifdef DEBUG
361 assert(path.size() - 1.0 <= 2*log(node_count + 1)/log(2));
362# endif
363 return p;
364 }
365
366 if (cmp(key, pk))
367 {
368 if (LLINK(p) == Node::NullPtr)
369 {
370# ifdef DEBUG
371 assert(path.size() - 1.0 <= 2*log(node_count + 1)/log(2));
372# endif
373 return p;
374 }
375
376 p = LLINK(p);
377 continue;
378 }
379
380 if (RLINK(p) == Node::NullPtr)
381 {
382# ifdef DEBUG
383 assert(path.size() - 1.0 <= 2*log(node_count + 1)/log(2));
384# endif
385 return p;
386 }
387
388 p = RLINK(p);
389 }
390 }
391
400 void findSuccAndSwap(Node *p, Node *& fp) noexcept
401 {
402 assert(p != Node::NullPtr);
405 assert(LLINK(fp) == p || RLINK(fp) == p);
406
407 /*
408 We save a reference to current stack content because p will be
409 swapped and p's position in stack should be occupied by
410 successor of p
411 */
413
415
416 /* Find succesor while updating searchPath */
417 Node *fSucc = p; // succesor's parent
418 Node *succ = RLINK(p); // Searching starts from p's right child
419
420 path.push(succ);
421 while (LLINK(succ) != Node::NullPtr) // go down to leftmost
422 {
423 fSucc = succ;
424 succ = LLINK(succ);
425 path.push(succ);
426 }
427# ifdef DEBUG
428 assert(path.size() - 1.0 <= 2*log(node_count + 1)/log(2));
429# endif
430
431 /*
432 update old stack entry occupied by p These operations are
433 equivalents to swap old top with current top
434 */
435 refToSearchPath = succ;
436 path.top() = p;
437
438 /* Setting of parent of p to its new child (succ) */
439 if (LLINK(fp) == p)
440 LLINK(fp) = succ;
441 else
442 RLINK(fp) = succ;
443
444 /* Swaps left branches */
445 LLINK(succ) = LLINK(p);
446 LLINK(p) = Node::NullPtr;
447
448 /* For right branches there are two cases */
449 if (RLINK(p) == succ)
450 { /* successor is just right's child of p */
451 RLINK(p) = RLINK(succ);
452 RLINK(succ) = p;
453 fp = succ;
454 }
455 else
456 { /*
457 successor is the leftmost nodo descending from right child of p
458 */
459 Node *succr = RLINK(succ);
460 RLINK(succ) = RLINK(p);
461 LLINK(fSucc) = p;
462 RLINK(p) = succr;
463 fp = fSucc;
464 }
465
466 // Swap of colors
467 Color tmp = COLOR(succ);
468 COLOR(succ) = COLOR(p);
469 COLOR(p) = tmp;
470 }
471
472
483 void balanceDownAndColor(Node *p, Node *& fp, Node *& sp) noexcept
484 {
485 assert(LLINK(fp) == p || RLINK(fp) == p);
486 assert(LLINK(fp) == sp || RLINK(fp) == sp);
487 assert(COLOR(fp) == BLACK);
488 assert(COLOR(sp) == RED);
489 assert(COLOR(p) == BLACK);
490 assert(!path.is_empty());
491
492 /* needed by rotation for links' update. We save a reference to search
493 stack because stack's head will cahnge after rotation */
494 Node *& ffp = path.top();
495
496 assert(LLINK(ffp) == fp || RLINK(ffp) == fp);
497
498 /* balancing down of p, update of out parameters and update of stack
499 entry corresponding to fp */
500 if (LLINK(fp) == p)
501 {
502 sp = LLINK(sp);
504 }
505 else
506 {
507 sp = RLINK(sp);
509 }
510
511 assert(LLINK(fp) == sp || RLINK(fp) == sp);
512 assert(COLOR(ffp) == RED);
513
514 /* coloring for ensuring to apply sibling black cases */
515 COLOR(ffp) = BLACK;
516 COLOR(fp) = RED;
517 }
518
530 {
531 assert(LLINK(fp) == sp || RLINK(fp) == sp);
532 assert(LLINK(sp) == np || RLINK(sp) == np);
533 assert(COLOR(sp) == BLACK);
534 assert(COLOR(np) == RED);
535 assert(!path.is_empty());
536
537 Node *ffp = path.top();
538
539 assert(LLINK(ffp) == fp || RLINK(ffp) == fp);
540
541 /* rotation for downing low fp */
542 if (RLINK(sp) == np)
544 else
546
547 /* coloring for fixing up red black conditions */
548 COLOR(sp) = COLOR(fp);
549 COLOR(fp) = BLACK;
550 COLOR(np) = BLACK;
551 }
552
564 {
565 assert(LLINK(fp) == sp || RLINK(fp) == sp);
566 assert(LLINK(sp) == snp || RLINK(sp) == snp);
567 assert(COLOR(sp) == BLACK);
568 assert(COLOR(snp) == RED);
569 assert(!path.is_empty());
570
571 Node *ffp = path.top();
572
573 assert(LLINK(ffp) == fp || RLINK(ffp) == fp);
574
575 /* double rotation for raising up of snp. snp becomes the new root of
576 sub tree fp */
577 if (LLINK(sp) == snp)
578 {
581 }
582 else
583 {
586 }
587
588 /* coloring for restoring all red black tree conditions */
589 COLOR(snp) = COLOR(fp);
590 COLOR(fp) = BLACK;
591 }
592
599 static void colorSiblingAsRed(Node *sp) noexcept
600 {
601 assert(COLOR(sp) == BLACK);
602 COLOR(sp) = RED;
603 }
604
612 static void colorParentAndSibling(Node *fp, Node *sp) noexcept
613 {
614 assert(LLINK(fp) == sp || RLINK(fp) == sp);
615 assert(COLOR(fp) == RED);
616 assert(COLOR(sp) == BLACK);
617
618 COLOR(fp) = BLACK;
619 COLOR(sp) = RED;
620 }
621
630 {
631 assert(path.top() == q);
632
633 /* look at second item after stack's head. We cannot pop it because
634 successor finding would require stack pushing */
635 Node *fq = path.top(1);
636 Node *p; /* Saves the new child of fp after p has been deleted, this
637 node can be a violating black condition black node */
638
640 assert(LLINK(fq) == q || RLINK(fq) == q);
641
642 /* Deletion step: by pass if there is a Node::NullPtr link or swap
643 with successor */
644 while (1)
645 {
646 if (LLINK(q) == Node::NullPtr) // by pass to the left side
647 {
648 if (LLINK(fq) == q)
649 p = LLINK(fq) = RLINK(q);
650 else
651 p = RLINK(fq) = RLINK(q);
652 break;
653 }
654
655 if (RLINK(q) == Node::NullPtr) // by pass to the right side
656 {
657 if (LLINK(fq) == q)
658 p = LLINK(fq) = LLINK(q);
659 else
660 p = RLINK(fq) = LLINK(q);
661 break;
662 }
663
665 }
666
667 /* if color of deleted node is red, then all red black conditions are
668 met and adjust is not necessary */
669 if (COLOR(q) == RED)
670 {
671 assert(COLOR(p) == BLACK);
672 path.empty();
673 return;
674 }
675
676 /* if color of p is black, then it misses a black node and four condition
677 is violated. However, if p's child is red we can recoloring it black
678 for restoring the missing black node */
679 if (COLOR(p) == RED)
680 {
681 COLOR(p) = BLACK;
682 path.empty();
683 return;
684 }
685
686 /* Bad luck we must do recoloring and/or balancing for restoring the
687 four condition */
688 // p's sibling
689 Node *np, *snp; // p's nephew and nephewg's sibling
690 Node *fp = fq; // we process in function of p
691
692 path.popn(2); // pops deleted node and fp
693
694 /* we examine p and we restore red black properties */
695 while (true)
696 {
697 if (p == root)
698 break;
699
700 Node *sp = getSibling(p, fp);
701
702 /* if sibling is red, we rotate down for assuring that p' sibling
703 to be black */
704 if (COLOR(sp) == RED)
706
707 assert(COLOR(sp) == BLACK);
708
709 /* Compute nephews */
710 if (LLINK(fp) == p)
711 {
712 np = RLINK(sp);
713 snp = LLINK(sp);
714 }
715 else
716 {
717 np = LLINK(sp);
718 snp = RLINK(sp);
719 }
720
721 if (COLOR(np) == RED)
722 {
724 break;
725 }
726
727 if (COLOR(snp) == RED)
728 {
730 break;
731 }
732
733 if (COLOR(fp) == RED)
734 {
736 break;
737 }
738
739 /* color and restart process with fp */
741 p = fp;
742 fp = path.pop(); // colorSiblingAsRed(sp) does not pop it
743 }
744 path.empty();
745 }
746
747 public:
749 using key_type = Key;
750
752 Compare & key_comp() noexcept { return cmp; }
753
755 const Compare & key_comp() const noexcept { return cmp; }
756
758 Compare & get_compare() noexcept { return cmp; }
759
761 [[nodiscard]] constexpr const Compare & get_compare() const noexcept { return cmp; }
762
764 HtdRbTree(Compare __cmp = Compare()) noexcept
765 : head(&headNode),
768 root(headNode.getR()),
769 cmp(__cmp)
770 {
771 RLINK(fHead) = head;
772 RLINK(ffHead) = fHead;
774 COLOR(head) = BLACK;
775 COLOR(fHead) = BLACK;
776 COLOR(ffHead) = BLACK;
777 }
778
780 void swap(HtdRbTree & tree) noexcept
781 {
782 std::swap(root, tree.root);
783 std::swap(node_count, tree.node_count);
784 std::swap(cmp, tree.cmp);
785 }
786
789 : head(&headNode),
792 root(headNode.getR()),
794 node_count(0),
795 cmp()
796 {
797 RLINK(fHead) = head;
798 RLINK(ffHead) = fHead;
800 COLOR(head) = BLACK;
801 COLOR(fHead) = BLACK;
802 COLOR(ffHead) = BLACK;
803 swap(tree);
804 }
805
807 HtdRbTree & operator=(HtdRbTree && tree) noexcept
808 {
809 swap(tree);
810 return *this;
811 }
812
814 HtdRbTree(const HtdRbTree &) = delete;
815
817 HtdRbTree & operator=(const HtdRbTree &) = delete;
818
820 virtual ~HtdRbTree() = default;
821
823 [[nodiscard]] constexpr bool is_empty() const noexcept { return root == Node::NullPtr; }
824
826 [[nodiscard]] constexpr size_t size() const noexcept { return node_count; }
827
830 {
832 node_count = 0;
833 }
834
840 Node * insert(Node *p) noexcept
841 {
842 assert(p != Node::NullPtr);
843 assert(COLOR(p) == RED);
845
846 if (root == Node::NullPtr) [[unlikely]]
847 {
848 root = p;
849 ++node_count;
850 return p;
851 }
852
854 }
855
862 {
863 assert(p != Node::NullPtr);
864 assert(COLOR(p) == RED);
866
867 if (root == Node::NullPtr) [[unlikely]]
868 {
869 root = p;
870 ++node_count;
871 return p;
872 }
873
874 const Key & pk = KEY(p);
875 Node *found = search(pk);
876 if (found != nullptr) [[unlikely]]
877 return found;
878
879 return insert(p);
880 }
881
887 Node * insert_dup(Node *p) noexcept
888 {
889 assert(p != Node::NullPtr);
890 assert(COLOR(p) == RED);
892
893 if (root == Node::NullPtr) [[unlikely]]
894 {
895 root = p;
896 ++node_count;
897 return p;
898 }
899
901 }
902
908 Node * search(const Key & key) const noexcept
909 {
911 return retVal == Node::NullPtr ? nullptr : retVal;
912 }
913
919 Node * remove(const Key & key) noexcept
920 {
921 if (root == Node::NullPtr) [[unlikely]]
922 return nullptr;
923
924 Node *p = searchAndBuildPath(key);
925
926 if (no_equals<Key, Compare>(KEY(p), key, cmp))
927 {
928 path.empty();
929 return nullptr;
930 }
931
933
934 assert(node_count > 0);
935 --node_count;
936
937 p->reset();
938
939 return p;
940 }
941
942
944 Node *& getRoot() noexcept { return root; }
945
948
949 private:
959 static void blackHeight(Node *p, int & max, int bh = 0) noexcept
960 {
961 if (COLOR(p) == BLACK)
962 bh++; // Another seen black node
963
964 /* if a leaf is reached, we must verify max with current bh (number of
965 visited black nodes */
966 if (LLINK(p) == Node::NullPtr && RLINK(p) == Node::NullPtr)
967 {
968 if (max == -1) // This is onbly for the first leaf reached
969 max = bh;
970 assert(bh == max);
971 return;
972 }
973
974 if (LLINK(p) != Node::NullPtr) /* continue counting in the left side */
975 blackHeight(LLINK(p), max, bh);
976
977 if (RLINK(p) != Node::NullPtr) /* continue counting in the right side */
978 blackHeight(RLINK(p), max, bh);
979 }
980
982 static void testNode(Node *p) noexcept
983 {
984 /* verify red condition */
985 COND_assert(COLOR(p) == RED,
986 COLOR(LLINK(p)) == BLACK && COLOR(RLINK(p)) == BLACK);
987
988 int max = -1;
989 int bh = 0;
990
991 blackHeight(p, max, bh);
992 }
993
994 public:
1000 void verifyRedBlack() const
1001 {
1003 }
1004
1010 {
1011 return is_red_black_bst(const_cast<Node *>(root),
1012 const_cast<HtdRbTree *>(this)->cmp);
1013 }
1014
1016 struct Iterator : public BinNodeInfixIterator<Node>
1017 {
1020
1022 : BinNodeInfixIterator<Node>(const_cast<HtdRbTree &>(t).getRoot()) {}
1023 };
1024 };
1025
1030 template <class Key, class Compare = Aleph::less<Key>>
1031 class HtdRbTreeVtl : public HtdRbTree<Key, Compare>
1032 {
1033 public:
1035 using Node = typename Base::Node;
1036 using Base::Base; // Inherit constructors
1037 };
1038
1039} // namespace Aleph
1040
1041#endif /* TPL_HTDRBTREE_H */
@ KEY
Definition btreepic.C:169
Inorder iterator on the nodes of a binary tree.
Fixed length stack.
T & push(const T &data) noexcept
Push a copy of data
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 & top() const noexcept
Return a modifiable referemce to stack's top.
T pop() noexcept
Pop by moving the top of stack.
void empty() noexcept
Empty the stack.
Hybrid red-black tree with virtual node destructor.
typename Base::Node Node
Hybrid top-down/bottom-up red-black tree.
Definition tpl_hRbTree.H:84
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:87
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.
Definition tpl_hRbTree.H:99
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:96
Node headNode
Auxiliary node, parent of root.
Definition tpl_hRbTree.H:95
RbNode< Key > Node
The node type used by this tree.
Definition tpl_hRbTree.H:90
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:97
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:109
static RbNode *const NullPtr
Definition rbNode.H:109
void reset() noexcept
Definition rbNode.H:109
RbNode *& getR() noexcept
Definition rbNode.H:109
static const size_t MaxHeight
Definition rbNode.H:109
__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
constexpr Node *& RLINK(Node *p) noexcept
Return the right tree of p.
Node * searchInBinTree(Node *root, const typename Node::key_type &key, const Compare &cmp=Compare()) noexcept
Search a key in a binary search tree.
constexpr Node *& LLINK(Node *p) noexcept
Return a pointer to left subtree.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
DynList< T > maps(const C &c, Op op)
Classic map operation.
#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:208
#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
Stack implementations backed by dynamic or fixed arrays.
Utility functions for binary tree operations.
Basic binary tree node definitions.