Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
bplus_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 <stdexcept>
40#include <vector>
41
42#include <gtest/gtest.h>
43
44#include <tpl_bplus_tree.H>
45
46using namespace Aleph;
47using namespace testing;
48
49namespace
50{
51 template <typename T>
52 std::vector<T> to_vector(const Array<T> & arr)
53 {
54 std::vector<T> out;
55 out.reserve(arr.size());
56 for (size_t i = 0; i < arr.size(); ++i)
57 out.push_back(arr[i]);
58 return out;
59 }
60
61 template <class Tree>
62 std::vector<typename Tree::key_type> to_vector(const Tree & tree)
63 {
64 return to_vector(tree.keys());
65 }
66
67 template <class Tree>
68 void expect_matches_reference(const Tree & tree, const std::set<int> & ref)
69 {
70 const std::vector<int> tree_keys = to_vector(tree);
71 const std::vector<int> ref_keys(ref.begin(), ref.end());
73 EXPECT_EQ(tree.size(), ref.size());
74 EXPECT_TRUE(tree.verify());
75
76 if (ref.empty())
77 {
78 EXPECT_FALSE(tree.min_key().has_value());
79 EXPECT_FALSE(tree.max_key().has_value());
80 }
81 else
82 {
83 ASSERT_TRUE(tree.min_key().has_value());
84 ASSERT_TRUE(tree.max_key().has_value());
85 EXPECT_EQ(*tree.min_key(), *ref.begin());
86 EXPECT_EQ(*tree.max_key(), *ref.rbegin());
87 }
88 }
89
90 void expect_optional_eq(const std::optional<int> & got,
91 const std::optional<int> & expected)
92 {
93 ASSERT_EQ(got.has_value(), expected.has_value());
94 if (got.has_value())
96 }
97
98 std::vector<int> ref_range(const std::set<int> & ref, int first, int last)
99 {
100 std::vector<int> out;
101 if (last < first)
102 return out;
103
104 for (auto it = ref.lower_bound(first);
105 it != ref.end() and *it <= last;
106 ++it)
107 out.push_back(*it);
108 return out;
109 }
110}
111
112class BPlusTreeTest : public Test
113{
114protected:
116};
117
119{
120 Tree tree;
121
122 EXPECT_TRUE(tree.empty());
123 EXPECT_TRUE(tree.is_empty());
124 EXPECT_EQ(tree.size(), 0);
125 EXPECT_EQ(tree.height(), 0);
126 EXPECT_TRUE(to_vector(tree).empty());
127 EXPECT_TRUE(to_vector(tree.range(0, 10)).empty());
128 EXPECT_FALSE(tree.min_key().has_value());
129 EXPECT_FALSE(tree.max_key().has_value());
130 EXPECT_FALSE(tree.lower_bound(10).has_value());
131 EXPECT_FALSE(tree.upper_bound(10).has_value());
132 EXPECT_TRUE(tree.verify());
133}
134
136{
137 Tree tree = {40, 10, 90, 10, 20, 70, 40, 60, 30, 50};
138
139 EXPECT_EQ(to_vector(tree), (std::vector<int>{10, 20, 30, 40, 50, 60, 70, 90}));
140 EXPECT_EQ(to_vector(tree.range(25, 65)), (std::vector<int>{30, 40, 50, 60}));
141 EXPECT_EQ(to_vector(tree.range(10, 10)), (std::vector<int>{10}));
142 EXPECT_TRUE(tree.verify());
143}
144
146{
147 Tree tree;
148 for (int i = 1; i <= 40; ++i)
149 EXPECT_TRUE(tree.insert(i * 3));
150
151 EXPECT_GT(tree.height(), 2);
152 expect_optional_eq(tree.lower_bound(1), 3);
153 expect_optional_eq(tree.lower_bound(58), 60);
154 expect_optional_eq(tree.lower_bound(120), 120);
155 expect_optional_eq(tree.lower_bound(121), std::nullopt);
156
157 expect_optional_eq(tree.upper_bound(57), 60);
158 expect_optional_eq(tree.upper_bound(120), std::nullopt);
159 EXPECT_EQ(to_vector(tree.range(27, 42)), (std::vector<int>{27, 30, 33, 36, 39, 42}));
160 EXPECT_TRUE(tree.verify());
161}
162
164{
165 Tree tree;
166 for (int value : {105, 110, 115, 120, 125, 130, 135, 140, 145, 150})
167 EXPECT_TRUE(tree.insert(value));
168
169 std::vector<int> all_keys;
170 for (auto it = tree.get_it(); it.has_curr(); it.next_ne())
171 all_keys.push_back(it.get_curr());
173 (std::vector<int>{105, 110, 115, 120, 125, 130, 135, 140, 145, 150}));
174
175 std::vector<int> band;
176 auto band_it = tree.get_range_it(118, 141);
177 ASSERT_TRUE(band_it.has_curr());
178 EXPECT_EQ(*band_it, 120);
179 band.push_back(band_it.get_curr());
180 band_it.next();
181 for (; band_it.has_curr(); band_it.next_ne())
182 band.push_back(band_it.get_curr());
183
184 EXPECT_EQ(band, (std::vector<int>{120, 125, 130, 135, 140}));
185}
186
188{
189 Tree tree;
190 std::set<int> ref;
191
192 for (int i = 1; i <= 60; ++i)
193 {
194 tree.insert(i);
195 ref.insert(i);
196 }
197
198 for (int value : {1, 2, 3, 6, 7, 8, 17, 18, 19, 28, 29, 30, 42, 43, 44, 60, 59})
199 {
200 EXPECT_TRUE(tree.remove(value));
201 ref.erase(value);
203 }
204
205 EXPECT_FALSE(tree.remove(999));
206 EXPECT_EQ(to_vector(tree.range(20, 27)), ref_range(ref, 20, 27));
208}
209
211{
212 Tree tree = {50, 20, 70, 10, 30, 60, 80, 25, 27};
213
214 Tree copy(tree);
216 assigned = tree;
217
220 EXPECT_TRUE(copy.verify());
221 EXPECT_TRUE(assigned.verify());
222
223 Tree moved(std::move(copy));
225 move_assigned = std::move(assigned);
226
229 EXPECT_TRUE(moved.verify());
230 EXPECT_TRUE(move_assigned.verify());
231}
232
234{
235 Tree tree = {1, 2, 3};
236 EXPECT_THROW((void) tree.range(10, 5), std::invalid_argument);
237}
238
240{
241 Tree tree;
242 std::set<int> ref;
243 std::mt19937 rng(0xBEEFBEEF);
244 std::uniform_int_distribution<int> op_dist(0, 6);
245 std::uniform_int_distribution<int> value_dist(-80, 180);
246
247 for (size_t step = 0; step < 1400; ++step)
248 {
249 const int value = value_dist(rng);
250
251 switch (op_dist(rng))
252 {
253 case 0:
254 case 1:
255 EXPECT_EQ(tree.insert(value), ref.insert(value).second);
256 break;
257
258 case 2:
259 EXPECT_EQ(tree.remove(value), ref.erase(value) == 1);
260 break;
261
262 case 3:
263 EXPECT_EQ(tree.contains(value), ref.contains(value));
264 break;
265
266 case 4:
267 {
268 const auto it = ref.lower_bound(value);
269 const std::optional<int> expected =
270 it == ref.end() ? std::nullopt : std::optional<int>(*it);
271 expect_optional_eq(tree.lower_bound(value), expected);
272 }
273 break;
274
275 case 5:
276 {
277 const auto it = ref.upper_bound(value);
278 const std::optional<int> expected =
279 it == ref.end() ? std::nullopt : std::optional<int>(*it);
280 expect_optional_eq(tree.upper_bound(value), expected);
281 }
282 break;
283
284 default:
285 {
286 int a = value_dist(rng);
287 int b = value_dist(rng);
288 if (a > b)
289 std::swap(a, b);
290 EXPECT_EQ(to_vector(tree.range(a, b)), ref_range(ref, a, b));
291 }
292 break;
293 }
294
296 }
297}
TEST_F(BPlusTreeTest, 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.
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
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
and
Check uniqueness with explicit hash + equality functors.
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 linked leaves and configurable degree.