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