Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
bin-node-xt.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 <random>
40#include <set>
41#include <stdexcept>
42#include <vector>
43
44#include <gtest/gtest.h>
45
46#include <tpl_binNodeXt.H>
47#include <tpl_binNodeUtils.H>
48
49using namespace Aleph;
50using namespace testing;
51
52namespace
53{
54 using Node = BinNodeXt<int>;
55
56 struct NodePool
57 {
58 std::vector<Node *> allocated;
59
60 Node * make(int k)
61 {
62 auto * p = new Node(k);
63 allocated.push_back(p);
64 return p;
65 }
66 void forget(Node * p) noexcept
67 {
68 for (auto & q : allocated)
69 if (q == p)
70 {
71 q = nullptr;
72 return;
73 }
74 }
75
76 ~NodePool()
77 {
78 for (auto * p : allocated)
79 delete p;
80 }
81 };
82
83 void delete_tree(Node * root) noexcept
84 {
85 if (root == Node::NullPtr)
86 return;
89 delete root;
90 }
91
92 std::vector<int> inorder_keys(Node * root)
93 {
94 std::vector<int> keys;
95 Aleph::infix_for_each<Node>(root, [&] (Node * p) { keys.push_back(KEY(p)); });
96 return keys;
97 }
98
100 {
103 if (root != Node::NullPtr)
105 }
106
108 {
110 if (root != Node::NullPtr)
112 }
113
114 struct Greater
115 {
116 bool operator()(int a, int b) const noexcept { return a > b; }
117 };
118}
119
121{
122 NodePool pool;
123 Node * root = Node::NullPtr;
124 for (int k : {1, 2, 4, 5})
125 ASSERT_NE(insert_by_key_xt(root, pool.make(k)), Node::NullPtr);
126
127 Node * l = Node::NullPtr;
128 Node * r = Node::NullPtr;
130 EXPECT_EQ(root, Node::NullPtr);
131
134 EXPECT_EQ(inorder_keys(l), (std::vector<int>{1, 2}));
135 EXPECT_EQ(inorder_keys(r), (std::vector<int>{4, 5}));
136}
137
139{
140 NodePool pool;
141 Node * root = Node::NullPtr;
142 for (const int k : {1, 2, 3, 4, 5})
143 ASSERT_NE(insert_by_key_xt(root, pool.make(k)), Node::NullPtr);
144
145 Node * l = Node::NullPtr;
146 Node * r = Node::NullPtr;
148
150 EXPECT_EQ(inorder_keys(root), (std::vector<int>{1, 2, 3, 4, 5}));
151}
152
154{
155 NodePool pool;
156 Node * root = Node::NullPtr;
157 for (const int k : {1, 2, 2, 3, 4})
158 ASSERT_NE(insert_dup_by_key_xt(root, pool.make(k)), Node::NullPtr);
159
160 Node * l = Node::NullPtr;
161 Node * r = Node::NullPtr;
163 EXPECT_EQ(root, Node::NullPtr);
164
167 EXPECT_EQ(inorder_keys(l), (std::vector<int>{1, 2, 2}));
168 EXPECT_EQ(inorder_keys(r), (std::vector<int>{3, 4}));
169}
170
172{
173 NodePool pool;
174 Node * root = Node::NullPtr;
175 for (const int k : {2, 1, 3})
176 ASSERT_NE(insert_by_key_xt(root, pool.make(k)), Node::NullPtr);
177
178 auto * p = pool.make(4);
179 ASSERT_NE(insert_root_xt(root, p), Node::NullPtr);
180 EXPECT_EQ(root, p);
182 EXPECT_EQ(inorder_keys(root), (std::vector<int>{1, 2, 3, 4}));
183
184 auto * dup = pool.make(2);
185 EXPECT_EQ(insert_root_xt(root, dup), Node::NullPtr);
187 EXPECT_EQ(inorder_keys(root), (std::vector<int>{1, 2, 3, 4}));
188}
189
191{
192 NodePool pool;
193 Node * root = Node::NullPtr;
194 for (const int k : {1, 2, 3})
195 ASSERT_NE(insert_by_key_xt(root, pool.make(k)), Node::NullPtr);
196
197 auto * p = pool.make(2);
198 ASSERT_NE(insert_dup_root_xt(root, p), Node::NullPtr);
199 EXPECT_EQ(root, p);
201 EXPECT_EQ(inorder_keys(root), (std::vector<int>{1, 2, 2, 3}));
202}
203
205{
206 NodePool pool;
207 Node * root = Node::NullPtr;
208 for (const int k : {1, 2, 3, 4, 5})
209 ASSERT_NE(insert_by_key_xt(root, pool.make(k)), Node::NullPtr);
210
211 auto * p0 = pool.make(99);
214 EXPECT_EQ(inorder_keys(root), (std::vector<int>{99, 1, 2, 3, 4, 5}));
215 EXPECT_EQ(KEY(select(root, 0)), 99);
216 EXPECT_EQ(KEY(select(root, 1)), 1);
217
218 auto expected = std::vector<int>{99, 1, 2, 3, 4, 5};
219 auto * p3 = pool.make(77);
220 insert_by_pos_xt(root, p3, 3);
221 expected.insert(expected.begin() + 3, 77);
224
225 // out_of_range when pos > COUNT(root)
226 auto * bad = pool.make(123);
227 EXPECT_THROW(insert_by_pos_xt(root, bad, COUNT(root) + 1), std::out_of_range);
229}
230
232{
233 NodePool pool;
234 Node * root = Node::NullPtr;
235 for (const int k : {1, 2, 3})
236 ASSERT_NE(insert_by_key_xt(root, pool.make(k)), Node::NullPtr);
237
238 auto * p = pool.make(0);
240 if (ret == p)
241 root = p;
242
243 EXPECT_EQ(root, p);
245 EXPECT_EQ(inorder_keys(root), (std::vector<int>{0, 1, 2, 3}));
246
247 auto * q = pool.make(2);
249 EXPECT_NE(ret2, q);
250 EXPECT_EQ(KEY(ret2), 2);
251 // root should remain as-is (only update when ret == inserted node)
252 EXPECT_EQ(root, p);
254}
255
257{
258 NodePool pool;
259 Node * root = Node::NullPtr;
260 Greater cmp;
261
262 for (const int k : {1, 2, 3, 4, 5})
263 ASSERT_NE((insert_by_key_xt<Node, Greater>(root, pool.make(k), cmp)), Node::NullPtr);
264
267 EXPECT_EQ(inorder_keys(root), (std::vector<int>{5, 4, 3, 2, 1}));
268
269 Node * p = Node::NullPtr;
270 const auto pos = find_position<Node, Greater>(root, 3, p, cmp);
271 EXPECT_EQ(pos, 2);
272 EXPECT_EQ(KEY(p), 3);
273
275 ASSERT_NE(removed, Node::NullPtr);
276 pool.forget(removed);
277 delete removed;
280 EXPECT_EQ(inorder_keys(root), (std::vector<int>{5, 3, 2, 1}));
281}
282
284{
285 NodePool pool;
286 Node * root = Node::NullPtr;
287 for (int k : {1, 2, 3})
288 ASSERT_NE(insert_by_key_xt(root, pool.make(k)), Node::NullPtr);
289
290 EXPECT_THROW(select(root, COUNT(root)), std::out_of_range);
291 EXPECT_THROW(select_rec(root, COUNT(root)), std::out_of_range);
292 EXPECT_THROW(remove_by_pos_xt(root, COUNT(root)), std::out_of_range);
293
294 Node * ts = Node::NullPtr;
295 Node * tg = Node::NullPtr;
296 EXPECT_THROW(split_pos_rec(root, COUNT(root) + 1, ts, tg), std::out_of_range);
297}
298
300{
301 EXPECT_EQ(COUNT(Node::NullPtr), 0u);
302}
303
305{
306 NodePool pool;
307 Node * root = Node::NullPtr;
308
309 for (const int k : {5, 3, 7, 2, 4, 6, 8})
310 ASSERT_NE(insert_by_key_xt(root, pool.make(k)), Node::NullPtr);
311
313 EXPECT_EQ(inorder_keys(root), (std::vector<int>{2, 3, 4, 5, 6, 7, 8}));
314 EXPECT_EQ(COUNT(root), 7u);
315}
316
318{
319 NodePool pool;
320 Node * root = Node::NullPtr;
321
322 ASSERT_NE(insert_by_key_xt(root, pool.make(2)), Node::NullPtr);
323 ASSERT_NE(insert_by_key_xt(root, pool.make(1)), Node::NullPtr);
324 ASSERT_NE(insert_by_key_xt(root, pool.make(3)), Node::NullPtr);
325
326 auto * dup = pool.make(2);
327 EXPECT_EQ(insert_by_key_xt(root, dup), Node::NullPtr);
328
330}
331
333{
334 NodePool pool;
335 Node * root = Node::NullPtr;
336
337 ASSERT_NE(insert_dup_by_key_xt(root, pool.make(2)), Node::NullPtr);
338 ASSERT_NE(insert_dup_by_key_xt(root, pool.make(2)), Node::NullPtr);
339 ASSERT_NE(insert_dup_by_key_xt(root, pool.make(2)), Node::NullPtr);
340
342 EXPECT_EQ(COUNT(root), 3u);
343}
344
346{
347 NodePool pool;
348 Node * root = Node::NullPtr;
349
350 auto * p = pool.make(10);
353 EXPECT_EQ(COUNT(root), 1u);
354
355 auto * q = pool.make(10);
357 EXPECT_NE(got, q);
358 EXPECT_EQ(KEY(got), 10);
360 EXPECT_EQ(COUNT(root), 1u);
361}
362
364{
365 NodePool pool;
366 Node * root = Node::NullPtr;
367 for (const int k : {5, 3, 7, 2, 4, 6, 8})
368 ASSERT_NE(insert_by_key_xt(root, pool.make(k)), Node::NullPtr);
369
370 for (size_t i = 0; i < COUNT(root); ++i)
371 {
372 auto * a = select_rec(root, i);
373 auto * b = select_ne(root, i);
374 auto * c = select(root, i);
375 EXPECT_EQ(a, b);
376 EXPECT_EQ(a, c);
377 }
378
379 Node * parent = Node::NullPtr;
380 auto * mid = select(root, 3, parent);
381 ASSERT_NE(mid, Node::NullPtr);
382 EXPECT_EQ(KEY(mid), 5);
383 EXPECT_NE(parent, mid);
384}
385
387{
388 NodePool pool;
389 Node * root = Node::NullPtr;
390 for (const int k : {5, 3, 7, 2, 4, 6, 8})
391 ASSERT_NE(insert_by_key_xt(root, pool.make(k)), Node::NullPtr);
392
393 for (size_t i = 0; i < COUNT(root); ++i)
394 {
395 auto * p = select(root, i);
396 Node * out = Node::NullPtr;
397 EXPECT_EQ(inorder_position(root, KEY(p), out), static_cast<long>(i));
398 EXPECT_EQ(out, p);
399 }
400
402}
403
405{
406 NodePool pool;
407 Node * root = Node::NullPtr;
408 for (const int k : {2, 4, 6, 8})
409 ASSERT_NE(insert_by_key_xt(root, pool.make(k)), Node::NullPtr);
410
411 Node * p = Node::NullPtr;
412
413 // key smaller than min
414 EXPECT_EQ(find_position(root, 1, p), -1);
415 EXPECT_EQ(KEY(p), 2);
416
417 // exact key
418 EXPECT_EQ(find_position(root, 6, p), 2);
419 EXPECT_EQ(KEY(p), 6);
420
421 // between keys
422 EXPECT_EQ(find_position(root, 5, p), 1);
423 EXPECT_EQ(KEY(p), 6);
424
425 // bigger than max
426 EXPECT_EQ(find_position(root, 9, p), 3);
427 EXPECT_EQ(p, Node::NullPtr);
428}
429
431{
432 NodePool pool;
433 Node * root = Node::NullPtr;
434 for (const int k : {1, 2, 3, 4, 5, 6, 7})
435 ASSERT_NE(insert_by_key_xt(root, pool.make(k)), Node::NullPtr);
436
437 Node * l = Node::NullPtr;
438 Node * r = Node::NullPtr;
439 split_pos_rec(root, 3, l, r);
440 EXPECT_EQ(root, Node::NullPtr);
441
444 EXPECT_EQ(inorder_keys(l), (std::vector<int>{1, 2, 3}));
445 EXPECT_EQ(inorder_keys(r), (std::vector<int>{4, 5, 6, 7}));
446
448 EXPECT_EQ(l, Node::NullPtr);
449 EXPECT_EQ(r, Node::NullPtr);
450
452 EXPECT_EQ(inorder_keys(joined), (std::vector<int>{1, 2, 3, 4, 5, 6, 7}));
453}
454
456{
457 NodePool pool;
458 Node * root = Node::NullPtr;
459 for (const int k : {1, 2, 3, 4, 5, 6, 7})
460 ASSERT_NE(insert_by_key_xt(root, pool.make(k)), Node::NullPtr);
461
462 auto * removed = remove_by_pos_xt(root, 3);
463 ASSERT_NE(removed, Node::NullPtr);
464 EXPECT_EQ(KEY(removed), 4);
465 EXPECT_EQ(COUNT(removed), 1u);
467
468 pool.forget(removed);
469 delete removed;
470
471 auto * removed2 = remove_by_key_xt(root, 6);
472 ASSERT_NE(removed2, Node::NullPtr);
474 pool.forget(removed2);
475 delete removed2;
476
478 EXPECT_EQ(inorder_keys(root), (std::vector<int>{1, 2, 3, 5, 7}));
479}
480
482{
483 NodePool pool;
484
485 auto * p = pool.make(2);
486 LLINK(p) = pool.make(1);
487 RLINK(p) = pool.make(3);
488 COUNT(LLINK(p)) = 1;
489 COUNT(RLINK(p)) = 1;
490 COUNT(p) = 3;
491
492 const auto before = inorder_keys(p);
493 auto * q = rotate_to_right_xt(p);
496
497 auto * r = rotate_to_left_xt(q);
500}
501
503{
504 NodePool pool;
505 Node * root = Node::NullPtr;
506
507 std::mt19937 rng(12345);
508 std::uniform_int_distribution<int> dist(0, 400);
509
510 std::set<int> oracle;
511
512 for (int i = 0; i < 300; ++i)
513 {
514 int k = dist(rng);
515 auto * p = pool.make(k);
516 auto * ins = insert_by_key_xt(root, p);
517 if (ins == Node::NullPtr)
518 {
519 // duplicate
520 pool.forget(p);
521 delete p;
522 }
523 else
524 oracle.insert(k);
525
527 EXPECT_EQ(inorder_keys(root), std::vector<int>(oracle.begin(), oracle.end()));
528 }
529
530 for (int i = 0; i < 200; ++i)
531 {
532 int k = dist(rng);
533 if (auto * removed = remove_by_key_xt(root, k); removed != Node::NullPtr)
534 {
535 oracle.erase(k);
536 pool.forget(removed);
537 delete removed;
538 }
540 EXPECT_EQ(inorder_keys(root), std::vector<int>(oracle.begin(), oracle.end()));
541 }
542}
WeightedDigraph::Node Node
@ KEY
Definition btreepic.C:169
Node for extended binary search tree.
T & insert(const T &item)
Insert a new item by copy.
Definition htlist.H:1502
void forget(Node *p)
Definition rand-tree.cc:93
Node * make(int key)
Definition rand-tree.cc:86
iterator end() noexcept
Return an STL-compatible end iterator.
iterator begin() noexcept
Return an STL-compatible iterator to the first element.
#define TEST(name)
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
int cmp(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4118
void delete_tree(Tree_Node< T > *node)
long inorder_position(Node *r, const typename Node::key_type &key, Node *&p, Compare &cmp) noexcept
Compute the inorder position of a key.
Node * insert_dup_by_key_xt(Node *&r, Node *p, Compare &cmp) noexcept
Insert a node in an extended binary search tree without testing for duplicity.
Node * insert_dup_root_xt(Node *&root, Node *p, Compare &cmp) noexcept
Insert a node as root of an extended binary search tree.
Node * insert_by_key_xt(Node *&r, Node *p, Compare &cmp) noexcept
Insert a node in an extended binary search tree.
bool check_rank_tree(Node *root) noexcept
Return true if root is a valid extended binary tree.
void split_pos_rec(Node *&r, const size_t i, Node *&ts, Node *&tg)
Split a extended binary tree according to a position.
constexpr Node *& RLINK(Node *p) noexcept
Return the right tree of p.
auto & COUNT(Node *p) noexcept
Return the number of nodes of the tree fron p is root.
Node * remove_by_pos_xt(Node *&root, size_t pos)
Remove from a extended binary tree the node whose inorder position is pos.
Node * remove_by_key_xt(Node *&root, const typename Node::key_type &key, Compare &cmp) noexcept
Remove a key of extended binary tree.
Node * insert_root_xt(Node *&root, Node *p, Compare &cmp) noexcept
Insert a node p as root of an extended binary search tree.
Node * rotate_to_left_xt(Node *p) noexcept
Rotate to left the extended binary tree with root p.
bool split_key_rec_xt(Node *&root, const typename Node::key_type &key, Node *&l, Node *&r, Compare &cmp) noexcept
Split an extended binary search tree according to a key.
Node * select(Node *r, const size_t pos)
Iterative selection of a node according to inorder position.
Node * select_ne(Node *r, const size_t pos) noexcept
Iterative selection of a node according to inorder position without exception.
constexpr Node *& LLINK(Node *p) noexcept
Return a pointer to left subtree.
Node * rotate_to_right_xt(Node *p) noexcept
Rotate to right the extended bianry tree with root p
void split_key_dup_rec_xt(Node *&root, const typename Node::key_type &key, Node *&l, Node *&r, Compare &cmp) noexcept
Split an extended binary search tree according to a key which can be in the tree.
void insert_by_pos_xt(Node *&r, Node *p, size_t pos)
Insert a node in a specific inorder position in a binary tree.
Node * select_rec(Node *r, const size_t i)
Recursively select the i-th node inorder sense.
Node * join_exclusive_xt(Node *&ts, Node *&tg) noexcept
Exclusive union of two extended binary search trees.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
size_t size(Node *root) noexcept
long find_position(Node *r, const typename Node::key_type &key, Node *&p, Compare &cmp) noexcept
Find the inorder position of a key in an extended binary search tree.
Node * search_or_insert_by_key_xt(Node *&r, Node *p, Compare &cmp) noexcept
Search or insert a node in an extended binary search tree.
DynList< T > maps(const C &c, Op op)
Classic map operation.
std::vector< int > inorder_keys(NodeT *root)
Definition rand-tree.cc:59
Utility functions for binary tree operations.
Extended binary node with subtree count.
DynList< int > l