Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_hRbTreeRk.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_HTDRBTREERK_H
46# define TPL_HTDRBTREERK_H
47
48# ifdef DEBUG
49# include <cmath>
50# endif
51# include <stdexcept>
52# include <ah-errors.H>
53# include <tpl_binNode.H>
54# include <tpl_binNodeUtils.H>
55# include <tpl_binNodeXt.H>
56# include <tpl_binTreeOps.H>
57# include <tpl_arrayStack.H>
58# include <rbNodeRk.H>
59
60namespace Aleph
61{
62
91template <class Key, class Compare = Aleph::less<Key>>
93{
94public:
95 using Color = unsigned char;
97
98private:
102
107
109
110 Compare cmp;
111
112 bool less(const Key & k1, const Key & k2) const noexcept
113 { return cmp(k1, k2); }
114
115 bool equals(const Key & k1, const Key & k2) const noexcept
116 { return not cmp(k1, k2) and not cmp(k2, k1); }
117
118 static Node * getSibling(Node *p, Node *fp) noexcept
119 {
120 assert(LLINK(fp) == p || RLINK(fp) == p);
121 return LLINK(fp) == p ? RLINK(fp) : LLINK(fp);
122 }
123
124 // ===================== RANK-AWARE ROTATIONS =====================
125
133 static Node * rotate_to_right_rk(Node *p, Node *fp) noexcept
134 {
135 assert(p != Node::NullPtr);
137
138 Node *q = LLINK(p);
139
140 // q takes p's count (it will be in p's position)
141 COUNT(q) = COUNT(p);
142
143 LLINK(p) = RLINK(q);
144 RLINK(q) = p;
145
146 // Update p's count based on its new children
147 COUNT(p) = COUNT(LLINK(p)) + COUNT(RLINK(p)) + 1;
148
149 if (LLINK(fp) == p)
150 LLINK(fp) = q;
151 else
152 RLINK(fp) = q;
153
154 return q;
155 }
156
158 static Node * rotate_to_left_rk(Node *p, Node *fp) noexcept
159 {
160 assert(p != Node::NullPtr);
162
163 Node *q = RLINK(p);
164
165 COUNT(q) = COUNT(p);
166
167 RLINK(p) = LLINK(q);
168 LLINK(q) = p;
169
170 COUNT(p) = COUNT(LLINK(p)) + COUNT(RLINK(p)) + 1;
171
172 if (LLINK(fp) == p)
173 LLINK(fp) = q;
174 else
175 RLINK(fp) = q;
176
177 return q;
178 }
179
180 // ===================== INSERTION ROUTINES =====================
181
182 void restoreRedCondition(Node *p, Node *& fp, Node *ffp, Node *fffp) noexcept
183 {
184 assert(LLINK(fp) == p || RLINK(fp) == p);
185 assert(COLOR(fp) == RED);
186 assert(COLOR(p) == RED);
187
188 if (fp == root)
189 {
190 COLOR(fp) = BLACK;
191 return;
192 }
193
194 assert(LLINK(ffp) == fp || RLINK(ffp) == fp);
195 assert(COLOR(ffp) == BLACK);
196 assert(LLINK(fffp) == ffp || RLINK(fffp) == ffp);
197
198 COLOR(ffp) = RED;
199
200 if (LLINK(fp) == p && LLINK(ffp) == fp)
201 {
202 COLOR(fp) = BLACK;
204 }
205 else if (RLINK(fp) == p && RLINK(ffp) == fp)
206 {
207 COLOR(fp) = BLACK;
209 }
210 else
211 {
212 COLOR(p) = BLACK;
213 if (RLINK(fp) == p)
214 {
217 }
218 else
219 {
222 }
223 fp = fffp;
224 }
225 }
226
227 static void flipColors(Node *p) noexcept
228 {
229 assert(p != Node::NullPtr);
230 assert(COLOR(p) == BLACK);
231 assert(COLOR(LLINK(p)) == RED && COLOR(RLINK(p)) == RED);
232
233 COLOR(p) = RED;
234 COLOR(LLINK(p)) = COLOR(RLINK(p)) = BLACK;
235 }
236
243 {
244 assert(q != Node::NullPtr);
246 assert(COLOR(q) == RED);
247 assert(COUNT(q) == 1);
248
249 const Key & qk = KEY(q);
250
251 // Track path for count updates
252 Node* insertPath[128];
253 size_t insertPathLen = 0;
254
255 Node *p = root;
256 Node *fp = head;
257 Node *ffp = fHead;
258 Node *fffp = ffHead;
259 Node *nextNode;
260
262
263 while (true)
264 {
265 const Key & pk = KEY(p);
266
267 if (equals(qk, pk)) [[unlikely]]
268 return nullptr; // Duplicate key
269
270 if (COLOR(p) == BLACK && COLOR(LLINK(p)) == RED
271 && COLOR(RLINK(p)) == RED)
272 {
273 flipColors(p);
274 if (COLOR(fp) == RED)
275 {
278 }
279 }
280
281 if (less(qk, pk))
282 {
283 if (LLINK(p) == Node::NullPtr)
284 break;
285 nextNode = LLINK(p);
286 }
287 else
288 {
289 if (RLINK(p) == Node::NullPtr)
290 break;
291 nextNode = RLINK(p);
292 }
293
294 fffp = ffp;
295 ffp = fp;
296 fp = p;
297 p = nextNode;
299 }
300
301 // Perform insertion
302 const Key & pk = KEY(p);
303 if (less(qk, pk))
304 LLINK(p) = q;
305 else
306 RLINK(p) = q;
307
308 if (COLOR(p) == RED)
309 restoreRedCondition(q, p, fp, ffp);
310
311 // Update counts bottom-up - O(log n)
312 for (size_t i = insertPathLen; i > 0; --i)
313 {
314 Node* node = insertPath[i - 1];
315 COUNT(node) = COUNT(LLINK(node)) + COUNT(RLINK(node)) + 1;
316 }
317
318 return q;
319 }
320
322 {
323 assert(q != Node::NullPtr);
325 assert(COLOR(q) == RED);
326 assert(COUNT(q) == 1);
327
328 const Key & qk = KEY(q);
329
330 Node* insertPath[128];
331 size_t insertPathLen = 0;
332
333 Node *p = root;
334 Node *fp = head;
335 Node *ffp = fHead;
336 Node *fffp = ffHead;
337 Node *nextNode;
338
340
341 while (true)
342 {
343 const Key & pk = KEY(p);
344
345 if (COLOR(p) == BLACK && COLOR(LLINK(p)) == RED
346 && COLOR(RLINK(p)) == RED)
347 {
348 flipColors(p);
349 if (COLOR(fp) == RED)
350 {
353 }
354 }
355
356 if (less(qk, pk))
357 {
358 if (LLINK(p) == Node::NullPtr)
359 break;
360 nextNode = LLINK(p);
361 }
362 else
363 {
364 if (RLINK(p) == Node::NullPtr)
365 break;
366 nextNode = RLINK(p);
367 }
368
369 fffp = ffp;
370 ffp = fp;
371 fp = p;
372 p = nextNode;
374 }
375
376 const Key & pk = KEY(p);
377 if (less(qk, pk))
378 LLINK(p) = q;
379 else
380 RLINK(p) = q;
381
382 if (COLOR(p) == RED)
383 restoreRedCondition(q, p, fp, ffp);
384
385 // Update counts bottom-up
386 for (size_t i = insertPathLen; i > 0; --i)
387 {
388 Node* node = insertPath[i - 1];
389 COUNT(node) = COUNT(LLINK(node)) + COUNT(RLINK(node)) + 1;
390 }
391
392 return q;
393 }
394
395 // ===================== DELETION ROUTINES =====================
396
397 Node * searchAndBuildPath(const Key & key) noexcept
398 {
400
401 Node *p = root;
402 path.push(head);
403
404 while (true)
405 {
406 path.push(p);
407
408 const Key & pk = KEY(p);
409
410 if (equals(key, pk))
411 return p;
412
413 if (less(key, pk))
414 {
415 if (LLINK(p) == Node::NullPtr)
416 return p;
417 p = LLINK(p);
418 continue;
419 }
420
421 if (RLINK(p) == Node::NullPtr)
422 return p;
423
424 p = RLINK(p);
425 }
426 }
427
428 void findSuccAndSwap(Node *p, Node *& fp) noexcept
429 {
430 assert(p != Node::NullPtr);
433 assert(LLINK(fp) == p || RLINK(fp) == p);
434
437
438 Node *fSucc = p;
439 Node *succ = RLINK(p);
440
441 path.push(succ);
442 while (LLINK(succ) != Node::NullPtr)
443 {
444 fSucc = succ;
445 succ = LLINK(succ);
446 path.push(succ);
447 }
448
449 refToSearchPath = succ;
450 path.top() = p;
451
452 if (LLINK(fp) == p)
453 LLINK(fp) = succ;
454 else
455 RLINK(fp) = succ;
456
457 LLINK(succ) = LLINK(p);
458 LLINK(p) = Node::NullPtr;
459
460 if (RLINK(p) == succ)
461 {
462 RLINK(p) = RLINK(succ);
463 RLINK(succ) = p;
464 fp = succ;
465 }
466 else
467 {
468 Node *succr = RLINK(succ);
469 RLINK(succ) = RLINK(p);
470 LLINK(fSucc) = p;
471 RLINK(p) = succr;
472 fp = fSucc;
473 }
474
475 Color tmp = COLOR(succ);
476 COLOR(succ) = COLOR(p);
477 COLOR(p) = tmp;
478 // Counts will be recalculated after removal completes
479 }
480
481 void balanceDownAndColor(Node *p, Node *& fp, Node *& sp) noexcept
482 {
483 assert(LLINK(fp) == p || RLINK(fp) == p);
484 assert(LLINK(fp) == sp || RLINK(fp) == sp);
485 assert(COLOR(fp) == BLACK);
486 assert(COLOR(sp) == RED);
487 assert(COLOR(p) == BLACK);
488 assert(!path.is_empty());
489
490 Node *& ffp = path.top();
491 assert(LLINK(ffp) == fp || RLINK(ffp) == fp);
492
493 if (LLINK(fp) == p)
494 {
495 sp = LLINK(sp);
497 }
498 else
499 {
500 sp = RLINK(sp);
502 }
503
504 assert(LLINK(fp) == sp || RLINK(fp) == sp);
505 assert(COLOR(ffp) == RED);
506
507 COLOR(ffp) = BLACK;
508 COLOR(fp) = RED;
509 }
510
512 {
513 assert(LLINK(fp) == sp || RLINK(fp) == sp);
514 assert(LLINK(sp) == np || RLINK(sp) == np);
515 assert(COLOR(sp) == BLACK);
516 assert(COLOR(np) == RED);
517 assert(!path.is_empty());
518
519 Node *ffp = path.top();
520 assert(LLINK(ffp) == fp || RLINK(ffp) == fp);
521
522 if (RLINK(sp) == np)
524 else
526
527 COLOR(sp) = COLOR(fp);
528 COLOR(fp) = BLACK;
529 COLOR(np) = BLACK;
530 }
531
533 {
534 assert(LLINK(fp) == sp || RLINK(fp) == sp);
535 assert(LLINK(sp) == snp || RLINK(sp) == snp);
536 assert(COLOR(sp) == BLACK);
537 assert(COLOR(snp) == RED);
538 assert(!path.is_empty());
539
540 Node *ffp = path.top();
541 assert(LLINK(ffp) == fp || RLINK(ffp) == fp);
542
543 if (LLINK(sp) == snp)
544 {
547 }
548 else
549 {
552 }
553
554 COLOR(snp) = COLOR(fp);
555 COLOR(fp) = BLACK;
556 }
557
558 static void colorSiblingAsRed(Node *sp) noexcept
559 {
560 assert(COLOR(sp) == BLACK);
561 COLOR(sp) = RED;
562 }
563
564 static void colorParentAndSibling(Node *fp, Node *sp) noexcept
565 {
566 assert(LLINK(fp) == sp || RLINK(fp) == sp);
567 assert(COLOR(fp) == RED);
568 assert(COLOR(sp) == BLACK);
569
570 COLOR(fp) = BLACK;
571 COLOR(sp) = RED;
572 }
573
575 static void updateCountRec(Node * p) noexcept
576 {
577 if (p == Node::NullPtr)
578 return;
581 COUNT(p) = COUNT(LLINK(p)) + COUNT(RLINK(p)) + 1;
582 }
583
591 {
592 assert(path.top() == q);
593
594 Node *fq = path.top(1);
595 Node *p;
596
598 assert(LLINK(fq) == q || RLINK(fq) == q);
599
600 while (1)
601 {
602 if (LLINK(q) == Node::NullPtr)
603 {
604 if (LLINK(fq) == q)
605 p = LLINK(fq) = RLINK(q);
606 else
607 p = RLINK(fq) = RLINK(q);
608 break;
609 }
610
611 if (RLINK(q) == Node::NullPtr)
612 {
613 if (LLINK(fq) == q)
614 p = LLINK(fq) = LLINK(q);
615 else
616 p = RLINK(fq) = LLINK(q);
617 break;
618 }
619
621 }
622
623 if (COLOR(q) == RED)
624 {
625 assert(COLOR(p) == BLACK);
626 path.empty();
627 if (root != Node::NullPtr)
629 return;
630 }
631
632 if (COLOR(p) == RED)
633 {
634 COLOR(p) = BLACK;
635 path.empty();
636 if (root != Node::NullPtr)
638 return;
639 }
640
641 Node *np, *snp;
642 Node *fp = fq;
643
644 path.popn(2);
645
646 while (true)
647 {
648 if (p == root)
649 break;
650
651 Node *sp = getSibling(p, fp);
652
653 if (COLOR(sp) == RED)
655
656 assert(COLOR(sp) == BLACK);
657
658 if (LLINK(fp) == p)
659 {
660 np = RLINK(sp);
661 snp = LLINK(sp);
662 }
663 else
664 {
665 np = LLINK(sp);
666 snp = RLINK(sp);
667 }
668
669 if (COLOR(np) == RED)
670 {
672 break;
673 }
674
675 if (COLOR(snp) == RED)
676 {
678 break;
679 }
680
681 if (COLOR(fp) == RED)
682 {
684 break;
685 }
686
688 p = fp;
689 fp = path.pop();
690 }
691
692 path.empty();
693
694 // Update all counts after removal - O(n)
695 if (root != Node::NullPtr)
697 }
698
700 {
701 RLINK(fHead) = head;
702 RLINK(ffHead) = fHead;
704 COUNT(Node::NullPtr) = 0;
705 COLOR(head) = BLACK;
706 COUNT(head) = 0;
707 COLOR(fHead) = BLACK;
708 COUNT(fHead) = 0;
709 COLOR(ffHead) = BLACK;
710 COUNT(ffHead) = 0;
711 }
712
713public:
714 using key_type = Key;
715
716 Compare & key_comp() noexcept { return cmp; }
717 const Compare & key_comp() const noexcept { return cmp; }
718 Compare & get_compare() noexcept { return cmp; }
719 [[nodiscard]] constexpr const Compare & get_compare() const noexcept { return cmp; }
720
721 HtdRbTreeRk(Compare __cmp = Compare()) noexcept
722 : head(&headNode),
725 root(headNode.getR()),
726 cmp(__cmp)
727 {
728 init();
729 }
730
731 void swap(HtdRbTreeRk & tree) noexcept
732 {
733 std::swap(root, tree.root);
734 std::swap(cmp, tree.cmp);
735 }
736
738 : head(&headNode),
741 root(headNode.getR()),
743 cmp()
744 {
745 init();
746 swap(tree);
747 }
748
750 {
751 swap(tree);
752 return *this;
753 }
754
755 HtdRbTreeRk(const HtdRbTreeRk &) = delete;
756 HtdRbTreeRk & operator=(const HtdRbTreeRk &) = delete;
757
758 virtual ~HtdRbTreeRk() = default;
759
760 [[nodiscard]] constexpr bool is_empty() const noexcept { return root == Node::NullPtr; }
761
763 size_t size() const noexcept { return COUNT(root); }
764
766
767 Node * insert(Node *p) noexcept
768 {
769 assert(p != Node::NullPtr);
770 assert(COLOR(p) == RED);
771 COUNT(p) = 1;
772
773 if (root == Node::NullPtr) [[unlikely]]
774 {
775 root = p;
776 return p;
777 }
778
780 }
781
783 {
784 assert(p != Node::NullPtr);
785 assert(COLOR(p) == RED);
786 COUNT(p) = 1;
787
788 if (root == Node::NullPtr) [[unlikely]]
789 {
790 root = p;
791 return p;
792 }
793
794 const Key & pk = KEY(p);
795 Node *found = search(pk);
796 if (found != nullptr) [[unlikely]]
797 return found;
798
799 return insert(p);
800 }
801
802 Node * insert_dup(Node *p) noexcept
803 {
804 assert(p != Node::NullPtr);
805 assert(COLOR(p) == RED);
806 COUNT(p) = 1;
807
808 if (root == Node::NullPtr) [[unlikely]]
809 {
810 root = p;
811 return p;
812 }
813
815 }
816
817 Node * search(const Key & key) const noexcept
818 {
819 Node *p = root;
820 while (p != Node::NullPtr)
821 {
822 const Key & pk = KEY(p);
823 if (equals(key, pk))
824 return p;
825 p = less(key, pk) ? LLINK(p) : RLINK(p);
826 }
827 return nullptr;
828 }
829
830 Node * remove(const Key & key) noexcept
831 {
832 if (root == Node::NullPtr) [[unlikely]]
833 return nullptr;
834
835 Node *p = searchAndBuildPath(key);
836
837 if (not equals(KEY(p), key))
838 {
839 path.empty();
840 return nullptr;
841 }
842
844
845 p->reset();
846
847 return p;
848 }
849
850 Node *& getRoot() noexcept { return root; }
852
853 // ===================== RANK OPERATIONS =====================
854
861 Node * select(size_t i) const
862 {
863 return Aleph::select(root, i);
864 }
865
871 std::pair<long, Node*> position(const Key & key) const noexcept
872 {
873 std::pair<long, Node*> ret_val;
875 inorder_position(root, key, ret_val.second);
876 return ret_val;
877 }
878
886 std::pair<long, Node*> find_position(const Key & key) const noexcept
887 {
888 std::pair<long, Node*> r;
890 find_position(root, key, r.second);
891 return r;
892 }
893
900 Node * remove_pos(size_t i)
901 {
902 ah_out_of_range_error_if(i >= size()) << "remove_pos: position " << i << " out of range";
903 Node * p = select(i);
904 return remove(KEY(p));
905 }
906
918 void split_pos(size_t pos, HtdRbTreeRk & t1, HtdRbTreeRk & t2)
919 {
920 ah_out_of_range_error_if(pos > size()) << "split_pos: position " << pos << " out of range";
921
922 t1.reset();
923 t2.reset();
924
925 while (root != Node::NullPtr)
926 {
927 Node * p = remove_pos(0);
928 if (t1.size() < pos)
929 t1.insert(p);
930 else
931 t2.insert(p);
932 }
933 }
934
940 {
941 if (root == Node::NullPtr)
942 return true;
943
944 // Verify red-black properties
946 return false;
947
948 // Verify counts
949 return verifyCountsRec(root);
950 }
951
952private:
953 static bool verifyCountsRec(Node * p) noexcept
954 {
955 if (p == Node::NullPtr)
956 return true;
957
958 size_t expected = COUNT(LLINK(p)) + COUNT(RLINK(p)) + 1;
959 if (COUNT(p) != expected)
960 return false;
961
962 return verifyCountsRec(LLINK(p)) && verifyCountsRec(RLINK(p));
963 }
964
965public:
967 struct Iterator : public BinNodeInfixIterator<Node>
968 {
971
974 };
975};
976
978template <class Key, class Compare = Aleph::less<Key>>
979class HtdRbTreeRkVtl : public HtdRbTreeRk<Key, Compare>
980{
981public:
983 using Node = typename Base::Node;
984 using Base::Base;
985};
986
987} // namespace Aleph
988
989#endif /* TPL_HTDRBTREERK_H */
990
Exception handling system with formatted messages for Aleph-w.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Definition ah-errors.H:579
@ KEY
Definition btreepic.C:169
Inorder iterator on the nodes of a binary tree.
T & insert(const T &item)
Insert a new item by copy.
Definition htlist.H:1502
Fixed length stack.
T & push(const T &data) noexcept
Push a copy of data
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.
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
void reset() noexcept
Definition htlist.H:516
Hybrid RB tree with rank and virtual destructor.
typename Base::Node Node
Hybrid top-down/bottom-up red-black tree with rank support.
void findSuccAndSwap(Node *p, Node *&fp) noexcept
Node * search(const Key &key) const noexcept
void init() noexcept
Node * insert_dup(Node *p) noexcept
const Compare & key_comp() const noexcept
HtdRbTreeRk(Compare __cmp=Compare()) noexcept
std::pair< long, Node * > find_position(const Key &key) const noexcept
Find position where key would be inserted.
void restoreRedCondition(Node *p, Node *&fp, Node *ffp, Node *fffp) noexcept
constexpr const Compare & get_compare() const noexcept
static void colorParentAndSibling(Node *fp, Node *sp) noexcept
static Node * getSibling(Node *p, Node *fp) noexcept
Node * searchFlipColorsAndInsertDup(Node *q) noexcept
Node * search_or_insert(Node *p) noexcept
unsigned char Color
void balanceDownAndColor(Node *p, Node *&fp, Node *&sp) noexcept
FixedStack< Node * > path
static void flipColors(Node *p) noexcept
static Node * rotate_to_left_rk(Node *p, Node *fp) noexcept
Left rotation with count update.
virtual ~HtdRbTreeRk()=default
void rotateNephewAndColor(Node *fp, Node *sp, Node *np) noexcept
static bool verifyCountsRec(Node *p) noexcept
bool verify() const noexcept
Verify red-black and rank invariants.
void reset() noexcept
Compare & key_comp() noexcept
static void updateCountRec(Node *p) noexcept
Recursively update counts for entire subtree - O(n)
Node *& getRoot() noexcept
size_t size() const noexcept
O(1) size using root count.
bool equals(const Key &k1, const Key &k2) const noexcept
HtdRbTreeRk(HtdRbTreeRk &&tree) noexcept
void split_pos(size_t pos, HtdRbTreeRk &t1, HtdRbTreeRk &t2)
Split tree at position.
Node * select(size_t i) const
Select the i-th smallest element (0-indexed).
HtdRbTreeRk & operator=(const HtdRbTreeRk &)=delete
Node * getRoot() const noexcept
std::pair< long, Node * > position(const Key &key) const noexcept
Find position of a key.
HtdRbTreeRk & operator=(HtdRbTreeRk &&tree) noexcept
RbNodeRk< Key > Node
Compare & get_compare() noexcept
void removeAndFixBlackCondition(Node *q) noexcept
Remove node and fix red-black violations.
void swap(HtdRbTreeRk &tree) noexcept
constexpr bool is_empty() const noexcept
Node * remove(const Key &key) noexcept
HtdRbTreeRk(const HtdRbTreeRk &)=delete
Node * searchFlipColorsAndInsert(Node *q) noexcept
Insert with stack tracking for count updates.
static Node * rotate_to_right_rk(Node *p, Node *fp) noexcept
Right rotation with count update.
Node * insert(Node *p) noexcept
Node * searchAndBuildPath(const Key &key) noexcept
void doubleRotateNephewAndColor(Node *fp, Node *sp, Node *snp) noexcept
bool less(const Key &k1, const Key &k2) const noexcept
static void colorSiblingAsRed(Node *sp) noexcept
Node * remove_pos(size_t i)
Remove element at position i.
Extended Red-Black node with subtree counter.
Definition rbNodeRk.H:84
RbNodeRk *& getR() noexcept
Definition rbNodeRk.H:84
static const size_t MaxHeight
Definition rbNodeRk.H:84
void reset() noexcept
Definition rbNodeRk.H:84
static RbNodeRk *const NullPtr
Definition rbNodeRk.H:84
long inorder_position(Node *r, const typename Node::key_type &key, Node *&p, Compare &cmp) noexcept
Compute the inorder position of a key.
constexpr Node *& RLINK(Node *p) noexcept
Return the right tree of p.
auto & COUNT(Node *p) noexcept
Return the number of nodes of the tree fron p is root.
Node * select(Node *r, const size_t pos)
Iterative selection of a node according to inorder position.
constexpr Node *& LLINK(Node *p) noexcept
Return a pointer to left subtree.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
bool is_red_black_bst_rk(Node *node, Compare &cmp)
Verify that tree rooted at node is a valid red-black BST with counters.
Definition rbNodeRk.H:170
DynList< T > maps(const C &c, Op op)
Classic map operation.
#define COLOR(p)
Definition quadnode.H:58
Red-Black tree node with rank (subtree count).
#define BLACK
Black color constant.
Definition rbNode.H:76
#define RED
Red color constant (newly inserted nodes are red)
Definition rbNode.H:73
Iterator(const HtdRbTreeRk &t) noexcept
Iterator(HtdRbTreeRk &t) noexcept
Stack implementations backed by dynamic or fixed arrays.
Utility functions for binary tree operations.
Extended binary node with subtree count.
Basic binary tree node definitions.
Binary tree operations (split, join, rotate).