Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tdrbtreerk_test.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
43#include <gtest/gtest.h>
44#include <tpl_tdRbTreeRk.H>
45#include <tpl_rbRk.H>
46#include <random>
47#include <set>
48#include <vector>
49#include <algorithm>
50
51using namespace Aleph;
52
53// ============================================================================
54// Test Fixtures
55// ============================================================================
56
57class TdRbTreeRkTest : public ::testing::Test
58{
59protected:
62
64 std::vector<Node*> allocated_nodes;
65
66 void TearDown() override
67 {
68 for (auto *node : allocated_nodes)
69 delete node;
70 allocated_nodes.clear();
71 }
72
73 Node* make_node(int key)
74 {
75 auto *node = new Node(key);
76 allocated_nodes.push_back(node);
77 return node;
78 }
79
80 std::vector<Node*> make_nodes(const std::vector<int>& keys)
81 {
82 std::vector<Node*> nodes;
83 for (int k : keys)
84 nodes.push_back(make_node(k));
85 return nodes;
86 }
87};
88
89// ============================================================================
90// Basic Operations Tests
91// ============================================================================
92
94{
95 EXPECT_TRUE(tree.is_empty());
96 EXPECT_EQ(tree.size(), 0u);
97 EXPECT_EQ(tree.search(42), nullptr);
98 EXPECT_TRUE(tree.verify());
99}
100
102{
103 Node *node = make_node(42);
104 EXPECT_EQ(tree.insert(node), node);
105
106 EXPECT_FALSE(tree.is_empty());
107 EXPECT_EQ(tree.size(), 1u);
108 EXPECT_EQ(tree.search(42), node);
109 EXPECT_TRUE(tree.verify());
110}
111
113{
114 std::vector<int> keys = {50, 25, 75, 10, 30, 60, 90};
115 auto nodes = make_nodes(keys);
116
117 for (auto *node : nodes)
118 EXPECT_NE(tree.insert(node), nullptr);
119
120 EXPECT_EQ(tree.size(), keys.size());
121 EXPECT_TRUE(tree.verify());
122
123 for (int key : keys)
124 EXPECT_NE(tree.search(key), nullptr);
125}
126
128{
129 Node *node1 = make_node(42);
130 Node *node2 = make_node(42);
131
132 EXPECT_EQ(tree.insert(node1), node1);
133 EXPECT_EQ(tree.insert(node2), nullptr);
134
135 EXPECT_EQ(tree.size(), 1u);
136 EXPECT_TRUE(tree.verify());
137}
138
140{
141 auto nodes = make_nodes({50, 25, 75, 10, 30});
142 for (auto *node : nodes)
143 tree.insert(node);
144
145 EXPECT_EQ(tree.size(), 5u);
146
147 Node *removed = tree.remove(25);
148 EXPECT_NE(removed, nullptr);
149 EXPECT_EQ(tree.size(), 4u);
150 EXPECT_EQ(tree.search(25), nullptr);
151 EXPECT_TRUE(tree.verify());
152}
153
155{
156 std::vector<int> keys = {50, 25, 75, 10, 30, 60, 90};
157 auto nodes = make_nodes(keys);
158
159 for (auto *node : nodes)
160 tree.insert(node);
161
162 // Remove in different order
163 std::vector<int> removal = {30, 10, 90, 50, 25, 75, 60};
164 for (int key : removal)
165 {
166 EXPECT_NE(tree.remove(key), nullptr) << "Failed to remove " << key;
167 EXPECT_TRUE(tree.verify()) << "Verify failed after removing " << key;
168 }
169
170 EXPECT_TRUE(tree.is_empty());
171}
172
173// ============================================================================
174// Rank Operation Tests (Select)
175// ============================================================================
176
178{
179 // Insert in random order
180 auto nodes = make_nodes({50, 25, 75, 10, 30, 60, 90});
181 for (auto *node : nodes)
182 tree.insert(node);
183
184 // Select should return nodes in sorted order
185 std::vector<int> expected = {10, 25, 30, 50, 60, 75, 90};
186
187 for (size_t i = 0; i < expected.size(); ++i)
188 {
189 Node *selected = tree.select(i);
190 ASSERT_NE(selected, nullptr) << "select(" << i << ") returned null";
191 EXPECT_EQ(KEY(selected), expected[i]) << "select(" << i << ") wrong";
192 }
193}
194
196{
197 auto nodes = make_nodes({10, 20, 30, 40, 50});
198 for (auto *node : nodes)
199 tree.insert(node);
200
201 // Remove middle element
202 tree.remove(30);
203
204 EXPECT_EQ(tree.size(), 4u);
205
206 // Check remaining order
207 std::vector<int> expected = {10, 20, 40, 50};
208 for (size_t i = 0; i < expected.size(); ++i)
209 {
210 Node *selected = tree.select(i);
211 ASSERT_NE(selected, nullptr);
212 EXPECT_EQ(KEY(selected), expected[i]);
213 }
214}
215
217{
218 // Insert 100 elements
219 for (int i = 0; i < 100; ++i)
220 tree.insert(make_node(i * 2)); // Even numbers 0-198
221
222 EXPECT_EQ(tree.size(), 100u);
223 EXPECT_TRUE(tree.verify());
224
225 // Select should return i-th smallest
226 for (size_t i = 0; i < 100; ++i)
227 {
228 Node *selected = tree.select(i);
229 ASSERT_NE(selected, nullptr);
230 EXPECT_EQ(KEY(selected), static_cast<int>(i * 2));
231 }
232}
233
234// ============================================================================
235// Position Operation Tests
236// ============================================================================
237
239{
240 auto nodes = make_nodes({10, 20, 30, 40, 50});
241 for (auto *node : nodes)
242 tree.insert(node);
243
244 // Each key should be at its expected position
245 auto [pos10, node10] = tree.position(10);
246 EXPECT_EQ(pos10, 0);
247 EXPECT_NE(node10, nullptr);
248
249 auto [pos30, node30] = tree.position(30);
250 EXPECT_EQ(pos30, 2);
251
252 auto [pos50, node50] = tree.position(50);
253 EXPECT_EQ(pos50, 4);
254}
255
257{
258 auto nodes = make_nodes({10, 20, 30, 40, 50});
259 for (auto *node : nodes)
260 tree.insert(node);
261
262 auto [pos, node] = tree.position(25); // Not in tree
263 EXPECT_EQ(pos, -1);
264 EXPECT_EQ(node, nullptr);
265}
266
268{
269 auto nodes = make_nodes({10, 20, 30, 40, 50});
270 for (auto *node : nodes)
271 tree.insert(node);
272
273 auto [pos, node] = tree.find_position(30);
274 EXPECT_EQ(pos, 2);
275 EXPECT_NE(node, nullptr);
276 EXPECT_EQ(KEY(node), 30);
277}
278
280{
281 auto nodes = make_nodes({10, 20, 30, 40, 50});
282 for (auto *node : nodes)
283 tree.insert(node);
284
285 // 25 would be at position 2 if it existed
286 auto [pos, node] = tree.find_position(25);
287 EXPECT_GE(pos, 0); // Should give a valid position
288}
289
290// ============================================================================
291// Insert Dup Tests
292// ============================================================================
293
295{
296 EXPECT_NE(tree.insert_dup(make_node(42)), nullptr);
297 EXPECT_NE(tree.insert_dup(make_node(42)), nullptr);
298 EXPECT_NE(tree.insert_dup(make_node(42)), nullptr);
299
300 EXPECT_EQ(tree.size(), 3u);
301 EXPECT_TRUE(tree.verify());
302}
303
304// ============================================================================
305// Split by Position Tests
306// ============================================================================
307
309{
310 auto nodes = make_nodes({10, 20, 30, 40, 50});
311 for (auto *node : nodes)
312 tree.insert(node);
313
315 tree.split_pos(2, t1, t2); // Split at position 2
316
317 EXPECT_TRUE(tree.is_empty());
318 EXPECT_EQ(t1.size(), 2u); // [10, 20]
319 EXPECT_EQ(t2.size(), 3u); // [30, 40, 50]
320
321 EXPECT_NE(t1.search(10), nullptr);
322 EXPECT_NE(t1.search(20), nullptr);
323 EXPECT_NE(t2.search(30), nullptr);
324 EXPECT_NE(t2.search(40), nullptr);
325 EXPECT_NE(t2.search(50), nullptr);
326
327 EXPECT_TRUE(t1.verify());
328 EXPECT_TRUE(t2.verify());
329}
330
332{
333 auto nodes = make_nodes({10, 20, 30});
334 for (auto *node : nodes)
335 tree.insert(node);
336
338 tree.split_pos(0, t1, t2);
339
340 EXPECT_EQ(t1.size(), 0u);
341 EXPECT_EQ(t2.size(), 3u);
342}
343
345{
346 auto nodes = make_nodes({10, 20, 30});
347 for (auto *node : nodes)
348 tree.insert(node);
349
351 tree.split_pos(10, t1, t2); // Beyond end
352
353 EXPECT_EQ(t1.size(), 3u);
354 EXPECT_EQ(t2.size(), 0u);
355}
356
357// ============================================================================
358// Remove by Position Tests
359// ============================================================================
360
362{
363 auto nodes = make_nodes({10, 20, 30, 40, 50});
364 for (auto *node : nodes)
365 tree.insert(node);
366
367 // Remove middle element (position 2 = 30)
368 Node *removed = tree.remove_pos(2);
369 ASSERT_NE(removed, nullptr);
370 EXPECT_EQ(KEY(removed), 30);
371
372 EXPECT_EQ(tree.size(), 4u);
373 EXPECT_EQ(tree.search(30), nullptr);
374 EXPECT_TRUE(tree.verify());
375}
376
377// ============================================================================
378// Move Semantics Tests
379// ============================================================================
380
382{
383 auto nodes = make_nodes({10, 20, 30});
384 for (auto *node : nodes)
385 tree.insert(node);
386
387 TdRbTreeRk<int> tree2(std::move(tree));
388
389 EXPECT_EQ(tree2.size(), 3u);
390 EXPECT_TRUE(tree.is_empty()); // NOLINT
391 EXPECT_TRUE(tree2.verify());
392}
393
395{
396 auto nodes = make_nodes({10, 20, 30});
397 for (auto *node : nodes)
398 tree.insert(node);
399
401 tree2.insert(make_node(100));
402
403 tree2 = std::move(tree);
404
405 EXPECT_EQ(tree2.size(), 3u);
406 EXPECT_TRUE(tree.is_empty()); // NOLINT
407 EXPECT_TRUE(tree2.verify());
408}
409
410// ============================================================================
411// Comparison with Bottom-Up Rb_Tree_Rk
412// ============================================================================
413
415{
418
419 std::vector<RbNodeRk<int>*> td_nodes, bu_nodes;
420
421 std::mt19937 rng(42);
422 std::uniform_int_distribution<int> dist(1, 1000);
423
424 std::set<int> keys_set;
425 while (keys_set.size() < 100)
426 keys_set.insert(dist(rng));
427
428 std::vector<int> keys(keys_set.begin(), keys_set.end());
429
430 // Insert into both
431 for (int key : keys)
432 {
433 auto *td_node = new RbNodeRk<int>(key);
434 auto *bu_node = new RbNodeRk<int>(key);
435 td_nodes.push_back(td_node);
436 bu_nodes.push_back(bu_node);
437
440 }
441
442 // Compare sizes
444
445 // Compare select results
446 for (size_t i = 0; i < keys.size(); ++i)
447 {
448 auto *td_sel = td_tree.select(i);
449 auto *bu_sel = bu_tree.select(i);
450 ASSERT_NE(td_sel, nullptr);
451 ASSERT_NE(bu_sel, nullptr);
452 EXPECT_EQ(KEY(td_sel), KEY(bu_sel)) << "select(" << i << ") differs";
453 }
454
455 // Verify both
456 EXPECT_TRUE(td_tree.verify());
457 EXPECT_TRUE(bu_tree.verify());
458
459 // Cleanup
460 for (auto *n : td_nodes) delete n;
461 for (auto *n : bu_nodes) delete n;
462}
463
464// ============================================================================
465// Stress Tests
466// ============================================================================
467
469{
470 TdRbTreeRk<int> tree;
471 std::set<int> reference;
472 std::vector<RbNodeRk<int>*> all_nodes;
473
474 std::mt19937 rng(12345);
475 std::uniform_int_distribution<int> key_dist(1, 5000);
476 std::uniform_int_distribution<int> op_dist(0, 2);
477
478 auto make = [&all_nodes](int k) {
479 auto *n = new RbNodeRk<int>(k);
480 all_nodes.push_back(n);
481 return n;
482 };
483
484 const int NUM_OPS = 2000;
485
486 for (int i = 0; i < NUM_OPS; ++i)
487 {
488 int op = op_dist(rng);
489 int key = key_dist(rng);
490
491 if (op == 0) // Insert
492 {
493 auto *node = make(key);
494 bool td_inserted = (tree.insert(node) != nullptr);
495 bool ref_inserted = reference.insert(key).second;
497 }
498 else if (op == 1) // Remove
499 {
500 bool td_removed = (tree.remove(key) != nullptr);
501 bool ref_removed = (reference.erase(key) > 0);
503 }
504 else // Search
505 {
506 bool td_found = (tree.search(key) != nullptr);
507 bool ref_found = (reference.count(key) > 0);
509 }
510
511 if (i % 200 == 0)
512 {
513 EXPECT_TRUE(tree.verify()) << "Verify failed at op " << i;
514 EXPECT_EQ(tree.size(), reference.size());
515 }
516 }
517
518 EXPECT_TRUE(tree.verify());
519
520 for (auto *n : all_nodes)
521 delete n;
522}
523
525{
526 TdRbTreeRk<int> tree;
527 std::vector<RbNodeRk<int>*> nodes;
528
529 const int N = 5000;
530
531 for (int i = 0; i < N; ++i)
532 {
533 auto *node = new RbNodeRk<int>(i);
534 nodes.push_back(node);
535 tree.insert(node);
536 }
537
538 EXPECT_EQ(tree.size(), static_cast<size_t>(N));
539 EXPECT_TRUE(tree.verify());
540
541 // Test select at various positions
542 for (int i = 0; i < N; i += 100)
543 {
544 auto *sel = tree.select(i);
545 ASSERT_NE(sel, nullptr);
546 EXPECT_EQ(KEY(sel), i);
547 }
548
549 for (auto *n : nodes)
550 delete n;
551}
552
553// ============================================================================
554// Iterator Tests
555// ============================================================================
556
558{
559 auto nodes = make_nodes({50, 25, 75, 10, 30});
560 for (auto *node : nodes)
561 tree.insert(node);
562
563 std::vector<int> traversal;
564 for (TdRbTreeRk<int>::Iterator it(tree); it.has_curr(); it.next())
565 traversal.push_back(KEY(it.get_curr()));
566
567 std::vector<int> expected = {10, 25, 30, 50, 75};
569}
570
571// ============================================================================
572// Main
573// ============================================================================
574
575int main(int argc, char **argv)
576{
577 ::testing::InitGoogleTest(&argc, argv);
578 return RUN_ALL_TESTS();
579}
580
int main()
WeightedDigraph::Node Node
@ KEY
Definition btreepic.C:169
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
Node * select(size_t i) const
Select i-th node in order.
Node * search(const Key &key) const noexcept
Search for a key.
NodeType< Key > Node
Node * insert(Node *p) noexcept
Insert a node.
size_t size() const noexcept
Get number of nodes O(1)
Node * remove(const Key &key) noexcept
Remove node with given key.
bool verify() const noexcept
Verify tree properties.
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
Extended Red-Black node with subtree counter.
Definition rbNodeRk.H:84
iterator end() noexcept
Return an STL-compatible end iterator.
iterator begin() noexcept
Return an STL-compatible iterator to the first element.
Node * make_node(int key)
std::vector< Node * > make_nodes(const std::vector< int > &keys)
void TearDown() override
std::vector< Node * > allocated_nodes
#define TEST(name)
static mt19937 rng
#define N
Definition fib.C:294
DynArray< Graph::Node * > nodes
Definition graphpic.C:406
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
DynList< T > maps(const C &c, Op op)
Classic map operation.
Red-Black binary search tree with nodes without virtual destructor and with subtree counters for sele...
Definition tpl_rbRk.H:1544
TEST_F(TdRbTreeRkTest, EmptyTree)
Red-Black tree with rank (order statistics).
Top-down Red-Black tree with rank support.