Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
rand-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
33
38#include <gtest/gtest.h>
39
40#include <tpl_rand_tree.H>
41#include <tpl_binNodeUtils.H>
42#include <random>
43#include <set>
44#include <vector>
45#include <algorithm>
46
47using namespace std;
48using namespace Aleph;
49
50// ============================================================================
51// Type Aliases and Helpers
52// ============================================================================
53
56
57// Helper to collect keys in inorder
58template <typename NodeT>
59std::vector<int> inorder_keys(NodeT *root)
60{
61 std::vector<int> keys;
62 if (root == NodeT::NullPtr)
63 return keys;
64
65 auto left = inorder_keys<NodeT>(LLINK(root));
66 keys.insert(keys.end(), left.begin(), left.end());
67 keys.push_back(KEY(root));
68 auto right = inorder_keys<NodeT>(RLINK(root));
69 keys.insert(keys.end(), right.begin(), right.end());
70
71 return keys;
72}
73
74// Helper class to manage node allocation/deallocation
76{
77 std::vector<Node *> nodes;
78
79public:
81 {
82 for (auto *p : nodes)
83 delete p;
84 }
85
86 Node *make(int key)
87 {
88 auto *p = new Node(key);
89 nodes.push_back(p);
90 return p;
91 }
92
93 void forget(Node *p)
94 {
95 nodes.erase(std::remove(nodes.begin(), nodes.end(), p), nodes.end());
96 }
97};
98
99// ============================================================================
100// Empty Tree Tests
101// ============================================================================
102
104{
105 Tree tree(42); // fixed seed for reproducibility
106
107 EXPECT_EQ(tree.size(), 0u);
108 EXPECT_TRUE(tree.is_empty());
109 EXPECT_EQ(tree.getRoot(), Node::NullPtr);
110 EXPECT_TRUE(tree.verify());
111}
112
114{
115 Tree tree(42);
116
117 EXPECT_EQ(tree.search(10), nullptr);
118 EXPECT_EQ(tree.search(0), nullptr);
119 EXPECT_EQ(tree.search(-1), nullptr);
120}
121
123{
124 Tree tree(42);
125
126 EXPECT_EQ(tree.remove(10), nullptr);
127 EXPECT_EQ(tree.size(), 0u);
128}
129
130// ============================================================================
131// Insert Tests
132// ============================================================================
133
135{
136 Tree tree(42);
137 NodePool pool;
138
139 auto *p = pool.make(10);
140 auto *inserted = tree.insert(p);
141
143 EXPECT_EQ(tree.size(), 1u);
144 EXPECT_FALSE(tree.is_empty());
145 EXPECT_EQ(tree.getRoot(), p);
146 EXPECT_TRUE(tree.verify());
147}
148
150{
151 Tree tree(42);
152 NodePool pool;
153
154 for (int k : {5, 3, 7, 1, 4, 6, 8})
155 ASSERT_NE(tree.insert(pool.make(k)), nullptr);
156
157 EXPECT_EQ(tree.size(), 7u);
158 EXPECT_TRUE(tree.verify());
159
160 auto keys = inorder_keys<Node>(tree.getRoot());
161 EXPECT_EQ(keys, (std::vector<int>{1, 3, 4, 5, 6, 7, 8}));
162}
163
165{
166 Tree tree(42);
167 NodePool pool;
168
169 auto *p1 = pool.make(10);
170 auto *p2 = pool.make(10);
171
172 EXPECT_NE(tree.insert(p1), nullptr);
173 EXPECT_EQ(tree.insert(p2), nullptr); // duplicate rejected
174
175 EXPECT_EQ(tree.size(), 1u);
176 pool.forget(p2);
177 delete p2;
178}
179
181{
182 Tree tree(42);
183 NodePool pool;
184
185 for (int i = 0; i < 5; ++i)
186 ASSERT_NE(tree.insert_dup(pool.make(10)), nullptr);
187
188 EXPECT_EQ(tree.size(), 5u);
189 EXPECT_TRUE(tree.verify());
190}
191
193{
194 Tree tree(42);
195 NodePool pool;
196
197 for (int k = 1; k <= 100; ++k)
198 ASSERT_NE(tree.insert(pool.make(k)), nullptr);
199
200 EXPECT_EQ(tree.size(), 100u);
201 EXPECT_TRUE(tree.verify());
202
203 auto keys = inorder_keys<Node>(tree.getRoot());
204 std::vector<int> expected(100);
205 std::iota(expected.begin(), expected.end(), 1);
206 EXPECT_EQ(keys, expected);
207}
208
210{
211 Tree tree(42);
212 NodePool pool;
213
214 for (int k = 100; k >= 1; --k)
215 ASSERT_NE(tree.insert(pool.make(k)), nullptr);
216
217 EXPECT_EQ(tree.size(), 100u);
218 EXPECT_TRUE(tree.verify());
219
220 auto keys = inorder_keys<Node>(tree.getRoot());
221 std::vector<int> expected(100);
222 std::iota(expected.begin(), expected.end(), 1);
223 EXPECT_EQ(keys, expected);
224}
225
226// ============================================================================
227// Search Tests
228// ============================================================================
229
231{
232 Tree tree(42);
233 NodePool pool;
234
235 for (int k : {1, 2, 3, 4, 5})
236 tree.insert(pool.make(k));
237
238 for (int k : {1, 2, 3, 4, 5})
239 {
240 auto *found = tree.search(k);
241 ASSERT_NE(found, nullptr);
242 EXPECT_EQ(KEY(found), k);
243 }
244}
245
247{
248 Tree tree(42);
249 NodePool pool;
250
251 for (int k : {1, 3, 5})
252 tree.insert(pool.make(k));
253
254 EXPECT_EQ(tree.search(2), nullptr);
255 EXPECT_EQ(tree.search(4), nullptr);
256 EXPECT_EQ(tree.search(0), nullptr);
257 EXPECT_EQ(tree.search(6), nullptr);
258}
259
261{
262 Tree tree(42);
263 NodePool pool;
264
265 auto *p1 = pool.make(10);
266 tree.insert(p1);
267
268 auto *p2 = pool.make(10);
269 auto *found = tree.search_or_insert(p2);
270
271 EXPECT_EQ(found, p1);
272 EXPECT_EQ(tree.size(), 1u);
273
274 pool.forget(p2);
275 delete p2;
276}
277
279{
280 Tree tree(42);
281 NodePool pool;
282
283 tree.insert(pool.make(5));
284
285 auto *p = pool.make(10);
286 auto *result = tree.search_or_insert(p);
287
288 EXPECT_EQ(result, p);
289 EXPECT_EQ(tree.size(), 2u);
290 EXPECT_NE(tree.search(10), nullptr);
291}
292
293// ============================================================================
294// Remove Tests
295// ============================================================================
296
298{
299 Tree tree(42);
300 NodePool pool;
301
302 for (int k : {1, 2, 3, 4, 5})
303 tree.insert(pool.make(k));
304
305 auto *removed = tree.remove(3);
306 ASSERT_NE(removed, nullptr);
307 EXPECT_EQ(KEY(removed), 3);
308
309 pool.forget(removed);
310 delete removed;
311
312 EXPECT_EQ(tree.size(), 4u);
313 EXPECT_EQ(tree.search(3), nullptr);
314 EXPECT_TRUE(tree.verify());
315
316 auto keys = inorder_keys<Node>(tree.getRoot());
317 EXPECT_EQ(keys, (std::vector<int>{1, 2, 4, 5}));
318}
319
321{
322 Tree tree(42);
323 NodePool pool;
324
325 tree.insert(pool.make(1));
326 tree.insert(pool.make(3));
327
328 EXPECT_EQ(tree.remove(2), nullptr);
329 EXPECT_EQ(tree.size(), 2u);
330}
331
333{
334 Tree tree(42);
335 NodePool pool;
336
337 auto *root = pool.make(5);
338 tree.insert(root);
339 tree.insert(pool.make(3));
340 tree.insert(pool.make(7));
341
342 auto *removed = tree.remove(5);
343 ASSERT_NE(removed, nullptr);
344 EXPECT_EQ(KEY(removed), 5);
345 pool.forget(removed);
346 delete removed;
347
348 EXPECT_EQ(tree.size(), 2u);
349 EXPECT_TRUE(tree.verify());
350}
351
353{
354 Tree tree(42);
355 NodePool pool;
356
357 for (int k : {5, 3, 7, 1, 4, 6, 8})
358 tree.insert(pool.make(k));
359
360 for (int k : {5, 3, 7, 1, 4, 6, 8})
361 {
362 auto *removed = tree.remove(k);
363 ASSERT_NE(removed, nullptr) << "Failed to remove " << k;
364 pool.forget(removed);
365 delete removed;
366 EXPECT_TRUE(tree.verify());
367 }
368
369 EXPECT_EQ(tree.size(), 0u);
370}
371
373{
374 Tree tree(42);
375 NodePool pool;
376
377 for (int k = 1; k <= 10; ++k)
378 tree.insert(pool.make(k));
379
380 for (int k = 1; k <= 10; ++k)
381 {
382 auto *removed = tree.remove(k);
383 ASSERT_NE(removed, nullptr);
384 pool.forget(removed);
385 delete removed;
386 EXPECT_TRUE(tree.verify());
387 }
388
389 EXPECT_EQ(tree.size(), 0u);
390}
391
393{
394 Tree tree(42);
395 NodePool pool;
396
397 for (int k = 1; k <= 10; ++k)
398 tree.insert(pool.make(k));
399
400 for (int k = 10; k >= 1; --k)
401 {
402 auto *removed = tree.remove(k);
403 ASSERT_NE(removed, nullptr);
404 pool.forget(removed);
405 delete removed;
406 EXPECT_TRUE(tree.verify());
407 }
408
409 EXPECT_EQ(tree.size(), 0u);
410}
411
412// ============================================================================
413// Select and Position Tests
414// ============================================================================
415
417{
418 Tree tree(42);
419 NodePool pool;
420
421 for (int k : {5, 3, 7, 1, 4, 6, 8})
422 tree.insert(pool.make(k));
423
424 // Inorder: 1, 3, 4, 5, 6, 7, 8
425 EXPECT_EQ(KEY(tree.select(0)), 1);
426 EXPECT_EQ(KEY(tree.select(1)), 3);
427 EXPECT_EQ(KEY(tree.select(2)), 4);
428 EXPECT_EQ(KEY(tree.select(3)), 5);
429 EXPECT_EQ(KEY(tree.select(4)), 6);
430 EXPECT_EQ(KEY(tree.select(5)), 7);
431 EXPECT_EQ(KEY(tree.select(6)), 8);
432}
433
435{
436 Tree tree(42);
437 NodePool pool;
438
439 tree.insert(pool.make(1));
440 tree.insert(pool.make(2));
441
442 EXPECT_THROW(tree.select(2), std::out_of_range);
443 EXPECT_THROW(tree.select(100), std::out_of_range);
444}
445
447{
448 Tree tree(42);
449 NodePool pool;
450
451 for (int k : {5, 3, 7, 1, 4, 6, 8})
452 tree.insert(pool.make(k));
453
454 // Inorder: 1, 3, 4, 5, 6, 7, 8
455 auto [pos1, node1] = tree.position(1);
456 EXPECT_EQ(pos1, 0);
457 EXPECT_EQ(KEY(node1), 1);
458
459 auto [pos5, node5] = tree.position(5);
460 EXPECT_EQ(pos5, 3);
461 EXPECT_EQ(KEY(node5), 5);
462
463 auto [pos8, node8] = tree.position(8);
464 EXPECT_EQ(pos8, 6);
465 EXPECT_EQ(KEY(node8), 8);
466}
467
469{
470 Tree tree(42);
471 NodePool pool;
472
473 for (int k : {2, 4, 6})
474 tree.insert(pool.make(k));
475
476 auto [pos, node] = tree.position(3);
477 EXPECT_EQ(pos, -1);
478}
479
481{
482 Tree tree(42);
483 NodePool pool;
484
485 for (int k : {2, 4, 6, 8})
486 tree.insert(pool.make(k));
487
488 auto [pos, node] = tree.find_position(4);
489 EXPECT_EQ(pos, 1);
490 EXPECT_EQ(KEY(node), 4);
491}
492
494{
495 Tree tree(42);
496 NodePool pool;
497
498 for (int k : {2, 4, 6, 8})
499 tree.insert(pool.make(k));
500
501 // 5 would be at position 2 (between 4 and 6)
502 auto [pos, node] = tree.find_position(5);
503 EXPECT_EQ(pos, 2);
504 // The returned node is the predecessor (key immediately less than 5)
505 EXPECT_NE(node, nullptr);
506}
507
509{
510 Tree tree(42);
511 NodePool pool;
512
513 for (int k : {2, 4, 6})
514 tree.insert(pool.make(k));
515
516 auto [pos, node] = tree.find_position(1);
517 EXPECT_EQ(pos, -1);
518 EXPECT_EQ(KEY(node), 2); // smallest key
519}
520
522{
523 Tree tree(42);
524 NodePool pool;
525
526 for (int k : {2, 4, 6})
527 tree.insert(pool.make(k));
528
529 auto [pos, node] = tree.find_position(10);
530 EXPECT_EQ(pos, 3);
531 EXPECT_EQ(KEY(node), 6); // largest key
532}
533
534// ============================================================================
535// Remove by Position Tests
536// ============================================================================
537
539{
540 Tree tree(42);
541 NodePool pool;
542
543 for (int k : {5, 3, 7, 1, 4, 6, 8})
544 tree.insert(pool.make(k));
545
546 // Inorder: 1, 3, 4, 5, 6, 7, 8
547 // Remove position 3 (key = 5)
548 auto *removed = tree.remove_pos(3);
549 ASSERT_NE(removed, nullptr);
550 EXPECT_EQ(KEY(removed), 5);
551 pool.forget(removed);
552 delete removed;
553
554 EXPECT_EQ(tree.size(), 6u);
555 EXPECT_TRUE(tree.verify());
556}
557
559{
560 Tree tree(42);
561 NodePool pool;
562
563 for (int k : {5, 3, 7})
564 tree.insert(pool.make(k));
565
566 // Inorder: 3, 5, 7 - remove first
567 auto *removed = tree.remove_pos(0);
568 ASSERT_NE(removed, nullptr);
569 EXPECT_EQ(KEY(removed), 3);
570 pool.forget(removed);
571 delete removed;
572
573 EXPECT_EQ(tree.size(), 2u);
574}
575
577{
578 Tree tree(42);
579 NodePool pool;
580
581 for (int k : {5, 3, 7})
582 tree.insert(pool.make(k));
583
584 // Inorder: 3, 5, 7 - remove last
585 auto *removed = tree.remove_pos(2);
586 ASSERT_NE(removed, nullptr);
587 EXPECT_EQ(KEY(removed), 7);
588 pool.forget(removed);
589 delete removed;
590
591 EXPECT_EQ(tree.size(), 2u);
592}
593
594// NOTE: remove_pos is marked noexcept but throws - this is a bug
595// The test below would cause std::terminate, so we skip it
596// TEST(RandTree, RemovePosOutOfRangeThrows)
597
598// ============================================================================
599// Split Tests
600// ============================================================================
601
603{
604 Tree tree(42);
605 Tree t1(42);
606 Tree t2(42);
607 NodePool pool;
608
609 for (int k : {2, 4, 6, 8, 10})
610 tree.insert(pool.make(k));
611
612 bool result = tree.split_key(5, t1, t2);
613 EXPECT_TRUE(result);
614
615 // t1 should have keys < 5: {2, 4}
616 // t2 should have keys > 5: {6, 8, 10}
617 auto keys1 = inorder_keys<Node>(t1.getRoot());
618 auto keys2 = inorder_keys<Node>(t2.getRoot());
619
620 EXPECT_EQ(keys1, (std::vector<int>{2, 4}));
621 EXPECT_EQ(keys2, (std::vector<int>{6, 8, 10}));
622}
623
625{
626 Tree tree(42);
627 Tree t1(42);
628 Tree t2(42);
629 NodePool pool;
630
631 for (int k : {2, 4, 6, 8, 10})
632 tree.insert(pool.make(k));
633
634 bool result = tree.split_key(6, t1, t2);
635 EXPECT_FALSE(result); // key was in tree
636}
637
639{
640 Tree tree(42);
641 Tree t1(42);
642 Tree t2(42);
643 NodePool pool;
644
645 for (int k : {2, 4, 6, 8, 10})
646 tree.insert(pool.make(k));
647
648 tree.split_key_dup(6, t1, t2);
649
650 auto keys1 = inorder_keys<Node>(t1.getRoot());
651 auto keys2 = inorder_keys<Node>(t2.getRoot());
652
653 // Actual semantics: t1 gets keys <= key, t2 gets keys > key
654 EXPECT_EQ(keys1, (std::vector<int>{2, 4, 6}));
655 EXPECT_EQ(keys2, (std::vector<int>{8, 10}));
656}
657
659{
660 Tree tree(42);
661 Tree t1(42);
662 Tree t2(42);
663 NodePool pool;
664
665 for (int k : {1, 2, 3, 4, 5})
666 tree.insert(pool.make(k));
667
668 tree.split_pos(2, t1, t2);
669
670 auto keys1 = inorder_keys<Node>(t1.getRoot());
671 auto keys2 = inorder_keys<Node>(t2.getRoot());
672
673 // t1: positions [0, 2) -> keys {1, 2}
674 // t2: positions [2, 5) -> keys {3, 4, 5}
675 EXPECT_EQ(keys1, (std::vector<int>{1, 2}));
676 EXPECT_EQ(keys2, (std::vector<int>{3, 4, 5}));
677}
678
679// ============================================================================
680// Join Tests
681// ============================================================================
682
684{
685 Tree tree1(42);
686 Tree tree2(42);
687 Tree dup(42);
688 NodePool pool;
689
690 for (int k : {1, 3, 5})
691 tree1.insert(pool.make(k));
692 for (int k : {2, 4, 6})
693 tree2.insert(pool.make(k));
694
695 tree1.join(tree2, dup);
696
697 EXPECT_EQ(tree1.size(), 6u);
698 EXPECT_EQ(tree2.size(), 0u);
699 EXPECT_EQ(dup.size(), 0u);
700 EXPECT_TRUE(tree1.verify());
701
702 auto keys = inorder_keys<Node>(tree1.getRoot());
703 EXPECT_EQ(keys, (std::vector<int>{1, 2, 3, 4, 5, 6}));
704}
705
707{
708 Tree tree1(42);
709 Tree tree2(42);
710 Tree dup(42);
711 NodePool pool;
712
713 for (int k : {1, 3, 5})
714 tree1.insert(pool.make(k));
715 for (int k : {3, 4, 5})
716 tree2.insert(pool.make(k));
717
718 tree1.join(tree2, dup);
719
720 EXPECT_EQ(tree1.size(), 4u); // 1, 3, 4, 5
721 EXPECT_EQ(tree2.size(), 0u);
722 EXPECT_EQ(dup.size(), 2u); // two duplicates: 3, 5
723
724 auto keys = inorder_keys<Node>(tree1.getRoot());
725 EXPECT_EQ(keys, (std::vector<int>{1, 3, 4, 5}));
726
727 auto dupKeys = inorder_keys<Node>(dup.getRoot());
728 std::sort(dupKeys.begin(), dupKeys.end());
729 EXPECT_EQ(dupKeys, (std::vector<int>{3, 5}));
730}
731
733{
734 Tree tree1(42);
735 Tree tree2(42);
736 NodePool pool;
737
738 for (int k : {1, 3, 5})
739 tree1.insert(pool.make(k));
740 for (int k : {3, 4, 5})
741 tree2.insert(pool.make(k));
742
743 tree1.join_dup(tree2);
744
745 EXPECT_EQ(tree1.size(), 6u); // 1, 3, 3, 4, 5, 5
746 EXPECT_EQ(tree2.size(), 0u);
747 EXPECT_TRUE(tree1.verify());
748}
749
751{
752 Tree tree1(42);
753 Tree tree2(42);
754 NodePool pool;
755
756 // tree1 has smaller keys
757 for (int k : {1, 2, 3})
758 tree1.insert(pool.make(k));
759 // tree2 has larger keys
760 for (int k : {10, 11, 12})
761 tree2.insert(pool.make(k));
762
763 tree1.join_exclusive(tree2);
764
765 EXPECT_EQ(tree1.size(), 6u);
766 EXPECT_EQ(tree2.size(), 0u);
767 EXPECT_TRUE(tree1.verify());
768
769 auto keys = inorder_keys<Node>(tree1.getRoot());
770 EXPECT_EQ(keys, (std::vector<int>{1, 2, 3, 10, 11, 12}));
771}
772
773// ============================================================================
774// Iterator Tests
775// ============================================================================
776
778{
779 Tree tree(42);
780 NodePool pool;
781
782 for (int k : {5, 3, 7, 1, 4, 6, 8})
783 tree.insert(pool.make(k));
784
785 std::vector<int> result;
786 for (Tree::Iterator it(tree); it.has_curr(); it.next())
787 result.push_back(KEY(it.get_curr()));
788
789 EXPECT_EQ(result, (std::vector<int>{1, 3, 4, 5, 6, 7, 8}));
790}
791
793{
794 Tree tree(42);
795 Tree::Iterator it(tree);
796
798}
799
801{
802 Tree tree(42);
803 NodePool pool;
804
805 for (int k : {1, 2, 3, 4, 5})
806 tree.insert(pool.make(k));
807
808 auto *removed = tree.remove(3);
809 pool.forget(removed);
810 delete removed;
811
812 std::vector<int> result;
813 for (Tree::Iterator it(tree); it.has_curr(); it.next())
814 result.push_back(KEY(it.get_curr()));
815
816 EXPECT_EQ(result, (std::vector<int>{1, 2, 4, 5}));
817}
818
819// ============================================================================
820// Special Member Functions Tests
821// ============================================================================
822
824{
825 Tree tree1(42);
826 Tree tree2(42);
827 NodePool pool;
828
829 for (int k : {1, 2, 3})
830 tree1.insert(pool.make(k));
831 for (int k : {10, 20})
832 tree2.insert(pool.make(k));
833
835
836 EXPECT_EQ(tree1.size(), 2u);
837 EXPECT_EQ(tree2.size(), 3u);
838
839 EXPECT_NE(tree1.search(10), nullptr);
840 EXPECT_NE(tree1.search(20), nullptr);
841 EXPECT_NE(tree2.search(1), nullptr);
842 EXPECT_NE(tree2.search(2), nullptr);
843 EXPECT_NE(tree2.search(3), nullptr);
844}
845
847{
848 NodePool pool1, pool2;
849
850 Tree tree1(123);
851 Tree tree2(456);
852
853 // Insert same elements in same order with different seeds
854 for (int k : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
855 {
856 tree1.insert(pool1.make(k));
857 tree2.insert(pool2.make(k));
858 }
859
860 // Both trees should have same elements but potentially different structure
862 EXPECT_TRUE(tree1.verify());
863 EXPECT_TRUE(tree2.verify());
864
865 // Inorder traversal should be the same
866 auto keys1 = inorder_keys<Node>(tree1.getRoot());
867 auto keys2 = inorder_keys<Node>(tree2.getRoot());
869}
870
871// ============================================================================
872// Custom Comparator Tests
873// ============================================================================
874
876{
878 using NodeGt = TreeGt::Node;
879
880 TreeGt tree(42);
881
882 std::vector<NodeGt *> nodes;
883 for (int k : {1, 2, 3, 4, 5})
884 {
885 auto *p = new NodeGt(k);
886 nodes.push_back(p);
887 tree.insert(p);
888 }
889
890 EXPECT_EQ(tree.size(), 5u);
891 EXPECT_TRUE(tree.verify());
892
893 // With greater<int>, inorder should be descending
894 std::vector<int> result;
895 for (TreeGt::Iterator it(tree); it.has_curr(); it.next())
896 result.push_back(KEY(it.get_curr()));
897
898 EXPECT_EQ(result, (std::vector<int>{5, 4, 3, 2, 1}));
899
900 // Clean up
901 for (int k : {1, 2, 3, 4, 5})
902 delete tree.remove(k);
903}
904
905// ============================================================================
906// Edge Cases
907// ============================================================================
908
910{
911 Tree tree(42);
912 NodePool pool;
913
914 for (int k : {-5, -3, -1, 0, 1, 3, 5})
915 tree.insert(pool.make(k));
916
917 EXPECT_EQ(tree.size(), 7u);
918 EXPECT_TRUE(tree.verify());
919
920 auto keys = inorder_keys<Node>(tree.getRoot());
921 EXPECT_EQ(keys, (std::vector<int>{-5, -3, -1, 0, 1, 3, 5}));
922
923 // Search negative keys
924 EXPECT_NE(tree.search(-5), nullptr);
925 EXPECT_NE(tree.search(-1), nullptr);
926 EXPECT_EQ(tree.search(-2), nullptr);
927}
928
930{
931 Tree tree(42);
932 NodePool pool;
933
934 auto *p = pool.make(42);
935 tree.insert(p);
936
937 EXPECT_EQ(tree.size(), 1u);
938 EXPECT_EQ(KEY(tree.select(0)), 42);
939
940 auto [pos, node] = tree.position(42);
941 EXPECT_EQ(pos, 0);
942 EXPECT_EQ(KEY(node), 42);
943
944 auto *removed = tree.remove(42);
945 ASSERT_NE(removed, nullptr);
946 pool.forget(removed);
947 delete removed;
948
949 EXPECT_EQ(tree.size(), 0u);
950}
951
952// ============================================================================
953// Stress Tests
954// ============================================================================
955
957{
958 Tree tree(42);
959 NodePool pool;
960 std::set<int> oracle;
961
962 std::mt19937 rng(12345);
963 std::uniform_int_distribution<int> dist(0, 999);
964
965 // Insert phase
966 for (int i = 0; i < 500; ++i)
967 {
968 int k = dist(rng);
969 if (oracle.count(k) == 0)
970 {
971 ASSERT_NE(tree.insert(pool.make(k)), nullptr);
972 oracle.insert(k);
973 }
974 }
975
976 EXPECT_EQ(tree.size(), oracle.size());
977 EXPECT_TRUE(tree.verify());
978
979 // Search phase
980 for (int i = 0; i < 200; ++i)
981 {
982 int k = dist(rng);
983 auto *found = tree.search(k);
984 if (oracle.count(k))
985 EXPECT_NE(found, nullptr);
986 else
987 EXPECT_EQ(found, nullptr);
988 }
989
990 // Remove phase
991 for (int i = 0; i < 200; ++i)
992 {
993 int k = dist(rng);
994 auto *removed = tree.remove(k);
995 if (oracle.count(k))
996 {
997 ASSERT_NE(removed, nullptr);
998 oracle.erase(k);
999 pool.forget(removed);
1000 delete removed;
1001 }
1002 else
1003 {
1004 EXPECT_EQ(removed, nullptr);
1005 }
1006 }
1007
1008 EXPECT_EQ(tree.size(), oracle.size());
1009 EXPECT_TRUE(tree.verify());
1010
1011 // Verify remaining keys
1012 auto keys = inorder_keys<Node>(tree.getRoot());
1013 EXPECT_EQ(keys, std::vector<int>(oracle.begin(), oracle.end()));
1014}
1015
1017{
1018 Tree tree(42);
1019 NodePool pool;
1020
1021 const int N = 5000;
1022
1023 // Insert N elements
1024 for (int k = 0; k < N; ++k)
1025 tree.insert(pool.make(k));
1026
1027 EXPECT_EQ(tree.size(), static_cast<size_t>(N));
1028 EXPECT_TRUE(tree.verify());
1029
1030 // Verify select works correctly
1031 for (int i = 0; i < 10; ++i)
1032 EXPECT_EQ(KEY(tree.select(i)), i);
1033
1034 // Remove half
1035 for (int k = 0; k < N; k += 2)
1036 {
1037 auto *removed = tree.remove(k);
1038 ASSERT_NE(removed, nullptr);
1039 pool.forget(removed);
1040 delete removed;
1041 }
1042
1043 EXPECT_EQ(tree.size(), static_cast<size_t>(N / 2));
1044 EXPECT_TRUE(tree.verify());
1045
1046 // Verify remaining elements
1047 for (int k = 1; k < N; k += 2)
1048 EXPECT_NE(tree.search(k), nullptr);
1049}
1050
1051// ============================================================================
1052// Rand_Tree_Vtl Tests
1053// ============================================================================
1054
1056{
1058 using NodeVtl = TreeVtl::Node;
1059
1060 TreeVtl tree(42);
1061
1062 for (int k : {1, 2, 3, 4, 5})
1063 tree.insert(new NodeVtl(k));
1064
1065 EXPECT_EQ(tree.size(), 5u);
1066 EXPECT_TRUE(tree.verify());
1067
1068 // Clean up properly using remove to avoid memory leaks
1069 for (int k : {1, 2, 3, 4, 5})
1070 delete tree.remove(k);
1071}
1072
1073// ============================================================================
1074// Verify Method Tests
1075// ============================================================================
1076
1078{
1079 Tree tree(42);
1080 NodePool pool;
1081
1082 EXPECT_TRUE(tree.verify()); // empty tree is valid
1083
1084 for (int k : {5, 3, 7, 1, 4, 6, 8})
1085 tree.insert(pool.make(k));
1086
1087 EXPECT_TRUE(tree.verify());
1088
1089 // After various operations
1090 tree.remove(5);
1091 EXPECT_TRUE(tree.verify());
1092}
1093
1094// ============================================================================
1095// API Coverage Tests
1096// ============================================================================
1097
1099{
1100 Tree tree(42);
1101 NodePool pool;
1102
1103 Node *&root = tree.getRoot();
1104 EXPECT_EQ(root, Node::NullPtr);
1105
1106 tree.insert(pool.make(10));
1107 EXPECT_NE(root, Node::NullPtr);
1108 EXPECT_EQ(KEY(root), 10);
1109}
1110
1112{
1113 Tree tree(42);
1114
1115 auto &cmp1 = tree.key_comp();
1116 auto &cmp2 = tree.get_compare();
1117
1118 // Both should return the same comparator
1119 EXPECT_TRUE(cmp1(1, 2));
1120 EXPECT_FALSE(cmp1(2, 1));
1121 EXPECT_TRUE(cmp2(1, 2));
1122 EXPECT_FALSE(cmp2(2, 1));
1123}
1124
1126{
1127 Tree tree(42);
1128
1129 auto *rng = tree.gsl_rng_object();
1130 EXPECT_NE(rng, nullptr);
1131}
1132
1134{
1135 Tree tree1(42);
1136 Tree tree2(42);
1137 NodePool pool1, pool2;
1138
1139 // Same seed, same insertion order -> same structure
1140 tree1.set_seed(999);
1141 tree2.set_seed(999);
1142
1143 for (int k : {1, 2, 3, 4, 5})
1144 {
1145 tree1.insert(pool1.make(k));
1146 tree2.insert(pool2.make(k));
1147 }
1148
1149 // Trees should have identical structure
1150 // (This is probabilistic but with same seed should be identical)
1152}
1153
1154// ============================================================================
1155// Copy Prevention Tests (compile-time)
1156// ============================================================================
1157
1158static_assert(!std::is_copy_assignable_v<Tree>,
1159 "Rand_Tree should not be copy assignable");
1160
1161static_assert(!std::is_copy_constructible_v<Tree>,
1162 "Rand_Tree should not be copy constructible");
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
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.
void split_pos(size_t pos, Gen_Rand_Tree &t1, Gen_Rand_Tree &t2) noexcept
Split a extended binary tree according to a position.
std::pair< long, Node * > find_position(const Key &key) const noexcept
Find the inorder position of a key in the tree.
Compare & get_compare() noexcept
bool split_key(const Key &key, Gen_Rand_Tree &t1, Gen_Rand_Tree &t2) noexcept
Split the tree according to a key.
Node * insert(Node *p) noexcept
Insert a node in the tree.
void split_key_dup(const Key &key, Gen_Rand_Tree &t1, Gen_Rand_Tree &t2) noexcept
Split the tree according to a key that could be in the tree.
size_t size() const noexcept
Return the number of nodes that have the tree.
Node * select(const size_t i) const
Return the i-th node in inorder sense.
gsl_rng * gsl_rng_object() noexcept
Get a pointer to gsl random number generator.
Node *& getRoot() noexcept
Return the tree's root.
Node * search(const Key &key) const noexcept
Search a key.
Node * remove_pos(Node *&root, const size_t pos) noexcept
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
void forget(Node *p)
Definition rand-tree.cc:93
std::vector< Node * > nodes
Definition rand-tree.cc:77
Node * make(int key)
Definition rand-tree.cc:86
Generator for uniformly random trees.
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
std::pair< long, Node * > position(const Key &key) const noexcept
Compute the inorder position of a key.
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.
STL namespace.
std::vector< int > inorder_keys(NodeT *root)
Definition rand-tree.cc:59
Tree::Node Node
Definition rand-tree.cc:55
Iterator on nodes of the tree.
Randomized binary search tree.
Utility functions for binary tree operations.
Randomized binary search tree.