Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
rb-tree.cc
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
38#include <algorithm>
39#include <cmath>
40#include <random>
41#include <set>
42#include <vector>
43#include <functional>
44
45#include <gtest/gtest.h>
46
47#include <tpl_rb_tree.H>
48#include <tpl_hRbTree.H>
49
50using namespace Aleph;
51using namespace testing;
52
53namespace
54{
55 using Tree = Rb_Tree<int>;
56 using Node = Tree::Node;
57
59 using HybridNode = HybridTree::Node;
60
61 struct NodePool
62 {
63 std::vector<Node *> allocated;
64
65 Node * make(const int k)
66 {
67 auto * p = new Node(k);
68 allocated.push_back(p);
69 return p;
70 }
71
72 void forget(const Node * p) noexcept
73 {
74 for (auto & q : allocated)
75 if (q == p)
76 {
77 q = nullptr;
78 return;
79 }
80 }
81
82 ~NodePool()
83 {
84 for (const auto * p : allocated)
85 delete p;
86 }
87 };
88
89 struct HybridNodePool
90 {
91 std::vector<HybridNode *> allocated;
92
93 HybridNode * make(const int k)
94 {
95 auto * p = new HybridNode(k);
96 allocated.push_back(p);
97 return p;
98 }
99
100 void forget(const HybridNode * p) noexcept
101 {
102 for (auto & q : allocated)
103 if (q == p)
104 {
105 q = nullptr;
106 return;
107 }
108 }
109
111 {
112 for (const auto * p : allocated)
113 delete p;
114 }
115 };
116
117 std::vector<int> inorder_keys(Node * root)
118 {
119 std::vector<int> keys;
120 if (root == Node::NullPtr)
121 return keys;
122
123 auto left = inorder_keys(LLINK(root));
124 keys.insert(keys.end(), left.begin(), left.end());
125 keys.push_back(KEY(root));
126 auto right = inorder_keys(RLINK(root));
127 keys.insert(keys.end(), right.begin(), right.end());
128 return keys;
129 }
130
131 size_t count_nodes(Node * root)
132 {
133 if (root == Node::NullPtr)
134 return 0;
135 return 1 + count_nodes(LLINK(root)) + count_nodes(RLINK(root));
136 }
137
138 void assert_valid_tree(Tree & tree)
139 {
140 ASSERT_TRUE(tree.verify()) << "Red-black tree invariant violated";
141 ASSERT_TRUE(check_bst(tree.getRoot(), tree.key_comp())) << "BST property violated";
142 }
143
144 bool tree_is_empty(Tree & tree)
145 {
146 return tree.getRoot() == Node::NullPtr;
147 }
148
149 template <typename NodeT>
151 {
152 if (root == NodeT::NullPtr)
153 return 0;
155 }
156
157 template <typename NodeT>
158 std::vector<int> inorder_keys_generic(NodeT * root)
159 {
160 std::vector<int> keys;
161 if (root == NodeT::NullPtr)
162 return keys;
163
164 auto left = inorder_keys_generic(LLINK(root));
165 keys.insert(keys.end(), left.begin(), left.end());
166 keys.push_back(KEY(root));
167 auto right = inorder_keys_generic(RLINK(root));
168 keys.insert(keys.end(), right.begin(), right.end());
169 return keys;
170 }
171
173 {
174 ASSERT_TRUE(tree.verify()) << "HtdRbTree red-black invariant violated";
175 ASSERT_TRUE(check_bst(tree.getRoot(), tree.key_comp())) << "BST property violated";
176 }
177}
178
179// ============================================================================
180// Basic Operations Tests
181// ============================================================================
182
184{
185 Tree tree;
186
187 EXPECT_EQ(tree.getRoot(), Node::NullPtr);
188 EXPECT_EQ(tree.search(42), nullptr);
189 EXPECT_TRUE(tree.verify());
190}
191
193{
194 Tree tree;
195 NodePool pool;
196
197 auto * p = pool.make(42);
198 auto * inserted = tree.insert(p);
199
201 EXPECT_NE(tree.getRoot(), Node::NullPtr);
202 EXPECT_EQ(tree.getRoot(), p);
203 EXPECT_EQ(count_nodes(tree.getRoot()), 1u);
204 assert_valid_tree(tree);
205}
206
208{
209 Tree tree;
210 NodePool pool;
211
212 for (int k : {5, 3, 7, 1, 4, 6, 8})
213 {
214 auto * p = pool.make(k);
215 ASSERT_NE(tree.insert(p), nullptr);
216 }
217
218 EXPECT_EQ(count_nodes(tree.getRoot()), 7u);
219 assert_valid_tree(tree);
220
221 auto keys = inorder_keys(tree.getRoot());
222 EXPECT_EQ(keys, (std::vector<int>{1, 3, 4, 5, 6, 7, 8}));
223}
224
226{
227 Tree tree;
228 NodePool pool;
229
230 auto * p1 = pool.make(10);
231 EXPECT_NE(tree.insert(p1), nullptr);
232
233 auto * p2 = pool.make(10);
234 EXPECT_EQ(tree.insert(p2), nullptr);
235
236 EXPECT_EQ(count_nodes(tree.getRoot()), 1u);
237 assert_valid_tree(tree);
238}
239
240// Tests for optimistic search edge cases
241// These verify that duplicates are correctly detected at various tree levels
242
244{
245 /*
246 * Build tree where duplicate will be at non-root level
247 * 10
248 * / \
249 * 5 15
250 */
251 // Try to insert 5 again - duplicate at intermediate level (left child of root)
252 Tree tree;
253 NodePool pool;
254
255 ASSERT_NE(tree.insert(pool.make(10)), nullptr);
256 ASSERT_NE(tree.insert(pool.make(5)), nullptr);
257 ASSERT_NE(tree.insert(pool.make(15)), nullptr);
258
259 // Try to insert duplicate of intermediate node
260 auto * dup = pool.make(5);
261 EXPECT_EQ(tree.insert(dup), nullptr) << "Should reject duplicate at intermediate level";
262 EXPECT_EQ(count_nodes(tree.getRoot()), 3u);
263 assert_valid_tree(tree);
264}
265
267{
268 // Build tree where we only go left to find duplicate
269 // 50
270 // /
271 // 30
272 // /
273 // 10
274 // Duplicate of 10 requires going left three times
275 Tree tree;
276 NodePool pool;
277
278 ASSERT_NE(tree.insert(pool.make(50)), nullptr);
279 ASSERT_NE(tree.insert(pool.make(30)), nullptr);
280 ASSERT_NE(tree.insert(pool.make(10)), nullptr);
281
282 auto * dup = pool.make(10);
283 EXPECT_EQ(tree.insert(dup), nullptr) << "Should reject duplicate after left descents";
284 EXPECT_EQ(count_nodes(tree.getRoot()), 3u);
285 assert_valid_tree(tree);
286}
287
289{
290 // Build a larger tree and test duplicate detection deep in the structure
291 Tree tree;
292 NodePool pool;
293
294 // Insert in order that creates a balanced-ish tree
295 for (int k : {50, 25, 75, 10, 30, 60, 80, 5, 15, 27, 35})
296 ASSERT_NE(tree.insert(pool.make(k)), nullptr);
297
298 // Now try duplicates at various depths
299 EXPECT_EQ(tree.insert(pool.make(50)), nullptr) << "Duplicate at root";
300 EXPECT_EQ(tree.insert(pool.make(25)), nullptr) << "Duplicate at level 1";
301 EXPECT_EQ(tree.insert(pool.make(10)), nullptr) << "Duplicate at level 2";
302 EXPECT_EQ(tree.insert(pool.make(5)), nullptr) << "Duplicate at deepest level";
303 EXPECT_EQ(tree.insert(pool.make(35)), nullptr) << "Duplicate after mixed descent";
304
305 EXPECT_EQ(count_nodes(tree.getRoot()), 11u);
306 assert_valid_tree(tree);
307}
308
310{
311 Tree tree;
312 NodePool pool;
313
314 for (int i = 0; i < 5; ++i)
315 ASSERT_NE(tree.insert_dup(pool.make(42)), nullptr);
316
317 EXPECT_EQ(count_nodes(tree.getRoot()), 5u);
318 assert_valid_tree(tree);
319
320 auto keys = inorder_keys(tree.getRoot());
321 EXPECT_EQ(keys, (std::vector<int>{42, 42, 42, 42, 42}));
322}
323
325{
326 Tree tree;
327 NodePool pool;
328
329 for (int k : {1, 2, 3, 4, 5})
330 tree.insert(pool.make(k));
331
332 for (int k : {1, 2, 3, 4, 5})
333 {
334 auto * found = tree.search(k);
335 ASSERT_NE(found, nullptr);
336 EXPECT_EQ(KEY(found), k);
337 }
338
339 assert_valid_tree(tree);
340}
341
343{
344 Tree tree;
345 NodePool pool;
346
347 for (int k : {1, 3, 5})
348 tree.insert(pool.make(k));
349
350 EXPECT_EQ(tree.search(2), nullptr);
351 EXPECT_EQ(tree.search(4), nullptr);
352 EXPECT_EQ(tree.search(0), nullptr);
353 EXPECT_EQ(tree.search(6), nullptr);
354
355 assert_valid_tree(tree);
356}
357
359{
360 Tree tree;
361 NodePool pool;
362
363 // Insert via search_or_insert
364 auto * p1 = pool.make(10);
365 auto * ret1 = tree.search_or_insert(p1);
366 EXPECT_EQ(ret1, p1);
367 EXPECT_EQ(count_nodes(tree.getRoot()), 1u);
368
369 // Search existing via search_or_insert
370 auto * p2 = pool.make(10);
371 auto * ret2 = tree.search_or_insert(p2);
372 EXPECT_NE(ret2, p2); // Should return existing node
373 EXPECT_EQ(KEY(ret2), 10);
374 EXPECT_EQ(count_nodes(tree.getRoot()), 1u);
375
376 assert_valid_tree(tree);
377}
378
379// ============================================================================
380// Remove Tests
381// ============================================================================
382
384{
385 Tree tree;
386 NodePool pool;
387
388 for (int k : {1, 2, 3, 4, 5})
389 tree.insert(pool.make(k));
390
391 auto * removed = tree.remove(3);
392 ASSERT_NE(removed, nullptr);
393 EXPECT_EQ(KEY(removed), 3);
394 pool.forget(removed);
395 delete removed;
396
397 EXPECT_EQ(count_nodes(tree.getRoot()), 4u);
398 EXPECT_EQ(tree.search(3), nullptr);
399 assert_valid_tree(tree);
400
401 auto keys = inorder_keys(tree.getRoot());
402 EXPECT_EQ(keys, (std::vector<int>{1, 2, 4, 5}));
403}
404
406{
407 Tree tree;
408 NodePool pool;
409
410 for (int k : {1, 3, 5})
411 tree.insert(pool.make(k));
412
413 EXPECT_EQ(tree.remove(2), nullptr);
414 EXPECT_EQ(tree.remove(4), nullptr);
415 EXPECT_EQ(count_nodes(tree.getRoot()), 3u);
416
417 assert_valid_tree(tree);
418}
419
421{
422 Tree tree;
423
424 EXPECT_EQ(tree.remove(42), nullptr);
426}
427
429{
430 Tree tree;
431 NodePool pool;
432
433 tree.insert(pool.make(5));
434 tree.insert(pool.make(3));
435 tree.insert(pool.make(7));
436
437 auto * removed = tree.remove(5);
438 ASSERT_NE(removed, nullptr);
439 EXPECT_EQ(KEY(removed), 5);
440 pool.forget(removed);
441 delete removed;
442
443 EXPECT_EQ(count_nodes(tree.getRoot()), 2u);
444 assert_valid_tree(tree);
445}
446
448{
449 Tree tree;
450 NodePool pool;
451
452 std::vector<int> keys = {5, 3, 7, 1, 4, 6, 8};
453 for (int k : keys)
454 tree.insert(pool.make(k));
455
456 for (int k : keys)
457 {
458 auto * removed = tree.remove(k);
459 ASSERT_NE(removed, nullptr) << "Failed to remove " << k;
460 pool.forget(removed);
461 delete removed;
462 assert_valid_tree(tree);
463 }
464
466}
467
469{
470 Tree tree;
471 NodePool pool;
472
473 for (int k = 1; k <= 10; ++k)
474 tree.insert(pool.make(k));
475
476 for (int k = 1; k <= 10; ++k)
477 {
478 auto * removed = tree.remove(k);
479 ASSERT_NE(removed, nullptr) << "Failed to remove " << k;
480 pool.forget(removed);
481 delete removed;
482 assert_valid_tree(tree);
483 }
484
486}
487
489{
490 Tree tree;
491 NodePool pool;
492
493 for (int k = 1; k <= 10; ++k)
494 tree.insert(pool.make(k));
495
496 for (int k = 10; k >= 1; --k)
497 {
498 auto * removed = tree.remove(k);
499 ASSERT_NE(removed, nullptr) << "Failed to remove " << k;
500 pool.forget(removed);
501 delete removed;
502 assert_valid_tree(tree);
503 }
504
506}
507
509{
510 Tree tree;
511 NodePool pool;
512
513 constexpr int key = 7;
514 for (int i = 0; i < 4; ++i)
515 ASSERT_NE(tree.insert_dup(pool.make(key)), nullptr);
516
517 for (int remaining = 4; remaining > 0; --remaining)
518 {
519 auto * removed = tree.remove(key);
520 ASSERT_NE(removed, nullptr);
521 EXPECT_EQ(KEY(removed), key);
522 pool.forget(removed);
523 delete removed;
524
525 EXPECT_EQ(count_nodes(tree.getRoot()),
526 static_cast<size_t>(remaining - 1));
527 assert_valid_tree(tree);
528 }
529
530 EXPECT_EQ(tree.remove(key), nullptr);
532}
533
534// ============================================================================
535// Red-Black Properties Tests
536// ============================================================================
537
539{
540 Tree tree;
541 NodePool pool;
542
543 tree.insert(pool.make(5));
544 assert_valid_tree(tree);
545
546 tree.insert(pool.make(3));
547 tree.insert(pool.make(7));
548 tree.insert(pool.make(1));
549 tree.insert(pool.make(4));
550
551 assert_valid_tree(tree);
552}
553
555{
556 Tree tree;
557 NodePool pool;
558
559 // Insert in a pattern that would cause consecutive reds without fixing
560 for (int k : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
561 {
562 tree.insert(pool.make(k));
563 assert_valid_tree(tree);
564 }
565}
566
568{
569 Tree tree;
570 NodePool pool;
571
572 std::mt19937 rng(42);
573 std::uniform_int_distribution<int> dist(0, 1000);
574
575 for (int i = 0; i < 100; ++i)
576 {
577 auto * p = pool.make(dist(rng));
578 tree.insert(p);
579 // Note: duplicates will fail to insert, that's ok
580 }
581
582 assert_valid_tree(tree);
583}
584
585// ============================================================================
586// Edge Cases
587// ============================================================================
588
590{
591 Tree tree;
592 NodePool pool;
593
594 auto * p = pool.make(42);
595 tree.insert(p);
596
597 EXPECT_EQ(tree.search(42), p);
598
599 auto * removed = tree.remove(42);
600 EXPECT_EQ(removed, p);
602 pool.forget(removed);
603 delete removed;
604}
605
607{
608 Tree tree;
609 NodePool pool;
610
611 for (int k = 10; k >= 1; --k)
612 tree.insert(pool.make(k));
613
614 EXPECT_EQ(count_nodes(tree.getRoot()), 10u);
615 assert_valid_tree(tree);
616
617 auto keys = inorder_keys(tree.getRoot());
618 EXPECT_EQ(keys, (std::vector<int>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}));
619}
620
622{
623 Tree tree;
624 NodePool pool;
625
626 for (int k = 1; k <= 10; ++k)
627 tree.insert(pool.make(k));
628
629 EXPECT_EQ(count_nodes(tree.getRoot()), 10u);
630 assert_valid_tree(tree);
631
632 auto keys = inorder_keys(tree.getRoot());
633 EXPECT_EQ(keys, (std::vector<int>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}));
634}
635
636// ============================================================================
637// Custom Comparator Tests
638// ============================================================================
639
641{
643 using NodeGt = TreeGt::Node;
644
645 TreeGt tree;
646 std::vector<NodeGt *> nodes;
647
648 for (int k : {1, 2, 3, 4, 5})
649 {
650 auto * p = new NodeGt(k);
651 nodes.push_back(p);
652 tree.insert(p);
653 }
654
655 EXPECT_EQ(count_nodes(tree.getRoot()), 5u);
656 EXPECT_TRUE(tree.verify());
657
658 // With greater<int>, inorder should be descending
659 std::vector<int> keys;
660 std::function<void(NodeGt*)> collect = [&](NodeGt* r) {
661 if (r == NodeGt::NullPtr) return;
662 collect(LLINK(r));
663 keys.push_back(KEY(r));
664 collect(RLINK(r));
665 };
666 collect(tree.getRoot());
667
668 EXPECT_EQ(keys, (std::vector<int>{5, 4, 3, 2, 1}));
669
670 for (auto * p : nodes)
671 delete p;
672}
673
674// ============================================================================
675// Stress Tests
676// ============================================================================
677
679{
680 Tree tree;
681 NodePool pool;
682 std::set<int> oracle;
683
684 std::mt19937 rng(42);
685 std::uniform_int_distribution<int> dist(0, 500);
686
687 // Insert phase
688 for (int i = 0; i < 200; ++i)
689 {
690 int k = dist(rng);
691 auto * p = pool.make(k);
692 if (tree.insert(p) != nullptr)
693 oracle.insert(k);
694 else
695 {
696 pool.forget(p);
697 delete p;
698 }
699
700 ASSERT_EQ(count_nodes(tree.getRoot()), oracle.size());
701 assert_valid_tree(tree);
702 }
703
704 // Verify all elements
705 auto keys = inorder_keys(tree.getRoot());
706 EXPECT_EQ(keys, std::vector<int>(oracle.begin(), oracle.end()));
707
708 // Search phase
709 for (int i = 0; i < 100; ++i)
710 {
711 int k = dist(rng);
712 auto * found = tree.search(k);
713 if (oracle.count(k))
714 {
715 ASSERT_NE(found, nullptr);
716 EXPECT_EQ(KEY(found), k);
717 }
718 else
719 EXPECT_EQ(found, nullptr);
720
721 assert_valid_tree(tree);
722 }
723
724 // Remove phase
725 for (int i = 0; i < 150; ++i)
726 {
727 int k = dist(rng);
728 auto * removed = tree.remove(k);
729 if (oracle.count(k))
730 {
731 ASSERT_NE(removed, nullptr);
733 oracle.erase(k);
734 pool.forget(removed);
735 delete removed;
736 }
737 else
738 EXPECT_EQ(removed, nullptr);
739
740 ASSERT_EQ(count_nodes(tree.getRoot()), oracle.size());
741 assert_valid_tree(tree);
742 }
743
744 // Final verification
745 keys = inorder_keys(tree.getRoot());
746 EXPECT_EQ(keys, std::vector<int>(oracle.begin(), oracle.end()));
747}
748
750{
751 Tree tree;
752 NodePool pool;
753
754 const int N = 1000;
755
756 // Insert N elements
757 for (int k = 0; k < N; ++k)
758 tree.insert(pool.make(k));
759
760 EXPECT_EQ(count_nodes(tree.getRoot()), static_cast<size_t>(N));
761 assert_valid_tree(tree);
762
763 // Remove half
764 for (int k = 0; k < N; k += 2)
765 {
766 auto * removed = tree.remove(k);
767 ASSERT_NE(removed, nullptr);
768 pool.forget(removed);
769 delete removed;
770 }
771
772 EXPECT_EQ(count_nodes(tree.getRoot()), static_cast<size_t>(N / 2));
773 assert_valid_tree(tree);
774}
775
776// ============================================================================
777// Iterator Tests
778// ============================================================================
779
781{
782 Tree tree;
783 Tree::Iterator it(tree);
784
786}
787
789{
790 Tree tree;
791 NodePool pool;
792
793 std::vector<int> expected = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
794 for (int k : expected)
795 tree.insert(pool.make(k));
796
797 std::vector<int> result;
798 for (Tree::Iterator it(tree); it.has_curr(); it.next())
799 result.push_back(KEY(it.get_curr()));
800
801 EXPECT_EQ(result, expected);
802}
803
805{
806 Tree tree;
807 NodePool pool;
808
809 for (int k : {1, 2, 3, 4, 5})
810 tree.insert(pool.make(k));
811
812 auto * removed = tree.remove(3);
813 pool.forget(removed);
814 delete removed;
815
816 std::vector<int> result;
817 for (Tree::Iterator it(tree); it.has_curr(); it.next())
818 result.push_back(KEY(it.get_curr()));
819
820 EXPECT_EQ(result, (std::vector<int>{1, 2, 4, 5}));
821}
822
823// ============================================================================
824// Verify Method Tests
825// ============================================================================
826
828{
829 Tree tree;
830 NodePool pool;
831
832 for (int k : {5, 3, 7, 1, 4, 6, 8})
833 tree.insert(pool.make(k));
834
835 EXPECT_TRUE(tree.verify());
836}
837
838// ============================================================================
839// Size and Empty Method Tests
840// ============================================================================
841
843{
844 Tree tree;
845 NodePool pool;
846
847 EXPECT_TRUE(tree.is_empty());
848
849 tree.insert(pool.make(1));
850 EXPECT_FALSE(tree.is_empty());
851
852 auto * removed = tree.remove(1);
853 pool.forget(removed);
854 delete removed;
855 EXPECT_TRUE(tree.is_empty());
856}
857
859{
860 Tree tree;
861 NodePool pool;
862
863 EXPECT_EQ(tree.size(), 0u);
864
865 for (int k = 1; k <= 10; ++k)
866 {
867 tree.insert(pool.make(k));
868 EXPECT_EQ(tree.size(), static_cast<size_t>(k));
869 }
870
871 for (int k = 1; k <= 5; ++k)
872 {
873 auto * removed = tree.remove(k);
874 pool.forget(removed);
875 delete removed;
876 }
877 EXPECT_EQ(tree.size(), 5u);
878}
879
880// ============================================================================
881// Swap and Move Semantics Tests
882// ============================================================================
883
885{
886 Tree tree1;
887 Tree tree2;
888 NodePool pool;
889
890 tree1.insert(pool.make(1));
891 tree1.insert(pool.make(2));
892 tree1.insert(pool.make(3));
893
894 tree2.insert(pool.make(10));
895 tree2.insert(pool.make(11));
896
898
899 EXPECT_EQ(count_nodes(tree1.getRoot()), 2u);
900 EXPECT_EQ(count_nodes(tree2.getRoot()), 3u);
901
902 auto keys1 = inorder_keys(tree1.getRoot());
903 EXPECT_EQ(keys1, (std::vector<int>{10, 11}));
904
905 auto keys2 = inorder_keys(tree2.getRoot());
906 EXPECT_EQ(keys2, (std::vector<int>{1, 2, 3}));
907
910}
911
913{
914 Tree tree1;
915 auto * p1 = new Node(1);
916 auto * p2 = new Node(2);
917 auto * p3 = new Node(3);
918 tree1.insert(p1);
919 tree1.insert(p2);
920 tree1.insert(p3);
921
922 Tree tree2(std::move(tree1));
923
925 EXPECT_EQ(tree2.size(), 3u);
927
928 // Clean up
929 delete tree2.remove(1);
930 delete tree2.remove(2);
931 delete tree2.remove(3);
932}
933
935{
936 Tree tree1;
937 Tree tree2;
938 auto * p1 = new Node(1);
939 auto * p2 = new Node(2);
940 tree1.insert(p1);
941 tree1.insert(p2);
942
943 tree2 = std::move(tree1);
944
946 EXPECT_EQ(tree2.size(), 2u);
948
949 delete tree2.remove(1);
950 delete tree2.remove(2);
951}
952
953// ============================================================================
954// Hybrid red-black tree (tpl_hRbTree.H) compatibility tests
955// ============================================================================
956
958{
959 HybridTree tree;
960 EXPECT_EQ(tree.getRoot(), HybridNode::NullPtr);
961 EXPECT_TRUE(tree.is_empty());
962 EXPECT_EQ(tree.size(), 0u);
963 EXPECT_EQ(tree.search(42), nullptr);
964 EXPECT_TRUE(tree.verify());
965 EXPECT_TRUE(check_bst(tree.getRoot(), tree.key_comp()));
966}
967
969{
970 HybridTree tree;
971 HybridNodePool pool;
972
973 auto * p1 = pool.make(10);
974 EXPECT_NE(tree.insert(p1), nullptr);
975 EXPECT_EQ(tree.size(), 1u);
976
977 auto * p2 = pool.make(10);
978 EXPECT_EQ(tree.insert(p2), nullptr);
979 EXPECT_EQ(tree.size(), 1u);
980
981 EXPECT_TRUE(tree.verify());
982 EXPECT_TRUE(check_bst(tree.getRoot(), tree.key_comp()));
983}
984
986{
987 HybridTree tree;
988 HybridNodePool pool;
989
990 for (int i = 0; i < 5; ++i)
991 ASSERT_NE(tree.insert_dup(pool.make(42)), nullptr);
992
993 EXPECT_EQ(tree.size(), 5u);
994 EXPECT_EQ(count_nodes_generic(tree.getRoot()), 5u);
995 EXPECT_TRUE(tree.verify());
996 EXPECT_TRUE(check_bst(tree.getRoot(), tree.key_comp()));
997}
998
1000{
1001 HybridTree tree;
1002 HybridNodePool pool;
1003
1004 auto * p1 = pool.make(10);
1005 auto * ret1 = tree.search_or_insert(p1);
1006 EXPECT_EQ(ret1, p1);
1007 EXPECT_EQ(tree.size(), 1u);
1008
1009 auto * p2 = pool.make(10);
1010 auto * ret2 = tree.search_or_insert(p2);
1011 EXPECT_NE(ret2, p2);
1012 EXPECT_EQ(KEY(ret2), 10);
1013 EXPECT_EQ(tree.size(), 1u);
1014
1015 EXPECT_TRUE(tree.verify());
1016 EXPECT_TRUE(check_bst(tree.getRoot(), tree.key_comp()));
1017}
1018
1020{
1021 HybridTree tree;
1022 HybridNodePool pool;
1023
1024 for (int k : {1, 2, 3, 4, 5})
1025 tree.insert(pool.make(k));
1026
1027 auto * removed = tree.remove(3);
1028 ASSERT_NE(removed, nullptr);
1029 EXPECT_EQ(KEY(removed), 3);
1030 pool.forget(removed);
1031 delete removed;
1032
1033 EXPECT_EQ(tree.size(), 4u);
1034 EXPECT_EQ(tree.search(3), nullptr);
1036}
1037
1039{
1040 HybridTree tree;
1041 HybridNodePool pool;
1042
1043 tree.insert(pool.make(42));
1044 EXPECT_EQ(tree.size(), 1u);
1045
1046 auto * removed = tree.remove(42);
1047 ASSERT_NE(removed, nullptr);
1048 EXPECT_EQ(KEY(removed), 42);
1049 pool.forget(removed);
1050 delete removed;
1051
1052 EXPECT_TRUE(tree.is_empty());
1053 EXPECT_EQ(tree.size(), 0u);
1054}
1055
1057{
1058 HybridTree tree;
1059 HybridNodePool pool;
1060
1061 std::vector<int> keys = {5, 3, 7, 1, 4, 6, 8};
1062 for (int k : keys)
1063 tree.insert(pool.make(k));
1064
1065 std::sort(keys.begin(), keys.end());
1066 for (int k : keys)
1067 {
1068 auto * removed = tree.remove(k);
1069 ASSERT_NE(removed, nullptr) << "Failed to remove " << k;
1070 pool.forget(removed);
1071 delete removed;
1073 }
1074
1075 EXPECT_TRUE(tree.is_empty());
1076}
1077
1079{
1080 HybridTree tree;
1081 HybridNodePool pool;
1082
1083 for (int k : {1, 3, 5})
1084 tree.insert(pool.make(k));
1085
1086 EXPECT_EQ(tree.remove(2), nullptr);
1087 EXPECT_EQ(tree.remove(4), nullptr);
1088 EXPECT_EQ(tree.size(), 3u);
1090}
1091
1093{
1094 HybridTree tree;
1095 HybridNodePool pool;
1096
1097 constexpr int key = 5;
1098 for (int i = 0; i < 3; ++i)
1099 ASSERT_NE(tree.insert_dup(pool.make(key)), nullptr);
1100
1101 for (int remaining = 3; remaining > 0; --remaining)
1102 {
1103 auto * removed = tree.remove(key);
1104 ASSERT_NE(removed, nullptr);
1105 EXPECT_EQ(KEY(removed), key);
1106 pool.forget(removed);
1107 delete removed;
1108
1109 EXPECT_EQ(tree.size(), static_cast<size_t>(remaining - 1));
1111 }
1112
1113 EXPECT_EQ(tree.remove(key), nullptr);
1114 EXPECT_TRUE(tree.is_empty());
1115}
1116
1118{
1119 HybridTree tree;
1120 HybridNodePool pool;
1121
1122 std::vector<int> expected = {1, 2, 3, 4, 5, 6, 7};
1123 for (int k : {4, 2, 6, 1, 3, 5, 7})
1124 tree.insert(pool.make(k));
1125
1126 std::vector<int> got;
1127 for (HybridTree::Iterator it(tree); it.has_curr(); it.next())
1128 got.push_back(KEY(it.get_curr()));
1129
1132}
1133
1135{
1136 HybridTree tree;
1137 HybridTree::Iterator it(tree);
1138
1139 EXPECT_FALSE(it.has_curr());
1140}
1141
1143{
1146 HybridNodePool pool;
1147
1148 tree1.insert(pool.make(1));
1149 tree1.insert(pool.make(2));
1150 tree1.insert(pool.make(3));
1151
1152 tree2.insert(pool.make(10));
1153 tree2.insert(pool.make(11));
1154
1155 ASSERT_EQ(tree1.size(), 3u);
1156 ASSERT_EQ(tree2.size(), 2u);
1157
1158 tree1.swap(tree2);
1159
1160 EXPECT_EQ(tree1.size(), 2u);
1161 EXPECT_EQ(tree2.size(), 3u);
1162
1163 auto keys1 = inorder_keys_generic(tree1.getRoot());
1164 EXPECT_EQ(keys1, (std::vector<int>{10, 11}));
1165
1166 auto keys2 = inorder_keys_generic(tree2.getRoot());
1167 EXPECT_EQ(keys2, (std::vector<int>{1, 2, 3}));
1168
1171}
1172
1174{
1175 struct AbsLess
1176 {
1177 bool operator()(int a, int b) const { return std::abs(a) < std::abs(b); }
1178 };
1179
1181 using NodeAbs = TreeAbs::Node;
1182
1183 TreeAbs tree(AbsLess{});
1184 auto * p = new NodeAbs(1);
1185 ASSERT_NE(tree.insert(p), nullptr);
1186
1187 auto * found = tree.search(-1);
1188 ASSERT_NE(found, nullptr);
1189 EXPECT_EQ(found, p);
1190 EXPECT_TRUE(tree.verify());
1191 EXPECT_TRUE(check_bst(tree.getRoot(), tree.key_comp()));
1192
1193 auto * removed = tree.remove(1);
1194 ASSERT_NE(removed, nullptr);
1195 delete removed;
1196}
1197
1199{
1200 HybridTree tree;
1201 HybridNodePool pool;
1202
1203 for (int k : {-5, -3, -1, 0, 1, 3, 5})
1204 tree.insert(pool.make(k));
1205
1206 EXPECT_EQ(tree.size(), 7u);
1208
1209 auto keys = inorder_keys_generic(tree.getRoot());
1210 EXPECT_EQ(keys, (std::vector<int>{-5, -3, -1, 0, 1, 3, 5}));
1211
1212 // Search for negative keys
1213 EXPECT_NE(tree.search(-3), nullptr);
1214 EXPECT_EQ(tree.search(-2), nullptr);
1215}
1216
1218{
1219 HybridTree tree;
1220 HybridNodePool pool;
1221 std::set<int> oracle;
1222
1223 std::mt19937 rng(123);
1224 std::uniform_int_distribution<int> dist(0, 500);
1225
1226 // Insert phase
1227 for (int i = 0; i < 200; ++i)
1228 {
1229 int k = dist(rng);
1230 auto * p = pool.make(k);
1231 if (tree.insert(p) != nullptr)
1232 oracle.insert(k);
1233 else
1234 {
1235 pool.forget(p);
1236 delete p;
1237 }
1238
1239 ASSERT_EQ(tree.size(), oracle.size());
1241 }
1242
1243 // Verify all elements
1244 auto keys = inorder_keys_generic(tree.getRoot());
1245 EXPECT_EQ(keys, std::vector<int>(oracle.begin(), oracle.end()));
1246
1247 // Search phase
1248 for (int i = 0; i < 100; ++i)
1249 {
1250 int k = dist(rng);
1251 auto * found = tree.search(k);
1252 if (oracle.count(k))
1253 {
1254 ASSERT_NE(found, nullptr);
1255 EXPECT_EQ(KEY(found), k);
1256 }
1257 else
1258 EXPECT_EQ(found, nullptr);
1259 }
1260
1261 // Remove phase
1262 for (int i = 0; i < 150; ++i)
1263 {
1264 int k = dist(rng);
1265 auto * removed = tree.remove(k);
1266 if (oracle.count(k))
1267 {
1268 ASSERT_NE(removed, nullptr);
1270 oracle.erase(k);
1271 pool.forget(removed);
1272 delete removed;
1273 }
1274 else
1275 EXPECT_EQ(removed, nullptr);
1276
1277 ASSERT_EQ(tree.size(), oracle.size());
1279 }
1280
1281 // Final verification
1282 keys = inorder_keys_generic(tree.getRoot());
1283 EXPECT_EQ(keys, std::vector<int>(oracle.begin(), oracle.end()));
1284}
1285
1287{
1288 HybridTree tree;
1289 HybridNodePool pool;
1290
1291 auto * p = pool.make(42);
1292 auto * inserted = tree.insert(p);
1293
1294 EXPECT_EQ(inserted, p);
1295 EXPECT_NE(tree.getRoot(), HybridNode::NullPtr);
1296 EXPECT_EQ(tree.getRoot(), p);
1297 EXPECT_EQ(tree.size(), 1u);
1299}
1300
1302{
1303 HybridTree tree;
1304 HybridNodePool pool;
1305
1306 for (int k : {5, 3, 7, 1, 4, 6, 8})
1307 ASSERT_NE(tree.insert(pool.make(k)), nullptr);
1308
1309 EXPECT_EQ(tree.size(), 7u);
1311
1312 auto keys = inorder_keys_generic(tree.getRoot());
1313 EXPECT_EQ(keys, (std::vector<int>{1, 3, 4, 5, 6, 7, 8}));
1314}
1315
1317{
1318 HybridTree tree;
1319 HybridNodePool pool;
1320
1321 for (int k : {1, 2, 3, 4, 5})
1322 tree.insert(pool.make(k));
1323
1324 for (int k : {1, 2, 3, 4, 5})
1325 {
1326 auto * found = tree.search(k);
1327 ASSERT_NE(found, nullptr);
1328 EXPECT_EQ(KEY(found), k);
1329 }
1330
1332}
1333
1335{
1336 HybridTree tree;
1337 HybridNodePool pool;
1338
1339 for (int k : {1, 3, 5})
1340 tree.insert(pool.make(k));
1341
1342 EXPECT_EQ(tree.search(2), nullptr);
1343 EXPECT_EQ(tree.search(4), nullptr);
1344 EXPECT_EQ(tree.search(0), nullptr);
1345 EXPECT_EQ(tree.search(6), nullptr);
1346
1348}
1349
1351{
1352 HybridTree tree;
1353
1354 EXPECT_EQ(tree.remove(42), nullptr);
1355 EXPECT_TRUE(tree.is_empty());
1356}
1357
1359{
1360 HybridTree tree;
1361 HybridNodePool pool;
1362
1363 tree.insert(pool.make(5));
1364 tree.insert(pool.make(3));
1365 tree.insert(pool.make(7));
1366
1367 auto * removed = tree.remove(5);
1368 ASSERT_NE(removed, nullptr);
1369 EXPECT_EQ(KEY(removed), 5);
1370 pool.forget(removed);
1371 delete removed;
1372
1373 EXPECT_EQ(tree.size(), 2u);
1375}
1376
1378{
1379 HybridTree tree;
1380 HybridNodePool pool;
1381
1382 for (int k = 1; k <= 10; ++k)
1383 tree.insert(pool.make(k));
1384
1385 for (int k = 10; k >= 1; --k)
1386 {
1387 auto * removed = tree.remove(k);
1388 ASSERT_NE(removed, nullptr) << "Failed to remove " << k;
1389 pool.forget(removed);
1390 delete removed;
1392 }
1393
1394 EXPECT_TRUE(tree.is_empty());
1395}
1396
1398{
1399 HybridTree tree;
1400 HybridNodePool pool;
1401
1402 for (int k = 10; k >= 1; --k)
1403 tree.insert(pool.make(k));
1404
1405 EXPECT_EQ(tree.size(), 10u);
1407
1408 auto keys = inorder_keys_generic(tree.getRoot());
1409 EXPECT_EQ(keys, (std::vector<int>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}));
1410}
1411
1413{
1414 HybridTree tree;
1415 HybridNodePool pool;
1416
1417 for (int k = 1; k <= 10; ++k)
1418 tree.insert(pool.make(k));
1419
1420 EXPECT_EQ(tree.size(), 10u);
1422
1423 auto keys = inorder_keys_generic(tree.getRoot());
1424 EXPECT_EQ(keys, (std::vector<int>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}));
1425}
1426
1428{
1429 HybridTree tree;
1430 HybridNodePool pool;
1431
1432 const int N = 1000;
1433
1434 for (int k = 0; k < N; ++k)
1435 tree.insert(pool.make(k));
1436
1437 EXPECT_EQ(tree.size(), static_cast<size_t>(N));
1439
1440 // Remove half
1441 for (int k = 0; k < N; k += 2)
1442 {
1443 auto * removed = tree.remove(k);
1444 ASSERT_NE(removed, nullptr);
1445 pool.forget(removed);
1446 delete removed;
1447 }
1448
1449 EXPECT_EQ(tree.size(), static_cast<size_t>(N / 2));
1451}
1452
1454{
1456 using NodeGt = TreeGt::Node;
1457
1458 TreeGt tree;
1459
1460 for (int k : {1, 2, 3, 4, 5})
1461 tree.insert(new NodeGt(k));
1462
1463 EXPECT_EQ(tree.size(), 5u);
1464 EXPECT_TRUE(tree.verify());
1465
1466 // With greater<int>, inorder should be descending
1467 std::vector<int> keys;
1468 for (TreeGt::Iterator it(tree); it.has_curr(); it.next())
1469 keys.push_back(KEY(it.get_curr()));
1470
1471 EXPECT_EQ(keys, (std::vector<int>{5, 4, 3, 2, 1}));
1472
1473 // Clean up
1474 for (int k : {1, 2, 3, 4, 5})
1475 delete tree.remove(k);
1476}
1477
1479{
1480 HybridTree tree;
1481 HybridNodePool pool;
1482
1483 for (int k : {1, 2, 3, 4, 5})
1484 tree.insert(pool.make(k));
1485
1486 auto * removed = tree.remove(3);
1487 pool.forget(removed);
1488 delete removed;
1489
1490 std::vector<int> result;
1491 for (HybridTree::Iterator it(tree); it.has_curr(); it.next())
1492 result.push_back(KEY(it.get_curr()));
1493
1494 EXPECT_EQ(result, (std::vector<int>{1, 2, 4, 5}));
1495}
1496
1498{
1500 auto * p1 = new HybridNode(1);
1501 auto * p2 = new HybridNode(2);
1502 auto * p3 = new HybridNode(3);
1503 tree1.insert(p1);
1504 tree1.insert(p2);
1505 tree1.insert(p3);
1506
1507 HybridTree tree2(std::move(tree1));
1508
1510 EXPECT_EQ(tree2.size(), 3u);
1512
1513 delete tree2.remove(1);
1514 delete tree2.remove(2);
1515 delete tree2.remove(3);
1516}
1517
1519{
1522 auto * p1 = new HybridNode(1);
1523 auto * p2 = new HybridNode(2);
1524 tree1.insert(p1);
1525 tree1.insert(p2);
1526
1527 tree2 = std::move(tree1);
1528
1530 EXPECT_EQ(tree2.size(), 2u);
1532
1533 delete tree2.remove(1);
1534 delete tree2.remove(2);
1535}
1536
1537// ============================================================================
1538
1540{
1541 using TreeVtl = Rb_Tree_Vtl<int>;
1542 using NodeVtl = TreeVtl::Node;
1543
1544 TreeVtl tree;
1545
1546 for (int k : {1, 2, 3, 4, 5})
1547 {
1548 auto * p = new NodeVtl(k);
1549 tree.insert(p);
1550 }
1551
1552 EXPECT_EQ(count_nodes_generic(tree.getRoot()), 5u);
1553 EXPECT_EQ(tree.size(), 5u);
1554 EXPECT_TRUE(tree.verify());
1555
1556 auto * found = tree.search(3);
1557 ASSERT_NE(found, nullptr);
1558 EXPECT_EQ(KEY(found), 3);
1559
1560 // Properly remove and delete each node
1561 for (int k : {1, 2, 3, 4, 5})
1562 {
1563 auto * removed = tree.remove(k);
1564 ASSERT_NE(removed, nullptr);
1565 delete removed;
1566 }
1567
1568 EXPECT_TRUE(tree.is_empty());
1569}
1570
1572{
1573 Tree tree;
1574 NodePool pool;
1575
1576 for (int k : {-5, -3, -1, 0, 1, 3, 5})
1577 tree.insert(pool.make(k));
1578
1579 EXPECT_EQ(tree.size(), 7u);
1580 assert_valid_tree(tree);
1581
1582 auto keys = inorder_keys(tree.getRoot());
1583 EXPECT_EQ(keys, (std::vector<int>{-5, -3, -1, 0, 1, 3, 5}));
1584
1585 EXPECT_NE(tree.search(-3), nullptr);
1586 EXPECT_EQ(tree.search(-2), nullptr);
1587}
1588
1590{
1592 using NodeGt = TreeGt::Node;
1593
1594 TreeGt tree;
1595
1596 for (int k : {1, 2, 3, 4, 5})
1597 tree.insert(new NodeGt(k));
1598
1599 EXPECT_EQ(tree.size(), 5u);
1600 EXPECT_TRUE(tree.verify());
1601
1602 // Remove some elements
1603 auto * removed = tree.remove(3);
1604 ASSERT_NE(removed, nullptr);
1605 delete removed;
1606
1607 removed = tree.remove(1);
1608 ASSERT_NE(removed, nullptr);
1609 delete removed;
1610
1611 EXPECT_EQ(tree.size(), 3u);
1612 EXPECT_TRUE(tree.verify());
1613
1614 // Clean up remaining
1615 for (int k : {2, 4, 5})
1616 delete tree.remove(k);
1617}
1618
1619// ============================================================================
1620// Stress and Fuzz Tests
1621// ============================================================================
1622
1624{
1625 Tree tree;
1626 NodePool pool;
1627
1628 // Ascending insertion is worst case for naive BST
1629 const int N = 10000;
1630 for (int k = 0; k < N; ++k)
1631 {
1632 tree.insert(pool.make(k));
1633 if (k % 1000 == 0)
1634 assert_valid_tree(tree);
1635 }
1636
1637 EXPECT_EQ(tree.size(), static_cast<size_t>(N));
1638 assert_valid_tree(tree);
1639
1640 // Verify all elements
1641 for (int k = 0; k < N; ++k)
1642 ASSERT_NE(tree.search(k), nullptr) << "Missing key " << k;
1643}
1644
1646{
1647 Tree tree;
1648 NodePool pool;
1649
1650 const int N = 10000;
1651 for (int k = N - 1; k >= 0; --k)
1652 {
1653 tree.insert(pool.make(k));
1654 if (k % 1000 == 0)
1655 assert_valid_tree(tree);
1656 }
1657
1658 EXPECT_EQ(tree.size(), static_cast<size_t>(N));
1659 assert_valid_tree(tree);
1660}
1661
1663{
1664 Tree tree;
1665 NodePool pool;
1666
1667 // Zigzag pattern: 0, N-1, 1, N-2, 2, N-3, ...
1668 const int N = 5000;
1669 for (int i = 0; i < N; ++i)
1670 {
1671 int k = (i % 2 == 0) ? i / 2 : N - 1 - i / 2;
1672 tree.insert(pool.make(k));
1673 }
1674
1675 EXPECT_EQ(tree.size(), static_cast<size_t>(N));
1676 assert_valid_tree(tree);
1677}
1678
1680{
1681 Tree tree;
1682 NodePool pool;
1683 std::set<int> oracle;
1684
1685 std::mt19937 gen(98765);
1686 std::uniform_int_distribution<> key_dist(0, 50000);
1687 std::uniform_int_distribution<> op_dist(0, 2);
1688
1689 for (int iter = 0; iter < 20000; ++iter)
1690 {
1691 int key = key_dist(gen);
1692 int op = op_dist(gen);
1693
1694 if (op == 0) // insert
1695 {
1696 auto * p = pool.make(key);
1697 if (tree.insert(p) != nullptr)
1698 oracle.insert(key);
1699 else
1700 {
1701 pool.forget(p);
1702 delete p;
1703 }
1704 }
1705 else if (op == 1 && !oracle.empty()) // remove
1706 {
1707 // Pick a random key from oracle
1708 auto it = oracle.begin();
1709 std::advance(it, gen() % oracle.size());
1710 int k = *it;
1711
1712 auto * removed = tree.remove(k);
1713 ASSERT_NE(removed, nullptr) << "Failed to remove existing key " << k;
1714 pool.forget(removed);
1715 delete removed;
1716 oracle.erase(k);
1717 }
1718 else // search
1719 {
1720 auto * found = tree.search(key);
1721 if (oracle.count(key))
1722 ASSERT_NE(found, nullptr);
1723 else
1724 EXPECT_EQ(found, nullptr);
1725 }
1726
1727 EXPECT_EQ(tree.size(), oracle.size());
1728
1729 if (iter % 2000 == 0)
1730 assert_valid_tree(tree);
1731 }
1732
1733 assert_valid_tree(tree);
1734
1735 auto keys = inorder_keys(tree.getRoot());
1736 EXPECT_EQ(keys, std::vector<int>(oracle.begin(), oracle.end()));
1737}
1738
1740{
1741 Tree tree;
1742 NodePool pool;
1743
1744 const int N = 10000;
1745
1746 // Bulk insert
1747 for (int k = 0; k < N; ++k)
1748 tree.insert(pool.make(k));
1749
1750 EXPECT_EQ(tree.size(), static_cast<size_t>(N));
1751 assert_valid_tree(tree);
1752
1753 // Bulk remove in random order
1754 std::vector<int> keys_to_remove(N);
1755 std::iota(keys_to_remove.begin(), keys_to_remove.end(), 0);
1756 std::mt19937 gen(11111);
1757 std::shuffle(keys_to_remove.begin(), keys_to_remove.end(), gen);
1758
1759 for (int k : keys_to_remove)
1760 {
1761 auto * removed = tree.remove(k);
1762 ASSERT_NE(removed, nullptr) << "Failed to remove " << k;
1763 pool.forget(removed);
1764 delete removed;
1765 }
1766
1767 EXPECT_TRUE(tree.is_empty());
1768}
1769
1771{
1772 Tree tree;
1773 NodePool pool;
1774
1775 // Insert many duplicates using insert_dup
1776 const int N = 1000;
1777 const int DUPS = 10;
1778
1779 for (int k = 0; k < N; ++k)
1780 for (int d = 0; d < DUPS; ++d)
1781 tree.insert_dup(pool.make(k));
1782
1783 EXPECT_EQ(tree.size(), static_cast<size_t>(N * DUPS));
1784 assert_valid_tree(tree);
1785
1786 // Remove all
1787 for (int k = 0; k < N; ++k)
1788 for (int d = 0; d < DUPS; ++d)
1789 {
1790 auto * removed = tree.remove(k);
1791 ASSERT_NE(removed, nullptr);
1792 pool.forget(removed);
1793 delete removed;
1794 }
1795
1796 EXPECT_TRUE(tree.is_empty());
1797}
1798
1800{
1801 Tree tree;
1802 NodePool pool;
1803 std::set<int> oracle;
1804
1805 std::mt19937 gen(22222);
1806 std::uniform_int_distribution<> key_dist(0, 1000);
1807
1808 for (int iter = 0; iter < 10000; ++iter)
1809 {
1810 int key = key_dist(gen);
1811
1812 if (iter % 2 == 0) // insert
1813 {
1814 auto * p = pool.make(key);
1815 if (tree.insert(p) != nullptr)
1816 oracle.insert(key);
1817 else
1818 {
1819 pool.forget(p);
1820 delete p;
1821 }
1822 }
1823 else if (!oracle.empty()) // remove random existing
1824 {
1825 auto it = oracle.begin();
1826 std::advance(it, gen() % oracle.size());
1827 int k = *it;
1828
1829 auto * removed = tree.remove(k);
1830 ASSERT_NE(removed, nullptr);
1831 pool.forget(removed);
1832 delete removed;
1833 oracle.erase(k);
1834 }
1835
1836 EXPECT_EQ(tree.size(), oracle.size());
1837 }
1838
1839 assert_valid_tree(tree);
1840}
1841
1843{
1845 using StrNode = StrTree::Node;
1846
1847 StrTree tree;
1848 std::vector<StrNode*> nodes;
1849 std::set<std::string> oracle;
1850
1851 std::mt19937 gen(33333);
1852
1853 auto random_string = [&gen]() {
1854 std::string s;
1855 int len = 5 + gen() % 20;
1856 for (int i = 0; i < len; ++i)
1857 s += 'a' + gen() % 26;
1858 return s;
1859 };
1860
1861 // Insert phase
1862 for (int i = 0; i < 2000; ++i)
1863 {
1864 std::string key = random_string();
1865 auto * p = new StrNode(key);
1866 nodes.push_back(p);
1867 if (tree.insert(p) != nullptr)
1868 oracle.insert(key);
1869 }
1870
1871 EXPECT_EQ(tree.size(), oracle.size());
1872 EXPECT_TRUE(tree.verify());
1873
1874 // Verify
1875 for (const auto & key : oracle)
1876 ASSERT_NE(tree.search(key), nullptr);
1877
1878 // Cleanup
1879 for (auto * p : nodes)
1880 delete p;
1881}
1882
1883// Hybrid tree stress tests
1885{
1886 HybridTree tree;
1887 HybridNodePool pool;
1888 std::set<int> oracle;
1889
1890 std::mt19937 gen(44444);
1891 std::uniform_int_distribution<> key_dist(0, 10000);
1892 std::uniform_int_distribution<> op_dist(0, 2);
1893
1894 for (int iter = 0; iter < 10000; ++iter)
1895 {
1896 int key = key_dist(gen);
1897 int op = op_dist(gen);
1898
1899 if (op == 0) // insert
1900 {
1901 auto * p = pool.make(key);
1902 if (tree.insert(p) != nullptr)
1903 oracle.insert(key);
1904 else
1905 {
1906 pool.forget(p);
1907 delete p;
1908 }
1909 }
1910 else if (op == 1 && !oracle.empty()) // remove
1911 {
1912 auto it = oracle.begin();
1913 std::advance(it, gen() % oracle.size());
1914 int k = *it;
1915
1916 auto * removed = tree.remove(k);
1917 ASSERT_NE(removed, nullptr);
1918 pool.forget(removed);
1919 delete removed;
1920 oracle.erase(k);
1921 }
1922 else // search
1923 {
1924 auto * found = tree.search(key);
1925 if (oracle.count(key))
1926 ASSERT_NE(found, nullptr);
1927 else
1928 EXPECT_EQ(found, nullptr);
1929 }
1930
1931 EXPECT_EQ(tree.size(), oracle.size());
1932 }
1933
1935}
static string random_string(std::mt19937 &rng, size_t len)
WeightedDigraph::Node Node
@ KEY
Definition btreepic.C:169
bool has_curr() const noexcept
Return true the iterator has current node.
T & insert(const T &item)
Insert a new item by copy.
Definition htlist.H:1502
T remove()
Remove the first item of the list.
Definition htlist.H:1611
void empty() noexcept
empty the list
Definition htlist.H:1689
DynList & swap(DynList &l) noexcept
Swap this with l.
Definition htlist.H:1448
bool is_empty() const noexcept
Return true if the tree is empty.
bool verify() const
Return true if this is a consistent randomized tree.
Node * remove(const Key &key) noexcept
Remove a key from the tree.
NodeType< Key > Node
Node * search_or_insert(Node *p) noexcept
Search or insert a key.
Compare & key_comp() noexcept
return the comparison criteria
Node * insert_dup(Node *p) noexcept
Insert a node in the tree.
Node * insert(Node *p) noexcept
Insert a node in the tree.
size_t size() const noexcept
Return the number of nodes that have the tree.
Node *& getRoot() noexcept
Return the tree's root.
Node * search(const Key &key) const noexcept
Search a key.
Red-black binary search tree implementation (bottom-up).
constexpr bool is_empty() const noexcept
Return true if list is empty.
Definition htlist.H:523
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
Hybrid top-down/bottom-up red-black tree.
Definition tpl_hRbTree.H:84
void forget(Node *p)
Definition rand-tree.cc:93
Node * make(int key)
Definition rand-tree.cc:86
iterator end() noexcept
Return an STL-compatible end iterator.
iterator begin() noexcept
Return an STL-compatible iterator to the first element.
#define TEST(name)
static mt19937 rng
#define N
Definition fib.C:294
__gmp_expr< T, __gmp_binary_expr< __gmp_expr< T, U >, unsigned long int, __gmp_root_function > > root(const __gmp_expr< T, U > &expr, unsigned long int l)
Definition gmpfrxx.h:4060
DynArray< Graph::Node * > nodes
Definition graphpic.C:406
bool check_bst(Node *p, const Compare &cmp=Compare())
Return true if p is a binary search tree.
constexpr Node *& RLINK(Node *p) noexcept
Return the right tree of p.
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.
std::vector< int > inorder_keys(NodeT *root)
Definition rand-tree.cc:59
Iterator on nodes of the tree.
Red-black tree with virtual destructor in nodes.
Red-black tree with nodes without virtual destructor.
Hybrid top-down/bottom-up red-black tree implementation.
Red-Black tree implementation (bottom-up balancing).