Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
htdrbtreerk_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_hRbTreeRk.H>
45#include <tpl_rbRk.H>
46#include <set>
47#include <vector>
48#include <algorithm>
49#include <random>
50
51using namespace Aleph;
52
53// ============================================================================
54// Test Fixture
55// ============================================================================
56
57class HtdRbTreeRkTest : public ::testing::Test
58{
59protected:
62
64 std::vector<Node*> nodes;
65
66 void TearDown() override
67 {
68 for (auto* n : nodes)
69 delete n;
70 nodes.clear();
71 }
72
73 Node* make_node(int key)
74 {
75 Node* n = new Node(key);
76 nodes.push_back(n);
77 return n;
78 }
79
80 void insert_range(int start, int end)
81 {
82 for (int i = start; i < end; ++i)
84 }
85};
86
87// ============================================================================
88// Basic Operations Tests
89// ============================================================================
90
92{
93 EXPECT_TRUE(tree.is_empty());
94 EXPECT_EQ(tree.size(), 0u);
95 EXPECT_TRUE(tree.verify());
96}
97
99{
100 tree.insert(make_node(42));
101
102 EXPECT_FALSE(tree.is_empty());
103 EXPECT_EQ(tree.size(), 1u);
104 EXPECT_TRUE(tree.verify());
105
106 auto* found = tree.search(42);
107 ASSERT_NE(found, nullptr);
108 EXPECT_EQ(KEY(found), 42);
109}
110
112{
113 insert_range(0, 10);
114
115 EXPECT_EQ(tree.size(), 10u);
116 EXPECT_TRUE(tree.verify());
117
118 for (int i = 0; i < 10; ++i)
119 EXPECT_NE(tree.search(i), nullptr) << "Missing key " << i;
120}
121
123{
124 tree.insert(make_node(42));
125 auto* dup = tree.insert(make_node(42));
126
127 EXPECT_EQ(dup, nullptr);
128 EXPECT_EQ(tree.size(), 1u);
129 EXPECT_TRUE(tree.verify());
130}
131
133{
134 tree.insert_dup(make_node(42));
135 tree.insert_dup(make_node(42));
136 tree.insert_dup(make_node(42));
137
138 EXPECT_EQ(tree.size(), 3u);
139 EXPECT_TRUE(tree.verify());
140}
141
143{
144 insert_range(0, 5);
145
146 auto* removed = tree.remove(2);
147 ASSERT_NE(removed, nullptr);
148 EXPECT_EQ(KEY(removed), 2);
149 EXPECT_EQ(tree.size(), 4u);
150 EXPECT_EQ(tree.search(2), nullptr);
151 EXPECT_TRUE(tree.verify());
152}
153
155{
156 std::vector<int> keys = {50, 25, 75, 10, 30, 60, 90};
157 for (int k : keys)
158 tree.insert(make_node(k));
159
160 for (int k : keys)
161 {
162 auto* removed = tree.remove(k);
163 ASSERT_NE(removed, nullptr) << "Failed to remove " << k;
164 EXPECT_TRUE(tree.verify()) << "Verify failed after removing " << k;
165 }
166
167 EXPECT_TRUE(tree.is_empty());
168}
169
170// ============================================================================
171// Rank Operations Tests
172// ============================================================================
173
175{
176 std::vector<int> keys = {50, 25, 75, 10, 30, 60, 90};
177 for (int k : keys)
178 tree.insert(make_node(k));
179
180 // Sorted order: 10, 25, 30, 50, 60, 75, 90
181 std::vector<int> expected = {10, 25, 30, 50, 60, 75, 90};
182
183 for (size_t i = 0; i < expected.size(); ++i)
184 {
185 auto* selected = tree.select(i);
186 ASSERT_NE(selected, nullptr) << "select(" << i << ") returned null";
187 EXPECT_EQ(KEY(selected), expected[i]) << "select(" << i << ") wrong";
188 }
189}
190
192{
193 insert_range(0, 5); // 0, 1, 2, 3, 4
194
195 tree.remove(2); // Now: 0, 1, 3, 4
196
197 EXPECT_EQ(tree.size(), 4u);
198 EXPECT_EQ(KEY(tree.select(0)), 0);
199 EXPECT_EQ(KEY(tree.select(1)), 1);
200 EXPECT_EQ(KEY(tree.select(2)), 3);
201 EXPECT_EQ(KEY(tree.select(3)), 4);
202 EXPECT_TRUE(tree.verify());
203}
204
206{
207 const int N = 100;
208 for (int i = 0; i < N; ++i)
209 tree.insert(make_node(i * 2)); // Even numbers 0, 2, 4, ..., 198
210
211 EXPECT_EQ(tree.size(), static_cast<size_t>(N));
212 EXPECT_TRUE(tree.verify());
213
214 for (int i = 0; i < N; ++i)
215 {
216 auto* selected = tree.select(i);
217 ASSERT_NE(selected, nullptr);
218 EXPECT_EQ(KEY(selected), i * 2);
219 }
220}
221
223{
224 std::vector<int> keys = {10, 20, 30, 40, 50};
225 for (int k : keys)
226 tree.insert(make_node(k));
227
228 for (size_t i = 0; i < keys.size(); ++i)
229 {
230 auto [pos, node] = tree.position(keys[i]);
231 EXPECT_EQ(pos, static_cast<long>(i)) << "Position wrong for " << keys[i];
232 ASSERT_NE(node, nullptr);
233 EXPECT_EQ(KEY(node), keys[i]);
234 }
235}
236
238{
239 insert_range(0, 10);
240
241 auto [pos, node] = tree.position(100);
242 EXPECT_EQ(pos, -1);
243 EXPECT_EQ(node, nullptr);
244}
245
247{
248 insert_range(0, 10);
249
250 auto [pos, node] = tree.find_position(5);
251 EXPECT_EQ(pos, 5);
252 ASSERT_NE(node, nullptr);
253 EXPECT_EQ(KEY(node), 5);
254}
255
257{
258 // Insert 0, 2, 4, 6, 8
259 for (int i = 0; i < 5; ++i)
260 tree.insert(make_node(i * 2));
261
262 // Find position for 5 (would be between 4 and 6, so position 3)
263 // For non-existing keys, find_position returns the position where
264 // the key would be and nullptr for the node
265 auto [pos, node] = tree.find_position(5);
266 // Position 3 means: after 0, 2, 4 (positions 0, 1, 2)
267 // Note: find_position may return different behavior based on implementation
268 // The key 5 would go between 4 (pos 2) and 6 (pos 3), so position could be 2 or 3
269 EXPECT_GE(pos, 2);
270 EXPECT_LE(pos, 3);
271}
272
274{
275 insert_range(0, 5); // 0, 1, 2, 3, 4
276
277 auto* removed = tree.remove_pos(2); // Remove element at position 2 (which is key 2)
278 ASSERT_NE(removed, nullptr);
279 EXPECT_EQ(KEY(removed), 2);
280 EXPECT_EQ(tree.size(), 4u);
281 EXPECT_TRUE(tree.verify());
282}
283
285{
286 insert_range(0, 6); // 0, 1, 2, 3, 4, 5
287
288 Tree t1, t2;
289 tree.split_pos(3, t1, t2);
290
291 EXPECT_EQ(t1.size(), 3u); // 0, 1, 2
292 EXPECT_EQ(t2.size(), 3u); // 3, 4, 5
293 EXPECT_TRUE(tree.is_empty());
294
295 EXPECT_TRUE(t1.verify());
296 EXPECT_TRUE(t2.verify());
297
298 // Check contents
299 EXPECT_NE(t1.search(0), nullptr);
300 EXPECT_NE(t1.search(1), nullptr);
301 EXPECT_NE(t1.search(2), nullptr);
302 EXPECT_NE(t2.search(3), nullptr);
303 EXPECT_NE(t2.search(4), nullptr);
304 EXPECT_NE(t2.search(5), nullptr);
305}
306
307// ============================================================================
308// Move Semantics Tests
309// ============================================================================
310
312{
313 insert_range(0, 5);
314
315 Tree tree2(std::move(tree));
316
317 EXPECT_EQ(tree2.size(), 5u);
318 EXPECT_TRUE(tree2.verify());
319
320 for (int i = 0; i < 5; ++i)
321 EXPECT_NE(tree2.search(i), nullptr);
322}
323
325{
326 insert_range(0, 5);
327
328 Tree tree2;
329 tree2 = std::move(tree);
330
331 EXPECT_EQ(tree2.size(), 5u);
332 EXPECT_TRUE(tree2.verify());
333}
334
335// ============================================================================
336// Comparison with Bottom-Up Rank Tree
337// ============================================================================
338
340{
341 // Create parallel trees with unique keys
344
345 std::vector<Node*> htd_nodes;
346 std::vector<RbNodeRk<int>*> bu_nodes;
347
348 // Insert same elements (unique keys)
349 for (int i = 0; i < 50; ++i)
350 {
351 int key = i * 7; // Use unique keys
352
353 auto* htd_node = new Node(key);
354 auto* bu_node = new RbNodeRk<int>(key);
355 htd_nodes.push_back(htd_node);
356 bu_nodes.push_back(bu_node);
357
358 auto* htd_result = htd.insert(htd_node);
359 auto* bu_result = bu.insert(bu_node);
360
361 EXPECT_NE(htd_result, nullptr);
362 EXPECT_NE(bu_result, nullptr);
363 }
364
365 EXPECT_EQ(htd.size(), bu.size());
366 EXPECT_TRUE(htd.verify());
367
368 // Compare select results
369 for (size_t i = 0; i < htd.size(); ++i)
370 {
371 auto* htd_sel = htd.select(i);
372 auto* bu_sel = bu.select(i);
373 EXPECT_EQ(KEY(htd_sel), KEY(bu_sel)) << "select(" << i << ") differs";
374 }
375
376 // Cleanup
377 for (auto* n : htd_nodes) delete n;
378 for (auto* n : bu_nodes) delete n;
379}
380
381// ============================================================================
382// Stress Tests
383// ============================================================================
384
386{
387 // Insert many elements, then remove some
388 for (int i = 0; i < 200; ++i)
389 tree.insert(make_node(i));
390
391 EXPECT_EQ(tree.size(), 200u);
392 EXPECT_TRUE(tree.verify());
393
394 // Remove half
395 for (int i = 0; i < 200; i += 2)
396 tree.remove(i);
397
398 EXPECT_EQ(tree.size(), 100u);
399 EXPECT_TRUE(tree.verify());
400
401 // Verify select works correctly
402 int expected = 1; // Odd numbers starting from 1
403 for (size_t i = 0; i < tree.size(); ++i)
404 {
405 EXPECT_EQ(KEY(tree.select(i)), expected);
406 expected += 2;
407 }
408}
409
411{
412 const int N = 5000;
413
414 for (int i = 0; i < N; ++i)
415 tree.insert(make_node(i));
416
417 EXPECT_EQ(tree.size(), static_cast<size_t>(N));
418 EXPECT_TRUE(tree.verify());
419
420 // Test select at various positions
421 EXPECT_EQ(KEY(tree.select(0)), 0);
422 EXPECT_EQ(KEY(tree.select(N/2)), N/2);
423 EXPECT_EQ(KEY(tree.select(N-1)), N-1);
424
425 // Remove half
426 for (int i = 0; i < N; i += 2)
427 tree.remove(i);
428
429 EXPECT_EQ(tree.size(), static_cast<size_t>(N/2));
430 EXPECT_TRUE(tree.verify());
431
432 // Check remaining elements
433 for (int i = 1; i < N; i += 2)
434 EXPECT_NE(tree.search(i), nullptr);
435}
436
438{
439 insert_range(0, 100);
440
441 // Verify select and position are inverses
442 for (size_t i = 0; i < 100; ++i)
443 {
444 auto* selected = tree.select(i);
445 auto [pos, node] = tree.position(KEY(selected));
446
447 EXPECT_EQ(pos, static_cast<long>(i));
448 EXPECT_EQ(node, selected);
449 }
450}
451
452// ============================================================================
453// Iterator Tests
454// ============================================================================
455
457{
458 std::vector<int> keys = {50, 25, 75, 10, 30, 60, 90};
459 for (int k : keys)
460 tree.insert(make_node(k));
461
462 std::vector<int> expected = {10, 25, 30, 50, 60, 75, 90};
463 std::vector<int> actual;
464
465 for (Tree::Iterator it(tree); it.has_curr(); it.next())
466 actual.push_back(KEY(it.get_curr()));
467
469}
470
471// ============================================================================
472// Edge Cases
473// ============================================================================
474
476{
477 EXPECT_EQ(tree.remove(42), nullptr);
478}
479
481{
482 insert_range(0, 5);
483 EXPECT_THROW(tree.select(10), std::out_of_range);
484}
485
487{
488 insert_range(0, 5);
489 EXPECT_THROW(tree.remove_pos(10), std::out_of_range);
490}
491
493{
494 auto* n1 = make_node(42);
495 auto* result1 = tree.search_or_insert(n1);
496 EXPECT_EQ(result1, n1);
497 EXPECT_EQ(tree.size(), 1u);
498
499 auto* n2 = make_node(42);
500 auto* result2 = tree.search_or_insert(n2);
501 EXPECT_EQ(result2, n1); // Returns existing node
502 EXPECT_EQ(tree.size(), 1u);
503}
504
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
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
Node * insert(Node *p) noexcept
void insert_range(int start, int end)
Node * make_node(int key)
RbNodeRk< int > Node
std::vector< Node * > nodes
void TearDown() override
#define N
Definition fib.C:294
TEST_F(HtdRbTreeRkTest, EmptyTree)
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
DynList< T > maps(const C &c, Op op)
Classic map operation.
Iterator on nodes of the tree.
Red-Black binary search tree with nodes without virtual destructor and with subtree counters for sele...
Definition tpl_rbRk.H:1544
Hybrid top-down/bottom-up red-black tree with rank support.
Red-Black tree with rank (order statistics).