Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
treap_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
44#include <algorithm>
45#include <random>
46#include <set>
47#include <vector>
48
49#include <gtest/gtest.h>
50
51#include <tpl_treap.H>
52
53using namespace Aleph;
54using namespace testing;
55
56namespace
57{
58 // Helper to manage node allocation
59 template <class Tree>
60 struct NodePool
61 {
62 using Node = typename Tree::Node;
63
64 std::vector<Node *> allocated;
65
66 Node * make(const typename Node::key_type & key)
67 {
68 Node * p = new Node(key);
69 allocated.push_back(p);
70 return p;
71 }
72
73 void forget(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 (Node * p : allocated)
86 delete p;
87 }
88 };
89
90 // Collect keys in inorder traversal
91 template <class Node>
92 std::vector<typename Node::key_type> inorder_keys(Node * root)
93 {
94 std::vector<typename Node::key_type> keys;
95 if (root == nullptr || root == Node::NullPtr)
96 return keys;
97
98 auto left = inorder_keys(LLINK(root));
99 keys.insert(keys.end(), left.begin(), left.end());
100 keys.push_back(KEY(root));
101 auto right = inorder_keys(RLINK(root));
102 keys.insert(keys.end(), right.begin(), right.end());
103
104 return keys;
105 }
106
107 // Count nodes
108 template <class Node>
109 size_t count_nodes(Node * root)
110 {
111 if (root == nullptr || root == Node::NullPtr)
112 return 0;
113 return 1 + count_nodes(LLINK(root)) + count_nodes(RLINK(root));
114 }
115
116 // Check BST property
117 template <class Node>
118 bool check_bst_property(Node * p)
119 {
120 if (p == nullptr || p == Node::NullPtr)
121 return true;
122
123 if (LLINK(p) != nullptr && LLINK(p) != Node::NullPtr && KEY(LLINK(p)) >= KEY(p))
124 return false;
125
126 if (RLINK(p) != nullptr && RLINK(p) != Node::NullPtr && KEY(RLINK(p)) <= KEY(p))
127 return false;
128
130 }
131
132 // Check heap property on priorities (min-heap for Treap - lower priority = higher in tree)
133 template <class Node>
134 bool check_heap_property(Node * p)
135 {
136 if (p == nullptr || p == Node::NullPtr)
137 return true;
138
139 if (LLINK(p) != nullptr && LLINK(p) != Node::NullPtr && PRIO(LLINK(p)) < PRIO(p))
140 return false;
141
142 if (RLINK(p) != nullptr && RLINK(p) != Node::NullPtr && PRIO(RLINK(p)) < PRIO(p))
143 return false;
144
146 }
147
148 // Verify all Treap properties
149 template <class Tree>
150 bool verify_treap_properties(Tree & tree)
151 {
152 auto root = tree.getRoot();
153 if (root == nullptr || root == Tree::Node::NullPtr)
154 return true;
155
157 }
158}
159
160// =============================================================================
161// Test Fixtures
162// =============================================================================
163
164class TreapTest : public Test
165{
166protected:
169
172
173 void SetUp() override
174 {
175 tree.set_seed(42); // Reproducible tests
176 }
177
178 void insert_values(std::initializer_list<int> values)
179 {
180 for (int v : values)
181 tree.insert(pool.make(v));
182 }
183
184 size_t tree_size()
185 {
186 return count_nodes(tree.getRoot());
187 }
188
190 {
191 return tree.getRoot() == nullptr || tree.getRoot() == Node::NullPtr;
192 }
193};
194
195// =============================================================================
196// Basic Operations Tests
197// =============================================================================
198
200{
201 EXPECT_TRUE(tree_empty());
202}
203
205{
206 tree.insert(pool.make(10));
207 EXPECT_EQ(tree_size(), 1);
208 EXPECT_FALSE(tree_empty());
209
210 tree.insert(pool.make(5));
211 tree.insert(pool.make(15));
212 EXPECT_EQ(tree_size(), 3);
213}
214
216{
217 insert_values({50, 25, 75, 10, 30, 60, 90});
218
219 EXPECT_NE(tree.search(50), nullptr);
220 EXPECT_NE(tree.search(25), nullptr);
221 EXPECT_NE(tree.search(75), nullptr);
222 EXPECT_NE(tree.search(10), nullptr);
223
224 EXPECT_EQ(tree.search(100), nullptr);
225 EXPECT_EQ(tree.search(0), nullptr);
226}
227
229{
230 insert_values({50, 25, 75});
231 EXPECT_EQ(tree_size(), 3);
232
233 Node * removed = tree.remove(25);
234 EXPECT_NE(removed, nullptr);
235 EXPECT_EQ(tree_size(), 2);
236 EXPECT_EQ(tree.search(25), nullptr);
237
238 pool.forget(removed);
239 delete removed;
240}
241
243{
244 insert_values({50, 25, 75});
245
246 Node * removed = tree.remove(100);
247 EXPECT_EQ(removed, nullptr);
248 EXPECT_EQ(tree_size(), 3);
249}
250
251// =============================================================================
252// Treap Properties Tests
253// =============================================================================
254
260
262{
263 insert_values({50, 25, 75, 10, 30, 60, 90, 5, 15, 27, 35});
265}
266
268{
269 for (int i = 1; i <= 20; ++i)
270 tree.insert(pool.make(i));
271
273 EXPECT_EQ(tree_size(), 20);
274}
275
277{
278 for (int i = 20; i >= 1; --i)
279 tree.insert(pool.make(i));
280
282 EXPECT_EQ(tree_size(), 20);
283}
284
286{
287 insert_values({50, 25, 75, 10, 30, 60, 90});
289
290 Node * removed = tree.remove(25);
291 pool.forget(removed);
292 delete removed;
293
295}
296
297// =============================================================================
298// Ordering Tests
299// =============================================================================
300
302{
303 insert_values({50, 25, 75, 10, 30, 60, 90});
304
305 auto keys = inorder_keys(tree.getRoot());
306
307 EXPECT_TRUE(std::is_sorted(keys.begin(), keys.end()));
308 EXPECT_EQ(keys.size(), 7);
309}
310
312{
313 insert_values({50, 25, 75, 10, 30, 60, 90});
314
315 auto keys = inorder_keys(tree.getRoot());
316
317 EXPECT_EQ(keys.front(), 10); // Min
318 EXPECT_EQ(keys.back(), 90); // Max
319}
320
321// =============================================================================
322// Priority Tests
323// =============================================================================
324
326{
327 tree.insert(pool.make(50));
328 tree.insert(pool.make(25));
329 tree.insert(pool.make(75));
330
331 // All nodes should have valid priorities
332 Node * root = tree.getRoot();
333 EXPECT_TRUE(root != nullptr && root != Node::NullPtr);
334}
335
337{
338 insert_values({50, 25, 75, 10, 30, 60, 90, 5, 15, 27, 35});
339
340 Node * root = tree.getRoot();
342}
343
344// =============================================================================
345// Seed Reproducibility Tests
346// =============================================================================
347
349{
350 // First tree with seed 12345
351 Tree tree1;
352 tree1.set_seed(12345);
354
355 for (int v : {50, 25, 75, 10, 30})
356 tree1.insert(pool1.make(v));
357
358 auto keys1 = inorder_keys(tree1.getRoot());
359 auto prio1 = PRIO(tree1.getRoot());
360
361 // Second tree with same seed
362 Tree tree2;
363 tree2.set_seed(12345);
365
366 for (int v : {50, 25, 75, 10, 30})
367 tree2.insert(pool2.make(v));
368
369 auto keys2 = inorder_keys(tree2.getRoot());
370 auto prio2 = PRIO(tree2.getRoot());
371
372 // Keys should be identical (BST property)
374 // Root priorities should be identical (same seed)
376}
377
378// =============================================================================
379// Stress Tests
380// =============================================================================
381
383{
384 std::mt19937 rng(42);
385 std::uniform_int_distribution<int> dist(1, 10000);
386 std::set<int> inserted;
387
388 for (int i = 0; i < 1000; ++i)
389 {
390 int value = dist(rng);
391 if (inserted.insert(value).second)
392 tree.insert(pool.make(value));
393 }
394
396 EXPECT_EQ(tree_size(), inserted.size());
397}
398
400{
401 std::mt19937 rng(123);
402 std::uniform_int_distribution<int> dist(1, 1000);
403 std::vector<int> values;
404
405 // Insert 500 random values
406 for (int i = 0; i < 500; ++i)
407 {
408 int value = dist(rng);
409 values.push_back(value);
410 tree.insert(pool.make(value));
411 }
412
414
415 // Remove half of them
416 std::shuffle(values.begin(), values.end(), rng);
417 for (size_t i = 0; i < values.size() / 2; ++i)
418 {
419 Node * removed = tree.remove(values[i]);
420 if (removed)
421 {
422 pool.forget(removed);
423 delete removed;
424 }
425 }
426
428}
429
430// =============================================================================
431// Large Scale Tests
432// =============================================================================
433
435{
436 for (int i = 1; i <= 10000; ++i)
437 tree.insert(pool.make(i));
438
440 EXPECT_EQ(tree_size(), 10000);
441
442 // Verify some keys present
443 EXPECT_NE(tree.search(1), nullptr);
444 EXPECT_NE(tree.search(5000), nullptr);
445 EXPECT_NE(tree.search(10000), nullptr);
446}
447
448// =============================================================================
449// Main
450// =============================================================================
451
452int main(int argc, char **argv)
453{
455 return RUN_ALL_TESTS();
456}
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
Node * remove(const Key &key) noexcept
Remove a key from the tree.
NodeType< Key > Node
Node * insert(Node *p) noexcept
Insert a node in the tree.
Node *& getRoot() noexcept
Return the tree's root.
Node * search(const Key &key) const noexcept
Search a key.
void set_seed(const unsigned long seed) noexcept
Set the random number generator seed.
Definition tpl_treap.H:171
NodeType< Key > Node
Definition tpl_treap.H:150
Node *& getRoot() noexcept
Return the tree's root.
Definition tpl_treap.H:212
Node * insert(Node *root, Node *p) noexcept
Definition tpl_treap.H:227
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
Node * make(int key)
Definition rand-tree.cc:86
bool tree_empty()
size_t tree_size()
void SetUp() override
Tree::Node Node
NodePool< Tree > pool
void insert_values(std::initializer_list< int > values)
static mt19937 rng
__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
constexpr Node *& RLINK(Node *p) noexcept
Return the right tree of p.
unsigned long & PRIO(Node *p) noexcept
Access the priority of a treap node.
Definition treapNode.H:120
constexpr Node *& LLINK(Node *p) noexcept
Return a pointer to left subtree.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
DynList< T > maps(const C &c, Op op)
Classic map operation.
std::vector< int > inorder_keys(NodeT *root)
Definition rand-tree.cc:59
Treap: randomized BST combining tree and heap properties.
TEST_F(TreapTest, EmptyTreeIsEmpty)