Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_tdRbTreeRk.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
50# ifndef TPL_TDRBTREERK_H
51# define TPL_TDRBTREERK_H
52
53# include <functional>
54# include <tpl_binNode.H>
55# include <tpl_binNodeUtils.H>
56# include <tpl_binNodeXt.H>
57# include <tpl_binTreeOps.H>
58# include <rbNodeRk.H>
59
60namespace Aleph
61{
62
94template <template <class> class NodeType, typename Key,
95 class Compare = std::less<Key>>
97{
98public:
100 using key_type = Key;
101 using compare_type = Compare;
102
103private:
109 Compare cmp;
110
112 bool less(const Key& a, const Key& b) const noexcept
113 {
114 return cmp(a, b);
115 }
116
118 bool equals(const Key& a, const Key& b) const noexcept
119 {
120 return not cmp(a, b) and not cmp(b, a);
121 }
122
124 static Node* rotate_to_right_rk(Node *p, Node *pp) noexcept
125 {
126 assert(p != Node::NullPtr);
127 assert(pp != Node::NullPtr);
128
129 Node *q = LLINK(p);
130 LLINK(p) = RLINK(q);
131 RLINK(q) = p;
132
133 // Update counters
134 COUNT(p) = COUNT(LLINK(p)) + COUNT(RLINK(p)) + 1;
135 COUNT(q) = COUNT(LLINK(q)) + COUNT(RLINK(q)) + 1;
136
137 if (LLINK(pp) == p)
138 LLINK(pp) = q;
139 else
140 RLINK(pp) = q;
141
142 return q;
143 }
144
146 static Node* rotate_to_left_rk(Node *p, Node *pp) noexcept
147 {
148 assert(p != Node::NullPtr);
149 assert(pp != Node::NullPtr);
150
151 Node *q = RLINK(p);
152 RLINK(p) = LLINK(q);
153 LLINK(q) = p;
154
155 // Update counters
156 COUNT(p) = COUNT(LLINK(p)) + COUNT(RLINK(p)) + 1;
157 COUNT(q) = COUNT(LLINK(q)) + COUNT(RLINK(q)) + 1;
158
159 if (LLINK(pp) == p)
160 LLINK(pp) = q;
161 else
162 RLINK(pp) = q;
163
164 return q;
165 }
166
168 void restoreRedCondition(Node *p, Node *&fp, Node *ffp, Node *fffp) noexcept
169 {
170 assert(LLINK(fp) == p or RLINK(fp) == p);
171 assert(COLOR(fp) == RED);
172 assert(COLOR(p) == RED);
173
174 if (fp == root)
175 {
176 COLOR(fp) = BLACK;
177 return;
178 }
179
180 assert(LLINK(ffp) == fp or RLINK(ffp) == fp);
181 assert(COLOR(ffp) == BLACK);
182 assert(LLINK(fffp) == ffp or RLINK(fffp) == ffp);
183
184 COLOR(ffp) = RED;
185
186 if (LLINK(fp) == p and LLINK(ffp) == fp)
187 {
188 COLOR(fp) = BLACK;
190 }
191 else if (RLINK(fp) == p and RLINK(ffp) == fp)
192 {
193 COLOR(fp) = BLACK;
195 }
196 else
197 {
198 COLOR(p) = BLACK;
199 if (RLINK(fp) == p)
200 {
203 }
204 else
205 {
208 }
209 fp = fffp;
210 }
211 }
212
214 static void flipColors(Node* p) noexcept
215 {
216 assert(p != Node::NullPtr);
217 assert(COLOR(p) == BLACK);
218 assert(COLOR(LLINK(p)) == RED and COLOR(RLINK(p)) == RED);
219
220 COLOR(p) = RED;
221 COLOR(LLINK(p)) = COLOR(RLINK(p)) = BLACK;
222 }
223
228 {
229 assert(q != Node::NullPtr);
230 assert(root != Node::NullPtr);
231 assert(COLOR(q) == RED);
232
233 // Stack to track visited nodes for count updates
234 Node* stack[128];
235 size_t stack_len = 0;
236
237 Node *p = root;
238 Node *fp = head;
239 Node *ffp = fHead;
240 Node *fffp = Node::NullPtr;
241 Node *nextNode;
242
243 stack[stack_len++] = p;
244
245 while (true)
246 {
247 if (equals(KEY(q), KEY(p)))
248 return nullptr; // Duplicate key
249
250 if (COLOR(p) == BLACK and COLOR(LLINK(p)) == RED
251 and COLOR(RLINK(p)) == RED)
252 {
253 flipColors(p);
254 if (COLOR(fp) == RED)
255 {
256 assert(fffp != Node::NullPtr);
258 }
259 }
260
261 if (less(KEY(q), KEY(p)))
262 {
263 if (LLINK(p) == Node::NullPtr)
264 break;
265 nextNode = LLINK(p);
266 }
267 else
268 {
269 if (RLINK(p) == Node::NullPtr)
270 break;
271 nextNode = RLINK(p);
272 }
273
274 fffp = ffp;
275 ffp = fp;
276 fp = p;
277 p = nextNode;
278 stack[stack_len++] = p;
279 }
280
281 // Perform insertion
282 if (less(KEY(q), KEY(p)))
283 LLINK(p) = q;
284 else
285 RLINK(p) = q;
286
287 if (COLOR(p) == RED)
288 restoreRedCondition(q, p, fp, ffp);
289
290 // Update counts bottom-up - O(log n)
291 // Each node's count = left_count + right_count + 1
292 // Children are already correct (leaf has count=1, rotated nodes recalculated)
294
295 return q;
296 }
297
301 {
302 assert(q != Node::NullPtr);
303 assert(root != Node::NullPtr);
304 assert(COLOR(q) == RED);
305
306 Node* stack[128];
307 size_t stack_len = 0;
308
309 Node *p = root;
310 Node *fp = head;
311 Node *ffp = fHead;
312 Node *fffp = Node::NullPtr;
313 Node *nextNode;
314
315 stack[stack_len++] = p;
316
317 while (true)
318 {
319 if (COLOR(p) == BLACK and COLOR(LLINK(p)) == RED
320 and COLOR(RLINK(p)) == RED)
321 {
322 flipColors(p);
323 if (COLOR(fp) == RED)
324 {
325 assert(fffp != Node::NullPtr);
327 }
328 }
329
330 if (less(KEY(q), KEY(p)))
331 {
332 if (LLINK(p) == Node::NullPtr)
333 break;
334 nextNode = LLINK(p);
335 }
336 else
337 {
338 if (RLINK(p) == Node::NullPtr)
339 break;
340 nextNode = RLINK(p);
341 }
342
343 fffp = ffp;
344 ffp = fp;
345 fp = p;
346 p = nextNode;
347 stack[stack_len++] = p;
348 }
349
350 if (less(KEY(q), KEY(p)))
351 LLINK(p) = q;
352 else
353 RLINK(p) = q;
354
355 if (COLOR(p) == RED)
356 restoreRedCondition(q, p, fp, ffp);
357
358 // Update counts bottom-up - O(log n)
360
361 return q;
362 }
363
365 static size_t updateCountRec(Node *p) noexcept
366 {
367 if (p == Node::NullPtr)
368 return 0;
369
370 size_t left_count = updateCountRec(LLINK(p));
371 size_t right_count = updateCountRec(RLINK(p));
372 COUNT(p) = left_count + right_count + 1;
373 return COUNT(p);
374 }
375
379 static void updateCountsFromStack(Node** stack, size_t len) noexcept
380 {
381 // Process bottom-up: children are already correct
382 while (len > 0)
383 {
384 Node* p = stack[--len];
385 COUNT(p) = COUNT(LLINK(p)) + COUNT(RLINK(p)) + 1;
386 }
387 }
388
389
391 static Node* gotoLeftAndColorRed(Node *fp, Node *&ffp) noexcept
392 {
393 assert(fp != Node::NullPtr);
394 assert(ffp != Node::NullPtr);
395 assert(LLINK(fp) != Node::NullPtr);
396
397 Node *p = LLINK(fp);
398
399 if (COLOR(p) == RED)
400 return p;
401
402 Node *sp = RLINK(fp);
403
404 if (COLOR(fp) == BLACK)
405 {
406 assert(COLOR(sp) == RED);
408 COLOR(fp) = RED;
409 COLOR(sp) = BLACK;
410 ffp = sp;
411 sp = RLINK(fp);
412 }
413
414 if (COLOR(LLINK(p)) == BLACK and COLOR(RLINK(p)) == BLACK)
415 {
416 assert(COLOR(fp) == RED);
417
418 COLOR(p) = RED;
419 COLOR(fp) = BLACK;
420
421 Node *np = RLINK(sp);
422 Node *snp = LLINK(sp);
423
424 if (COLOR(snp) == BLACK and COLOR(np) == BLACK)
425 {
426 COLOR(sp) = RED;
427 return p;
428 }
429
430 if (COLOR(np) == RED)
431 {
433 COLOR(sp) = RED;
434 COLOR(np) = BLACK;
435 return p;
436 }
437
438 assert(COLOR(snp) == RED);
439
442 }
443 return p;
444 }
445
447 static Node* gotoRightAndColorRed(Node *fp, Node *&ffp) noexcept
448 {
449 assert(fp != Node::NullPtr);
450 assert(ffp != Node::NullPtr);
451 assert(RLINK(fp) != Node::NullPtr);
452
453 Node *p = RLINK(fp);
454
455 if (COLOR(p) == RED)
456 return p;
457
458 Node *sp = LLINK(fp);
459
460 if (COLOR(fp) == BLACK)
461 {
462 assert(COLOR(sp) == RED);
464 COLOR(fp) = RED;
465 COLOR(sp) = BLACK;
466 ffp = sp;
467 sp = LLINK(fp);
468 }
469
470 if (COLOR(LLINK(p)) == BLACK and COLOR(RLINK(p)) == BLACK)
471 {
472 assert(COLOR(fp) == RED);
473
474 COLOR(p) = RED;
475 COLOR(fp) = BLACK;
476
477 Node *np = LLINK(sp);
478 Node *snp = RLINK(sp);
479
480 if (COLOR(snp) == BLACK and COLOR(np) == BLACK)
481 {
482 COLOR(sp) = RED;
483 return p;
484 }
485
486 if (COLOR(np) == RED)
487 {
489 COLOR(sp) = RED;
490 COLOR(np) = BLACK;
491 return p;
492 }
493
494 assert(COLOR(snp) == RED);
495
498 }
499 return p;
500 }
501
503 static void findSuccAndSwap(Node *p, Node *&fp) noexcept
504 {
505 assert(p != Node::NullPtr);
506 assert(RLINK(p) != Node::NullPtr);
507
508 size_t original_count = COUNT(p);
509
510 Node *fSucc = p;
511 Node *succ = gotoRightAndColorRed(p, fp);
512 Node *ffSucc = fp;
513
514 while (LLINK(succ) != Node::NullPtr)
515 {
516 ffSucc = fSucc;
517 fSucc = succ;
519 }
520
521 if (LLINK(fp) == p)
522 LLINK(fp) = succ;
523 else
524 RLINK(fp) = succ;
525
526 LLINK(succ) = LLINK(p);
527 LLINK(p) = Node::NullPtr;
528
529 if (RLINK(p) == succ)
530 {
531 RLINK(p) = RLINK(succ);
532 RLINK(succ) = p;
533 fSucc = fp;
534 fp = succ;
535 }
536 else
537 {
538 Node *tmp = fp;
539 Node *succr = RLINK(succ);
540
541 RLINK(succ) = RLINK(p);
542 LLINK(fSucc) = p;
543 RLINK(p) = succr;
544 fp = fSucc;
545 fSucc = tmp;
546 }
547
548 Color tmp = COLOR(succ);
549 COLOR(succ) = COLOR(p);
550 COLOR(p) = tmp;
551
552 // Preserve count at successor's new position
553 COUNT(succ) = original_count;
554 }
555
557 static void findPredAndSwap(Node *p, Node *&fp) noexcept
558 {
559 assert(p != Node::NullPtr);
560 assert(LLINK(p) != Node::NullPtr);
561
562 size_t original_count = COUNT(p);
563
564 Node *fPred = p;
566 Node *ffPred = fp;
567
568 while (RLINK(pred) != Node::NullPtr)
569 {
570 ffPred = fPred;
571 fPred = pred;
573 }
574
575 if (LLINK(fp) == p)
576 LLINK(fp) = pred;
577 else
578 RLINK(fp) = pred;
579
580 RLINK(pred) = RLINK(p);
581 RLINK(p) = Node::NullPtr;
582
583 if (LLINK(p) == pred)
584 {
585 LLINK(p) = LLINK(pred);
586 LLINK(pred) = p;
587 fPred = fp;
588 fp = pred;
589 }
590 else
591 {
592 Node *tmp = fp;
593 Node *predl = LLINK(pred);
594
595 LLINK(pred) = LLINK(p);
596 RLINK(fPred) = p;
597 LLINK(p) = predl;
598 fp = fPred;
599 fPred = tmp;
600 }
601
602 Color tmp = COLOR(pred);
603 COLOR(pred) = COLOR(p);
604 COLOR(p) = tmp;
605
607 }
608
611 {
612 if (COLOR(root) == RED)
613 return;
614
615 if (COLOR(LLINK(root)) == BLACK and COLOR(RLINK(root)) == BLACK)
616 COLOR(root) = RED;
617 }
618
621 Node* searchAndColorRed(const Key& key, Node *&fp,
622 Node** stack, size_t& stack_len) noexcept
623 {
624 Node *p = root;
625 fp = head;
626 Node *ffp = fHead;
627
628 stack_len = 0;
629
631 stack[stack_len++] = p;
632
633 while (true)
634 {
635 if (equals(key, KEY(p)))
636 return p;
637
638 ffp = fp;
639 fp = p;
640
641 if (less(key, KEY(p)))
642 {
643 if (LLINK(p) == Node::NullPtr)
644 return p; // Key not found, return current
646 }
647 else
648 {
649 if (RLINK(p) == Node::NullPtr)
650 return p; // Key not found, return current
652 }
653
654 stack[stack_len++] = p;
655 }
656 }
657
659 static void removeAndRendLeafRed(Node *p, Node *fp) noexcept
660 {
661 assert(p != Node::NullPtr);
662 assert(fp != Node::NullPtr);
663
664 while (LLINK(p) != Node::NullPtr or RLINK(p) != Node::NullPtr)
665 {
666 if (RLINK(p) != Node::NullPtr)
668 else if (LLINK(p) != Node::NullPtr)
670 }
671
672 if (LLINK(fp) == p)
673 LLINK(fp) = Node::NullPtr;
674 else
675 RLINK(fp) = Node::NullPtr;
676 }
677
680 {
681 RLINK(fHead) = head;
682 COLOR(Node::NullPtr) = BLACK;
683 COUNT(Node::NullPtr) = 0;
684 COLOR(head) = BLACK;
685 COUNT(head) = 0;
686 }
687
688public:
691 : head(&headNode), fHead(&headParent), root(headNode.getR()), cmp()
692 {
693 init();
694 }
695
697 explicit GenTdRbTreeRk(const Compare & __cmp) noexcept
699 {
700 init();
701 }
702
705 : head(&headNode), fHead(&headParent), root(headNode.getR()),
706 cmp(std::move(other.cmp))
707 {
708 init();
709 root = other.root;
710 other.root = Node::NullPtr;
711 }
712
715 {
716 if (this != &other)
717 {
718 root = other.root;
719 cmp = std::move(other.cmp);
720 other.root = Node::NullPtr;
721 }
722 return *this;
723 }
724
725 GenTdRbTreeRk(const GenTdRbTreeRk &) = delete;
727
730 {
731 root = Node::NullPtr;
732 }
733
735 void swap(GenTdRbTreeRk & other) noexcept
736 {
737 std::swap(root, other.root);
738 std::swap(cmp, other.cmp);
739 }
740
741 virtual ~GenTdRbTreeRk() = default;
742
744 size_t size() const noexcept { return COUNT(root); }
745
747 bool is_empty() const noexcept { return root == Node::NullPtr; }
748
750 Compare & get_compare() noexcept { return cmp; }
751 const Compare & get_compare() const noexcept { return cmp; }
752
756 Node* insert(Node *p) noexcept
757 {
758 assert(p != Node::NullPtr);
759 assert(COLOR(p) == RED);
760 COUNT(p) = 1;
761
762 if (root == Node::NullPtr)
763 {
764 root = p;
765 return p;
766 }
767
769 }
770
774 Node* insert_dup(Node *p) noexcept
775 {
776 assert(p != Node::NullPtr);
777 assert(COLOR(p) == RED);
778 COUNT(p) = 1;
779
780 if (root == Node::NullPtr)
781 {
782 root = p;
783 return p;
784 }
785
787 }
788
793 {
794 assert(p != Node::NullPtr);
795 assert(COLOR(p) == RED);
796 COUNT(p) = 1;
797
798 if (root == Node::NullPtr)
799 {
800 root = p;
801 return p;
802 }
803
804 Node *found = search(KEY(p));
805 if (found != nullptr)
806 return found;
807
809 }
810
814 Node* search(const Key& key) const noexcept
815 {
816 Node* p = root;
817 while (p != Node::NullPtr)
818 {
819 if (equals(key, KEY(p)))
820 return p;
821 p = less(key, KEY(p)) ? LLINK(p) : RLINK(p);
822 }
823 return nullptr;
824 }
825
831 Node* remove(const Key& key) noexcept
832 {
833 if (root == Node::NullPtr)
834 return nullptr;
835
836 Node* stack[128];
837 size_t stack_len = 0;
838
839 Node *fp;
840 Node *p = searchAndColorRed(key, fp, stack, stack_len);
841
842 if (not equals(KEY(p), key))
843 return nullptr;
844
846
847 // Recalculate counts for visited nodes - usually O(log n)
848 // For complex cases with many swaps, fall back to full recalc
849 if (root != Node::NullPtr)
850 {
851 // The stack contains nodes visited during search
852 // After swaps, some may have moved, so do full recalc for safety
854 }
855
856 return p;
857 }
858
860 Node*& getRoot() noexcept { return root; }
862
863 // ===================== RANK OPERATIONS =====================
864
870 Node* select(size_t i) const
871 {
872 return Aleph::select(root, i);
873 }
874
878 std::pair<long, Node*> position(const Key & key) const noexcept
879 {
880 std::pair<long, Node*> ret_val;
882 inorder_position(root, key, ret_val.second);
883 return ret_val;
884 }
885
889 std::pair<long, Node*> find_position(const Key & key) const noexcept
890 {
891 std::pair<long, Node*> r(-2, nullptr);
893 find_position(root, key, r.second);
894 return r;
895 }
896
901 Node* remove_pos(size_t i)
902 {
903 Node* p = select(i);
904 if (p == nullptr)
905 return nullptr;
906 return remove(KEY(p));
907 }
908
914 void split_pos(size_t pos, GenTdRbTreeRk & t1, GenTdRbTreeRk & t2) noexcept
915 {
916 if (root == Node::NullPtr)
917 return;
918
919 if (pos == 0)
920 {
921 t2.root = root;
922 root = Node::NullPtr;
923 return;
924 }
925
926 if (pos >= size())
927 {
928 t1.root = root;
929 root = Node::NullPtr;
930 return;
931 }
932
933 // Simple O(n) implementation
934 size_t count = 0;
936 root = Node::NullPtr;
937 }
938
939private:
940 void split_pos_inorder(Node *p, size_t pos,
942 size_t & count) noexcept
943 {
944 if (p == Node::NullPtr)
945 return;
946
947 Node *left = LLINK(p);
948 Node *right = RLINK(p);
949
950 split_pos_inorder(left, pos, t1, t2, count);
951
952 p->reset();
953 if (count < pos)
954 t1.insert(p);
955 else
956 t2.insert(p);
957 ++count;
958
959 split_pos_inorder(right, pos, t1, t2, count);
960 }
961
962public:
968
975};
976
981template <typename Key, class Compare = std::less<Key>>
982class TdRbTreeRk : public GenTdRbTreeRk<RbNodeRk, Key, Compare>
983{
985public:
986 using Base::Base;
987};
988
993template <typename Key, class Compare = std::less<Key>>
994class TdRbTreeRkVtl : public GenTdRbTreeRk<RbNodeRkVtl, Key, Compare>
995{
997public:
998 using Base::Base;
999};
1000
1001} // namespace Aleph
1002
1003# endif /* TPL_TDRBTREERK_H */
1004
@ 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
Top-down red-black tree with rank support (select/position).
GenTdRbTreeRk(GenTdRbTreeRk &&other) noexcept
Move constructor.
GenTdRbTreeRk(const Compare &__cmp) noexcept
Constructor with comparator.
Node * select(size_t i) const
Select i-th node in order.
Node * searchAndColorRed(const Key &key, Node *&fp, Node **stack, size_t &stack_len) noexcept
Search for key while coloring nodes red for deletion.
static void findPredAndSwap(Node *p, Node *&fp) noexcept
Find predecessor and swap for deletion.
Node * search(const Key &key) const noexcept
Search for a key.
GenTdRbTreeRk(const GenTdRbTreeRk &)=delete
NodeType< Key > Node
Node * getRoot() const noexcept
std::pair< long, Node * > position(const Key &key) const noexcept
Find position of a key.
Node * remove_pos(size_t i)
Remove node at position i.
static Node * rotate_to_left_rk(Node *p, Node *pp) noexcept
Rotate to left with counter update.
const Compare & get_compare() const noexcept
static Node * gotoRightAndColorRed(Node *fp, Node *&ffp) noexcept
Descend to right child for deletion, ensuring red.
Node headParent
Sentinel grandparent node.
void restoreRedCondition(Node *p, Node *&fp, Node *ffp, Node *fffp) noexcept
Restore red-black property after color flip.
static void flipColors(Node *p) noexcept
Flip colors with counter preservation.
Node *& getRoot() noexcept
Get root pointer.
bool less(const Key &a, const Key &b) const noexcept
Returns true if a < b according to comparator.
static size_t updateCountRec(Node *p) noexcept
Recursively update counts in subtree - O(n)
static void updateCountsFromStack(Node **stack, size_t len) noexcept
Update counts for nodes in stack (bottom-up) - O(log n) After rotations, nodes may have moved but the...
void colorRootAsRed() noexcept
Color root red if safe.
Node * insert(Node *p) noexcept
Insert a node.
Node headNode
Sentinel header node (parent of root)
static Node * rotate_to_right_rk(Node *p, Node *pp) noexcept
Rotate to right with counter update.
GenTdRbTreeRk & operator=(GenTdRbTreeRk &&other) noexcept
Move assignment.
GenTdRbTreeRk() noexcept
Default constructor.
size_t size() const noexcept
Get number of nodes O(1)
void split_pos(size_t pos, GenTdRbTreeRk &t1, GenTdRbTreeRk &t2) noexcept
Split tree by position.
void reset() noexcept
Reset tree (does not free nodes)
Compare & get_compare() noexcept
Get comparator.
Node * remove(const Key &key) noexcept
Remove node with given key.
Node * search_or_insert(Node *p) noexcept
Search or insert.
Compare cmp
Comparison functor.
static void findSuccAndSwap(Node *p, Node *&fp) noexcept
Find successor and swap for deletion.
Node *& root
Reference to root (right child of head)
Node * searchFlipColorsAndInsert(Node *q) noexcept
Search for insertion point, flipping colors proactively.
static Node * gotoLeftAndColorRed(Node *fp, Node *&ffp) noexcept
Descend to left child for deletion, ensuring red.
Node * head
Pointer to header.
bool equals(const Key &a, const Key &b) const noexcept
Returns true if a == b (neither a < b nor b < a)
void init() noexcept
Initialize header nodes.
GenTdRbTreeRk & operator=(const GenTdRbTreeRk &)=delete
Node * searchFlipColorsAndInsertDup(Node *q) noexcept
Search for insertion point allowing duplicates.
std::pair< long, Node * > find_position(const Key &key) const noexcept
Find position of a key (even if not in tree).
void swap(GenTdRbTreeRk &other) noexcept
Swap with another tree.
bool verify() const noexcept
Verify tree properties.
bool is_empty() const noexcept
Check if empty.
Node * fHead
Pointer to header's parent.
void split_pos_inorder(Node *p, size_t pos, GenTdRbTreeRk &t1, GenTdRbTreeRk &t2, size_t &count) noexcept
virtual ~GenTdRbTreeRk()=default
Node * insert_dup(Node *p) noexcept
Insert a node allowing duplicates.
static void removeAndRendLeafRed(Node *p, Node *fp) noexcept
Remove node, making it a red leaf.
Top-down red-black tree with rank (virtual destructor).
Top-down red-black tree with rank (no virtual destructor).
long inorder_position(Node *r, const typename Node::key_type &key, Node *&p, Compare &cmp) noexcept
Compute the inorder position of a key.
bool check_rank_tree(Node *root) noexcept
Return true if root is a valid extended binary tree.
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.
Freq_Node * pred
Predecessor node in level-order traversal.
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.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
unsigned char Color
Definition rbNodeRk.H:50
#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 GenTdRbTreeRk &t)
Utility functions for binary tree operations.
Extended binary node with subtree count.
Basic binary tree node definitions.
Binary tree operations (split, join, rotate).