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# include <ah-concepts.H>
60
61namespace Aleph
62{
63
92template <class Key, class Compare = Aleph::less<Key>>
95{
96public:
97 using Color = unsigned char;
99
100private:
104
109
111
112 Compare cmp;
113
114 bool less(const Key & k1, const Key & k2) const noexcept
115 { return cmp(k1, k2); }
116
117 bool equals(const Key & k1, const Key & k2) const noexcept
118 { return not cmp(k1, k2) and not cmp(k2, k1); }
119
120 static Node * getSibling(Node *p, Node *fp) noexcept
121 {
122 assert(LLINK(fp) == p || RLINK(fp) == p);
123 return LLINK(fp) == p ? RLINK(fp) : LLINK(fp);
124 }
125
126 // ===================== RANK-AWARE ROTATIONS =====================
127
135 static Node * rotate_to_right_rk(Node *p, Node *fp) noexcept
136 {
137 assert(p != Node::NullPtr);
139
140 Node *q = LLINK(p);
141
142 // q takes p's count (it will be in p's position)
143 COUNT(q) = COUNT(p);
144
145 LLINK(p) = RLINK(q);
146 RLINK(q) = p;
147
148 // Update p's count based on its new children
149 COUNT(p) = COUNT(LLINK(p)) + COUNT(RLINK(p)) + 1;
150
151 if (LLINK(fp) == p)
152 LLINK(fp) = q;
153 else
154 RLINK(fp) = q;
155
156 return q;
157 }
158
160 static Node * rotate_to_left_rk(Node *p, Node *fp) noexcept
161 {
162 assert(p != Node::NullPtr);
164
165 Node *q = RLINK(p);
166
167 COUNT(q) = COUNT(p);
168
169 RLINK(p) = LLINK(q);
170 LLINK(q) = p;
171
172 COUNT(p) = COUNT(LLINK(p)) + COUNT(RLINK(p)) + 1;
173
174 if (LLINK(fp) == p)
175 LLINK(fp) = q;
176 else
177 RLINK(fp) = q;
178
179 return q;
180 }
181
182 // ===================== INSERTION ROUTINES =====================
183
184 void restoreRedCondition(Node *p, Node *& fp, Node *ffp, Node *fffp) noexcept
185 {
186 assert(LLINK(fp) == p || RLINK(fp) == p);
187 assert(COLOR(fp) == RED);
188 assert(COLOR(p) == RED);
189
190 if (fp == root)
191 {
192 COLOR(fp) = BLACK;
193 return;
194 }
195
196 assert(LLINK(ffp) == fp || RLINK(ffp) == fp);
197 assert(COLOR(ffp) == BLACK);
198 assert(LLINK(fffp) == ffp || RLINK(fffp) == ffp);
199
200 COLOR(ffp) = RED;
201
202 if (LLINK(fp) == p && LLINK(ffp) == fp)
203 {
204 COLOR(fp) = BLACK;
206 }
207 else if (RLINK(fp) == p && RLINK(ffp) == fp)
208 {
209 COLOR(fp) = BLACK;
211 }
212 else
213 {
214 COLOR(p) = BLACK;
215 if (RLINK(fp) == p)
216 {
219 }
220 else
221 {
224 }
225 fp = fffp;
226 }
227 }
228
229 static void flipColors(Node *p) noexcept
230 {
231 assert(p != Node::NullPtr);
232 assert(COLOR(p) == BLACK);
233 assert(COLOR(LLINK(p)) == RED && COLOR(RLINK(p)) == RED);
234
235 COLOR(p) = RED;
236 COLOR(LLINK(p)) = COLOR(RLINK(p)) = BLACK;
237 }
238
245 {
246 assert(q != Node::NullPtr);
248 assert(COLOR(q) == RED);
249 assert(COUNT(q) == 1);
250
251 const Key & qk = KEY(q);
252
253 // Track path for count updates
254 Node* insertPath[128];
255 size_t insertPathLen = 0;
256
257 Node *p = root;
258 Node *fp = head;
259 Node *ffp = fHead;
260 Node *fffp = ffHead;
261 Node *nextNode;
262
264
265 while (true)
266 {
267 const Key & pk = KEY(p);
268
269 if (equals(qk, pk)) [[unlikely]]
270 return nullptr; // Duplicate key
271
272 if (COLOR(p) == BLACK && COLOR(LLINK(p)) == RED
273 && COLOR(RLINK(p)) == RED)
274 {
275 flipColors(p);
276 if (COLOR(fp) == RED)
277 {
280 }
281 }
282
283 if (less(qk, pk))
284 {
285 if (LLINK(p) == Node::NullPtr)
286 break;
287 nextNode = LLINK(p);
288 }
289 else
290 {
291 if (RLINK(p) == Node::NullPtr)
292 break;
293 nextNode = RLINK(p);
294 }
295
296 fffp = ffp;
297 ffp = fp;
298 fp = p;
299 p = nextNode;
301 }
302
303 // Perform insertion
304 const Key & pk = KEY(p);
305 if (less(qk, pk))
306 LLINK(p) = q;
307 else
308 RLINK(p) = q;
309
310 if (COLOR(p) == RED)
311 restoreRedCondition(q, p, fp, ffp);
312
313 // Update counts bottom-up - O(log n)
314 for (size_t i = insertPathLen; i > 0; --i)
315 {
316 Node* node = insertPath[i - 1];
317 COUNT(node) = COUNT(LLINK(node)) + COUNT(RLINK(node)) + 1;
318 }
319
320 return q;
321 }
322
324 {
325 assert(q != Node::NullPtr);
327 assert(COLOR(q) == RED);
328 assert(COUNT(q) == 1);
329
330 const Key & qk = KEY(q);
331
332 Node* insertPath[128];
333 size_t insertPathLen = 0;
334
335 Node *p = root;
336 Node *fp = head;
337 Node *ffp = fHead;
338 Node *fffp = ffHead;
339 Node *nextNode;
340
342
343 while (true)
344 {
345 const Key & pk = KEY(p);
346
347 if (COLOR(p) == BLACK && COLOR(LLINK(p)) == RED
348 && COLOR(RLINK(p)) == RED)
349 {
350 flipColors(p);
351 if (COLOR(fp) == RED)
352 {
355 }
356 }
357
358 if (less(qk, pk))
359 {
360 if (LLINK(p) == Node::NullPtr)
361 break;
362 nextNode = LLINK(p);
363 }
364 else
365 {
366 if (RLINK(p) == Node::NullPtr)
367 break;
368 nextNode = RLINK(p);
369 }
370
371 fffp = ffp;
372 ffp = fp;
373 fp = p;
374 p = nextNode;
376 }
377
378 const Key & pk = KEY(p);
379 if (less(qk, pk))
380 LLINK(p) = q;
381 else
382 RLINK(p) = q;
383
384 if (COLOR(p) == RED)
385 restoreRedCondition(q, p, fp, ffp);
386
387 // Update counts bottom-up
388 for (size_t i = insertPathLen; i > 0; --i)
389 {
390 Node* node = insertPath[i - 1];
391 COUNT(node) = COUNT(LLINK(node)) + COUNT(RLINK(node)) + 1;
392 }
393
394 return q;
395 }
396
397 // ===================== DELETION ROUTINES =====================
398
399 Node * searchAndBuildPath(const Key & key) noexcept
400 {
402
403 Node *p = root;
404 path.push(head);
405
406 while (true)
407 {
408 path.push(p);
409
410 const Key & pk = KEY(p);
411
412 if (equals(key, pk))
413 return p;
414
415 if (less(key, pk))
416 {
417 if (LLINK(p) == Node::NullPtr)
418 return p;
419 p = LLINK(p);
420 continue;
421 }
422
423 if (RLINK(p) == Node::NullPtr)
424 return p;
425
426 p = RLINK(p);
427 }
428 }
429
430 void findSuccAndSwap(Node *p, Node *& fp) noexcept
431 {
432 assert(p != Node::NullPtr);
434 assert(fp != Node::NullPtr);
435 assert(LLINK(fp) == p || RLINK(fp) == p);
436
439
440 Node *fSucc = p;
441 Node *succ = RLINK(p);
442
443 path.push(succ);
444 while (LLINK(succ) != Node::NullPtr)
445 {
446 fSucc = succ;
447 succ = LLINK(succ);
448 path.push(succ);
449 }
450
451 refToSearchPath = succ;
452 path.top() = p;
453
454 if (LLINK(fp) == p)
455 LLINK(fp) = succ;
456 else
457 RLINK(fp) = succ;
458
459 LLINK(succ) = LLINK(p);
460 LLINK(p) = Node::NullPtr;
461
462 if (RLINK(p) == succ)
463 {
464 RLINK(p) = RLINK(succ);
465 RLINK(succ) = p;
466 fp = succ;
467 }
468 else
469 {
470 Node *succr = RLINK(succ);
471 RLINK(succ) = RLINK(p);
472 LLINK(fSucc) = p;
473 RLINK(p) = succr;
474 fp = fSucc;
475 }
476
477 Color tmp = COLOR(succ);
478 COLOR(succ) = COLOR(p);
479 COLOR(p) = tmp;
480 // Counts will be recalculated after removal completes
481 }
482
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 Node *& ffp = path.top();
493 assert(LLINK(ffp) == fp || RLINK(ffp) == fp);
494
495 if (LLINK(fp) == p)
496 {
497 sp = LLINK(sp);
499 }
500 else
501 {
502 sp = RLINK(sp);
504 }
505
506 assert(LLINK(fp) == sp || RLINK(fp) == sp);
507 assert(COLOR(ffp) == RED);
508
509 COLOR(ffp) = BLACK;
510 COLOR(fp) = RED;
511 }
512
513 void rotateNephewAndColor(Node *fp, Node *sp, Node *np) noexcept
514 {
515 assert(LLINK(fp) == sp || RLINK(fp) == sp);
516 assert(LLINK(sp) == np || RLINK(sp) == np);
517 assert(COLOR(sp) == BLACK);
518 assert(COLOR(np) == RED);
519 assert(!path.is_empty());
520
521 Node *ffp = path.top();
522 assert(LLINK(ffp) == fp || RLINK(ffp) == fp);
523
524 if (RLINK(sp) == np)
526 else
528
529 COLOR(sp) = COLOR(fp);
530 COLOR(fp) = BLACK;
531 COLOR(np) = BLACK;
532 }
533
535 {
536 assert(LLINK(fp) == sp || RLINK(fp) == sp);
537 assert(LLINK(sp) == snp || RLINK(sp) == snp);
538 assert(COLOR(sp) == BLACK);
539 assert(COLOR(snp) == RED);
540 assert(!path.is_empty());
541
542 Node *ffp = path.top();
543 assert(LLINK(ffp) == fp || RLINK(ffp) == fp);
544
545 if (LLINK(sp) == snp)
546 {
549 }
550 else
551 {
554 }
555
556 COLOR(snp) = COLOR(fp);
557 COLOR(fp) = BLACK;
558 }
559
560 static void colorSiblingAsRed(Node *sp) noexcept
561 {
562 assert(COLOR(sp) == BLACK);
563 COLOR(sp) = RED;
564 }
565
566 static void colorParentAndSibling(Node *fp, Node *sp) noexcept
567 {
568 assert(LLINK(fp) == sp || RLINK(fp) == sp);
569 assert(COLOR(fp) == RED);
570 assert(COLOR(sp) == BLACK);
571
572 COLOR(fp) = BLACK;
573 COLOR(sp) = RED;
574 }
575
577 static void updateCountRec(Node * p) noexcept
578 {
579 if (p == Node::NullPtr)
580 return;
583 COUNT(p) = COUNT(LLINK(p)) + COUNT(RLINK(p)) + 1;
584 }
585
593 {
594 assert(path.top() == q);
595
596 Node *fq = path.top(1);
597 Node *p;
598
600 assert(LLINK(fq) == q || RLINK(fq) == q);
601
602 while (1)
603 {
604 if (LLINK(q) == Node::NullPtr)
605 {
606 if (LLINK(fq) == q)
607 p = LLINK(fq) = RLINK(q);
608 else
609 p = RLINK(fq) = RLINK(q);
610 break;
611 }
612
613 if (RLINK(q) == Node::NullPtr)
614 {
615 if (LLINK(fq) == q)
616 p = LLINK(fq) = LLINK(q);
617 else
618 p = RLINK(fq) = LLINK(q);
619 break;
620 }
621
623 }
624
625 if (COLOR(q) == RED)
626 {
627 assert(COLOR(p) == BLACK);
628 path.empty();
629 if (root != Node::NullPtr)
631 return;
632 }
633
634 if (COLOR(p) == RED)
635 {
636 COLOR(p) = BLACK;
637 path.empty();
638 if (root != Node::NullPtr)
640 return;
641 }
642
643 Node *np, *snp;
644 Node *fp = fq;
645
646 path.popn(2);
647
648 while (true)
649 {
650 if (p == root)
651 break;
652
653 Node *sp = getSibling(p, fp);
654
655 if (COLOR(sp) == RED)
656 balanceDownAndColor(p, fp, sp);
657
658 assert(COLOR(sp) == BLACK);
659
660 if (LLINK(fp) == p)
661 {
662 np = RLINK(sp);
663 snp = LLINK(sp);
664 }
665 else
666 {
667 np = LLINK(sp);
668 snp = RLINK(sp);
669 }
670
671 if (COLOR(np) == RED)
672 {
674 break;
675 }
676
677 if (COLOR(snp) == RED)
678 {
680 break;
681 }
682
683 if (COLOR(fp) == RED)
684 {
686 break;
687 }
688
690 p = fp;
691 fp = path.pop();
692 }
693
694 path.empty();
695
696 // Update all counts after removal - O(n)
697 if (root != Node::NullPtr)
699 }
700
702 {
703 RLINK(fHead) = head;
704 RLINK(ffHead) = fHead;
706 COUNT(Node::NullPtr) = 0;
707 COLOR(head) = BLACK;
708 COUNT(head) = 0;
709 COLOR(fHead) = BLACK;
710 COUNT(fHead) = 0;
711 COLOR(ffHead) = BLACK;
712 COUNT(ffHead) = 0;
713 }
714
715public:
716 using key_type = Key;
717
718 Compare & key_comp() noexcept { return cmp; }
719 const Compare & key_comp() const noexcept { return cmp; }
720 Compare & get_compare() noexcept { return cmp; }
721 [[nodiscard]] constexpr const Compare & get_compare() const noexcept { return cmp; }
722
723 HtdRbTreeRk(Compare __cmp = Compare()) noexcept
724 : head(&headNode),
727 root(headNode.getR()),
728 cmp(__cmp)
729 {
730 init();
731 }
732
733 void swap(HtdRbTreeRk & tree) noexcept
734 {
735 std::swap(root, tree.root);
736 std::swap(cmp, tree.cmp);
737 }
738
740 : head(&headNode),
743 root(headNode.getR()),
745 cmp()
746 {
747 init();
748 swap(tree);
749 }
750
752 {
753 swap(tree);
754 return *this;
755 }
756
757 HtdRbTreeRk(const HtdRbTreeRk &) = delete;
758 HtdRbTreeRk & operator=(const HtdRbTreeRk &) = delete;
759
760 virtual ~HtdRbTreeRk() = default;
761
762 [[nodiscard]] constexpr bool is_empty() const noexcept { return root == Node::NullPtr; }
763
765 size_t size() const noexcept { return COUNT(root); }
766
768
769 Node * insert(Node *p) noexcept
770 {
771 assert(p != Node::NullPtr);
772 assert(COLOR(p) == RED);
773 COUNT(p) = 1;
774
775 if (root == Node::NullPtr) [[unlikely]]
776 {
777 root = p;
778 return p;
779 }
780
782 }
783
785 {
786 assert(p != Node::NullPtr);
787 assert(COLOR(p) == RED);
788 COUNT(p) = 1;
789
790 if (root == Node::NullPtr) [[unlikely]]
791 {
792 root = p;
793 return p;
794 }
795
796 const Key & pk = KEY(p);
797 Node *found = search(pk);
798 if (found != nullptr) [[unlikely]]
799 return found;
800
801 return insert(p);
802 }
803
804 Node * insert_dup(Node *p) noexcept
805 {
806 assert(p != Node::NullPtr);
807 assert(COLOR(p) == RED);
808 COUNT(p) = 1;
809
810 if (root == Node::NullPtr) [[unlikely]]
811 {
812 root = p;
813 return p;
814 }
815
817 }
818
819 Node * search(const Key & key) const noexcept
820 {
821 Node *p = root;
822 while (p != Node::NullPtr)
823 {
824 const Key & pk = KEY(p);
825 if (equals(key, pk))
826 return p;
827 p = less(key, pk) ? LLINK(p) : RLINK(p);
828 }
829 return nullptr;
830 }
831
832 Node * remove(const Key & key) noexcept
833 {
834 if (root == Node::NullPtr) [[unlikely]]
835 return nullptr;
836
837 Node *p = searchAndBuildPath(key);
838
839 if (not equals(KEY(p), key))
840 {
841 path.empty();
842 return nullptr;
843 }
844
846
847 p->reset();
848
849 return p;
850 }
851
852 Node *& getRoot() noexcept { return root; }
854
855 // ===================== RANK OPERATIONS =====================
856
863 Node * select(size_t i) const
864 {
865 return Aleph::select(root, i);
866 }
867
873 std::pair<long, Node*> position(const Key & key) const noexcept
874 {
875 std::pair<long, Node*> ret_val;
877 inorder_position(root, key, ret_val.second);
878 return ret_val;
879 }
880
888 std::pair<long, Node*> find_position(const Key & key) const noexcept
889 {
890 std::pair<long, Node*> r;
892 find_position(root, key, r.second);
893 return r;
894 }
895
902 Node * remove_pos(size_t i)
903 {
904 ah_out_of_range_error_if(i >= size()) << "remove_pos: position " << i << " out of range";
905 Node * p = select(i);
906 return remove(KEY(p));
907 }
908
920 void split_pos(size_t pos, HtdRbTreeRk & t1, HtdRbTreeRk & t2)
921 {
922 ah_out_of_range_error_if(pos > size()) << "split_pos: position " << pos << " out of range";
923
924 t1.reset();
925 t2.reset();
926
927 while (root != Node::NullPtr)
928 {
929 Node * p = remove_pos(0);
930 if (t1.size() < pos)
931 t1.insert(p);
932 else
933 t2.insert(p);
934 }
935 }
936
942 {
943 if (root == Node::NullPtr)
944 return true;
945
946 // Verify red-black properties
948 return false;
949
950 // Verify counts
951 return verifyCountsRec(root);
952 }
953
954private:
955 static bool verifyCountsRec(Node * p) noexcept
956 {
957 if (p == Node::NullPtr)
958 return true;
959
960 size_t expected = COUNT(LLINK(p)) + COUNT(RLINK(p)) + 1;
961 if (COUNT(p) != expected)
962 return false;
963
964 return verifyCountsRec(LLINK(p)) && verifyCountsRec(RLINK(p));
965 }
966
967public:
969 struct Iterator : public BinNodeInfixIterator<Node>
970 {
973
976 };
977};
978
980template <class Key, class Compare = Aleph::less<Key>>
982class HtdRbTreeRkVtl : public HtdRbTreeRk<Key, Compare>
983{
984public:
986 using Node = typename Base::Node;
987 using Base::Base;
988};
989
990} // namespace Aleph
991
992#endif /* TPL_HTDRBTREERK_H */
993
C++20 concepts for constraining comparison functors.
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.
Fixed length 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 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.
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.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
and
Check uniqueness with explicit hash + equality functors.
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
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 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
#define RLINK(i, n)
#define LLINK(i, n)
gsl_rng * r
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).