Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
splay-tree.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
38#include <algorithm>
39#include <vector>
40
41#include <gtest/gtest.h>
42
43#include <tpl_splay_tree.H>
44
45using namespace Aleph;
46
47namespace
48{
49 template <class Node>
50 size_t count_nodes(Node * root) noexcept
51 {
52 if (root == Node::NullPtr)
53 return 0;
54 return 1 + count_nodes(LLINK(root)) + count_nodes(RLINK(root));
55 }
56
57 template <class Node>
58 std::vector<typename Node::key_type> inorder_keys(Node * root)
59 {
60 std::vector<typename Node::key_type> keys;
61 if (root == Node::NullPtr)
62 return keys;
63
64 auto left = inorder_keys(LLINK(root));
65 keys.insert(keys.end(), left.begin(), left.end());
66 keys.push_back(KEY(root));
67 auto right = inorder_keys(RLINK(root));
68 keys.insert(keys.end(), right.begin(), right.end());
69 return keys;
70 }
71
72 template <class Tree>
73 void assert_valid_tree(Tree & tree)
74 {
75 ASSERT_TRUE(tree.verify()) << "BST invariant violated";
76 }
77
78 template <class Tree>
79 struct NodePool
80 {
81 using Node = typename Tree::Node;
82 std::vector<Node *> allocated;
83
84 Node * make(typename Node::key_type k)
85 {
86 auto * p = new Node(k);
87 allocated.push_back(p);
88 return p;
89 }
90
91 void forget(Node * p) noexcept
92 {
93 for (auto & q : allocated)
94 if (q == p)
95 {
96 q = nullptr;
97 return;
98 }
99 }
100
101 ~NodePool()
102 {
103 for (auto * p : allocated)
104 delete p;
105 }
106 };
107
108 struct StatefulLess
109 {
110 bool use_abs = false;
111
112 StatefulLess() = default;
113 explicit StatefulLess(bool b) : use_abs(b) {}
114
115 bool operator()(int a, int b) const
116 {
117 if (use_abs)
118 {
119 a = std::abs(a);
120 b = std::abs(b);
121 }
122 return a < b;
123 }
124 };
125
126} // namespace
127
129{
130 Splay_Tree<int> tree;
132 EXPECT_EQ(tree.search(42), nullptr);
133 EXPECT_EQ(tree.remove(42), nullptr);
134 EXPECT_TRUE(tree.verify());
135}
136
138{
139 using Tree = Splay_Tree<int>;
140 using Node = Tree::Node;
141
142 Tree tree;
143 NodePool<Tree> pool;
144
145 auto * p = pool.make(7);
146 EXPECT_EQ(tree.insert(p), p);
147 EXPECT_EQ(tree.getRoot(), p);
148 assert_valid_tree(tree);
150}
151
153{
154 using Tree = Splay_Tree<int>;
155 using Node = Tree::Node;
156
157 Tree tree;
158 NodePool<Tree> pool;
159
160 auto * p1 = pool.make(10);
161 EXPECT_EQ(tree.insert(p1), p1);
162
163 auto * p2 = pool.make(10);
164 EXPECT_EQ(tree.insert(p2), nullptr);
165
166 assert_valid_tree(tree);
168}
169
171{
172 using Tree = Splay_Tree<int>;
173 using Node = Tree::Node;
174
175 Tree tree;
176 NodePool<Tree> pool;
177
178 for (int i = 0; i < 5; ++i)
179 ASSERT_NE(tree.insert_dup(pool.make(42)), nullptr);
180
181 assert_valid_tree(tree);
183
184 auto keys = inorder_keys(tree.getRoot());
185 EXPECT_EQ(keys, (std::vector<int>{42, 42, 42, 42, 42}));
186}
187
189{
190 using Tree = Splay_Tree<int>;
191
192 Tree tree;
193 NodePool<Tree> pool;
194
195 for (int k : {5, 3, 7, 1, 4, 6, 8})
196 tree.insert(pool.make(k));
197
198 auto * found = tree.search(4);
199 ASSERT_NE(found, nullptr);
200 EXPECT_EQ(KEY(found), 4);
201 EXPECT_EQ(tree.getRoot(), found);
202
203 assert_valid_tree(tree);
204}
205
207{
208 using Tree = Splay_Tree<int>;
209
210 Tree tree;
211 NodePool<Tree> pool;
212
213 for (int k : {1, 3, 5})
214 tree.insert(pool.make(k));
215
216 EXPECT_EQ(tree.search(0), nullptr);
217 ASSERT_NE(tree.getRoot(), Tree::Node::NullPtr);
218 EXPECT_EQ(KEY(tree.getRoot()), 1);
219
220 EXPECT_EQ(tree.search(6), nullptr);
221 ASSERT_NE(tree.getRoot(), Tree::Node::NullPtr);
222 EXPECT_EQ(KEY(tree.getRoot()), 5);
223
224 assert_valid_tree(tree);
225}
226
228{
229 using Tree = Splay_Tree<int>;
230 using Node = Tree::Node;
231
232 Tree tree;
233 NodePool<Tree> pool;
234
235 auto * p1 = pool.make(10);
236 EXPECT_EQ(tree.search_or_insert(p1), p1);
237
238 auto * p2 = pool.make(10);
239 auto * ret2 = tree.search_or_insert(p2);
240 EXPECT_EQ(ret2, p1);
241
242 assert_valid_tree(tree);
244}
245
247{
248 using Tree = Splay_Tree<int>;
249 using Node = Tree::Node;
250
251 Tree tree;
252 NodePool<Tree> pool;
253
254 for (int k : {1, 2, 3, 4, 5})
255 tree.insert(pool.make(k));
256
257 Node * removed = tree.remove(3);
258 ASSERT_NE(removed, nullptr);
259 EXPECT_EQ(KEY(removed), 3);
260 EXPECT_EQ(LLINK(removed), Node::NullPtr);
261 EXPECT_EQ(RLINK(removed), Node::NullPtr);
262
263 pool.forget(removed);
264 delete removed;
265
266 EXPECT_EQ(tree.search(3), nullptr);
267 assert_valid_tree(tree);
268
269 auto keys = inorder_keys(tree.getRoot());
270 EXPECT_EQ(keys, (std::vector<int>{1, 2, 4, 5}));
271}
272
274{
275 using Tree = Splay_Tree<int>;
276 using Node = Tree::Node;
277
278 Tree tree;
279 NodePool<Tree> pool;
280
281 for (int k : {1, 2, 3, 4, 5})
282 tree.insert(pool.make(k));
283
284 Node * removed = tree.remove(5);
285 ASSERT_NE(removed, nullptr);
286 pool.forget(removed);
287 delete removed;
288
289 ASSERT_NE(tree.getRoot(), Node::NullPtr);
290 EXPECT_EQ(KEY(tree.getRoot()), 4);
291 assert_valid_tree(tree);
292}
293
295{
297 using Node = Tree::Node;
298
299 Tree tree(StatefulLess(true));
300 NodePool<Tree> pool;
301
302 auto * p = pool.make(1);
303 tree.insert(p);
304
305 Node * found = tree.search(-1);
306 ASSERT_NE(found, nullptr);
307 EXPECT_EQ(found, p);
308 EXPECT_EQ(tree.getRoot(), p);
309 assert_valid_tree(tree);
310}
WeightedDigraph::Node Node
@ KEY
Definition btreepic.C:169
bool verify() const
Return true if this is a consistent randomized tree.
Node * remove(const Key &key) noexcept
Remove a key from the tree.
NodeType< Key > Node
Node * search_or_insert(Node *p) noexcept
Search or insert a key.
Node * insert_dup(Node *p) noexcept
Insert a node in the tree.
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.
bool verify() const
Node *& getRoot() noexcept
Get the top-down splay tree's root.
Node * remove(const Key &key) noexcept
Remove a key from a top down splay tree.
Node * search(const Key &key) noexcept
Searches a key in a top-down splay tree.
void forget(Node *p)
Definition rand-tree.cc:93
Node * make(int key)
Definition rand-tree.cc:86
#define TEST(name)
__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.
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
Top-down splay tree implementation (without rank support).