Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
b_tree_test.cc
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
36#include <algorithm>
37#include <random>
38#include <set>
39#include <vector>
40
41#include <gtest/gtest.h>
42
43#include <tpl_b_tree.H>
44
45using namespace Aleph;
46using namespace testing;
47
48namespace
49{
50 template <typename T>
51 std::vector<T> to_vector(const Array<T> & arr)
52 {
53 std::vector<T> out;
54 out.reserve(arr.size());
55 for (size_t i = 0; i < arr.size(); ++i)
56 out.push_back(arr[i]);
57 return out;
58 }
59
60 template <class Tree>
61 std::vector<typename Tree::key_type> to_vector(const Tree & tree)
62 {
63 return to_vector(tree.keys());
64 }
65
66 template <class Tree>
67 void expect_matches_reference(const Tree & tree, const std::set<int> & ref)
68 {
69 const std::vector<int> tree_keys = to_vector(tree);
70 const std::vector<int> ref_keys(ref.begin(), ref.end());
71 const auto min_key = tree.min_key();
72 const auto max_key = tree.max_key();
74 EXPECT_EQ(tree.size(), ref.size());
75 EXPECT_TRUE(tree.verify());
76
77 if (ref.empty())
78 {
79 EXPECT_FALSE(min_key.has_value());
80 EXPECT_FALSE(max_key.has_value());
81 }
82 else
83 {
84 ASSERT_TRUE(min_key.has_value());
85 ASSERT_TRUE(max_key.has_value());
86 EXPECT_EQ(*min_key, *ref.begin());
87 EXPECT_EQ(*max_key, *ref.rbegin());
88 }
89 }
90
91 void expect_optional_eq(const std::optional<int> & got,
92 const std::optional<int> & expected)
93 {
94 ASSERT_EQ(got.has_value(), expected.has_value());
95 if (got.has_value())
97 }
98}
99
100class BTreeTest : public Test
101{
102protected:
104};
105
107{
108 Tree tree;
109
110 EXPECT_TRUE(tree.empty());
111 EXPECT_TRUE(tree.is_empty());
112 EXPECT_EQ(tree.size(), 0);
113 EXPECT_EQ(tree.height(), 0);
114 EXPECT_TRUE(to_vector(tree).empty());
115 EXPECT_FALSE(tree.min_key().has_value());
116 EXPECT_FALSE(tree.max_key().has_value());
117 EXPECT_FALSE(tree.lower_bound(10).has_value());
118 EXPECT_FALSE(tree.upper_bound(10).has_value());
119 EXPECT_TRUE(tree.verify());
120}
121
123{
124 Tree from_init = {40, 10, 90, 10, 20, 70, 40};
125 std::vector<int> src = {8, 3, 5, 8, 2, 9, 1};
126 Tree from_range(src.begin(), src.end());
127
128 EXPECT_EQ(to_vector(from_init), (std::vector<int>{10, 20, 40, 70, 90}));
129 EXPECT_EQ(to_vector(from_range), (std::vector<int>{1, 2, 3, 5, 8, 9}));
130 EXPECT_TRUE(from_init.verify());
131 EXPECT_TRUE(from_range.verify());
132}
133
135{
136 Tree tree;
137 for (int value : {40, 10, 90, 20, 70, 60, 30, 50, 80})
138 EXPECT_TRUE(tree.insert(value));
139
140 EXPECT_FALSE(tree.insert(70));
141 EXPECT_TRUE(tree.contains(10));
142 EXPECT_TRUE(tree.search(80));
143 EXPECT_FALSE(tree.contains(11));
144
145 EXPECT_EQ(to_vector(tree), (std::vector<int>{10, 20, 30, 40, 50, 60, 70, 80, 90}));
146 EXPECT_EQ(tree.height(), 2);
147
148 expect_optional_eq(tree.lower_bound(55), 60);
149 expect_optional_eq(tree.lower_bound(60), 60);
150 expect_optional_eq(tree.lower_bound(91), std::nullopt);
151
152 expect_optional_eq(tree.upper_bound(60), 70);
153 expect_optional_eq(tree.upper_bound(89), 90);
154 expect_optional_eq(tree.upper_bound(90), std::nullopt);
155
156 EXPECT_TRUE(tree.verify());
157}
158
160{
161 Tree tree;
162 std::set<int> ref;
163
164 for (int i = 1; i <= 40; ++i)
165 {
166 tree.insert(i);
167 ref.insert(i);
168 }
169
170 for (int value : {1, 2, 3, 7, 8, 9, 16, 17, 18, 25, 26, 27, 40, 31, 24, 12})
171 {
172 SCOPED_TRACE(value);
173 EXPECT_TRUE(tree.remove(value));
174 ref.erase(value);
176 }
177
178 EXPECT_FALSE(tree.remove(999));
180}
181
183{
184 Tree tree = {50, 20, 70, 10, 30, 60, 80};
185
186 Tree copy(tree);
188 assigned = tree;
189
192 EXPECT_TRUE(copy.verify());
193 EXPECT_TRUE(assigned.verify());
194
195 Tree moved(std::move(copy));
197 move_assigned = std::move(assigned);
198
201 EXPECT_TRUE(moved.verify());
202 EXPECT_TRUE(move_assigned.verify());
203}
204
206{
207 Tree tree;
208 std::set<int> ref;
209 std::mt19937 rng(0xBADA55);
210 std::uniform_int_distribution<int> op_dist(0, 5);
211 std::uniform_int_distribution<int> value_dist(-50, 150);
212
213 for (size_t step = 0; step < 1200; ++step)
214 {
216 const int value = value_dist(rng);
217
218 switch (op_dist(rng))
219 {
220 case 0:
221 case 1:
222 EXPECT_EQ(tree.insert(value), ref.insert(value).second);
223 break;
224
225 case 2:
226 EXPECT_EQ(tree.remove(value), ref.erase(value) == 1);
227 break;
228
229 case 3:
230 EXPECT_EQ(tree.contains(value), ref.contains(value));
231 break;
232
233 case 4:
234 {
235 const auto it = ref.lower_bound(value);
236 const std::optional<int> expected =
237 it == ref.end() ? std::nullopt : std::optional<int>(*it);
238 expect_optional_eq(tree.lower_bound(value), expected);
239 }
240 break;
241
242 default:
243 {
244 const auto it = ref.upper_bound(value);
245 const std::optional<int> expected =
246 it == ref.end() ? std::nullopt : std::optional<int>(*it);
247 expect_optional_eq(tree.upper_bound(value), expected);
248 }
249 break;
250 }
251
253 }
254}
TEST_F(BTreeTest, EmptyTreeReportsNoKeys)
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:139
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
Definition tpl_array.H:351
Generic B-Tree with configurable minimum degree.
Definition tpl_b_tree.H:134
QuadTree - Hierarchical spatial index for 2D points.
Definition quadtree.H:126
void empty(Node *&r) noexcept
Recursively delete all nodes.
Definition quadtree.H:255
void remove(const Point &p)
Remove a point from the tree.
Definition quadtree.H:502
Point * search(const Point &p) noexcept
Search for a point in the tree.
Definition quadtree.H:461
bool contains(const Point &p) const noexcept
Check if a point is within the tree's region.
Definition quadtree.H:424
Point * insert(Node *&r, const Point &p)
Recursive insert helper.
Definition quadtree.H:237
static mt19937 rng
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Itor2 copy(Itor1 sourceBeg, const Itor1 &sourceEnd, Itor2 destBeg)
Copy elements from one range to another.
Definition ahAlgo.H:584
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
std::vector< typename C::Item_Type > to_vector(const C &c)
Convert a container to a std::vector.
Definition ah-convert.H:238
Dnode< int > Test
Definition testDnode.C:37
B-Tree implementation with configurable minimum degree.