Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tree-node.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
33
38# include <gtest/gtest.h>
39
40# include <tpl_tree_node.H>
41# include <ah-zip.H>
42# include <ah-string-utils.H>
43
44# include "tree-node-common.H"
45
46using namespace std;
47using namespace Aleph;
48
50{
52
59
60 ASSERT_EQ(p.get_right_child(), nullptr);
61 ASSERT_EQ(p.get_left_child(), nullptr);
62
63 ASSERT_EQ(p.get_child(0), nullptr);
64 ASSERT_EQ(p.get_parent(), nullptr);
65
66 ASSERT_EQ(p.get_left_tree(), nullptr);
67 ASSERT_EQ(p.get_right_tree(), nullptr);
68
69 ASSERT_TRUE(p.children().is_empty());
70
71 ASSERT_TRUE(p.traverse([] (auto) { return true; }));
72 ASSERT_FALSE(p.traverse([] (auto) { return false; }));
73
76 ASSERT_EQ(it.get_curr(), &p);
79 ASSERT_THROW(it.get_curr(), overflow_error);
80 ASSERT_THROW(it.next(), overflow_error);
81 it.reset_first();
83 ASSERT_EQ(it.get_curr(), &p);
86 ASSERT_THROW(it.get_curr(), overflow_error);
87 ASSERT_THROW(it.next(), overflow_error);
88
90 ASSERT_FALSE(cit.has_curr());
91 ASSERT_THROW(cit.get_curr(), overflow_error);
92 ASSERT_THROW(cit.next(), overflow_error);
93}
94
96{
97 Tree_Node<int> p1 = 1;
98 Tree_Node<int> p2 = 2;
99 Tree_Node<int> p3 = 3;
100 Tree_Node<int> p4 = 4;
101 Tree_Node<int> p5 = 5;
102
103 /* 1 insert_leftmost_child() test
104 |
105 2
106 */
107 p1.insert_leftmost_child(&p2);
108 ASSERT_TRUE(p1.is_root());
111 ASSERT_FALSE(p1.is_leaf());
112 ASSERT_FALSE(p2.is_root());
115
116 /* 1 insert_rightmost_child() test
117 /\
118 2 3
119 */
121 ASSERT_TRUE(p1.is_root());
124 ASSERT_FALSE(p1.is_leaf());
125 ASSERT_TRUE(p2.is_leaf());
126 ASSERT_FALSE(p2.is_root());
129 ASSERT_TRUE(p2.is_leaf());
130 ASSERT_FALSE(p3.is_root());
133
134 /* 0
135 / | \
136 2 3 5
137 */
139 ASSERT_TRUE(p1.is_root());
142 ASSERT_FALSE(p1.is_leaf());
143 ASSERT_FALSE(p2.is_root());
146 ASSERT_TRUE(p2.is_leaf());
147 ASSERT_FALSE(p3.is_root());
150 ASSERT_TRUE(p3.is_leaf());
151 ASSERT_FALSE(p5.is_leftmost());
152 ASSERT_TRUE(p5.is_rightmost());
153 ASSERT_FALSE(p5.is_root());
154 ASSERT_TRUE(p5.is_leaf());
155
156 /* 1
157 / / | |
158 2 3 4 5
159 */
160 p5.insert_left_sibling(&p4);
161 ASSERT_TRUE(p1.is_root());
164 ASSERT_FALSE(p1.is_leaf());
165 ASSERT_FALSE(p2.is_root());
168 ASSERT_TRUE(p2.is_leaf());
169
170 ASSERT_FALSE(p3.is_root());
173 ASSERT_TRUE(p3.is_leaf());
174
175 ASSERT_FALSE(p4.is_root());
178 ASSERT_TRUE(p4.is_leaf());
179
180 ASSERT_FALSE(p5.is_leftmost());
181 ASSERT_TRUE(p5.is_rightmost());
182 ASSERT_FALSE(p5.is_root());
183 ASSERT_TRUE(p5.is_leaf());
184
185 ASSERT_EQ(p1.get_left_child(), &p2);
187
188 ASSERT_EQ(p2.get_left_sibling(), nullptr);
189 ASSERT_EQ(p2.get_right_sibling(), &p3);
190
191 ASSERT_EQ(p3.get_left_sibling(), &p2);
192 ASSERT_EQ(p3.get_right_sibling(), &p4);
193
194 ASSERT_EQ(p4.get_left_sibling(), &p3);
196
197 ASSERT_EQ(p5.get_left_sibling(), &p4);
198 ASSERT_EQ(p5.get_right_sibling(), nullptr);
199
200 ASSERT_EQ(p1.get_child(0), &p2);
201 ASSERT_EQ(p1.get_child(1), &p3);
202 ASSERT_EQ(p1.get_child(2), &p4);
203 ASSERT_EQ(p1.get_child(3), &p5);
204
205 int k = 0;
206 ASSERT_TRUE(p1.traverse([&k] (auto p) { return p->get_key() == ++k; }));
207 ASSERT_EQ(k, 5);
208 k = 1;
209 ASSERT_TRUE(p1.children_nodes().traverse([&k] (auto p)
210 { return p->get_key() == ++k; }));
211 ASSERT_EQ(k, 5);
212 k = 1;
213 ASSERT_TRUE(p1.children().traverse([&k] (auto i) { return i == ++k; }));
214 ASSERT_EQ(k, 5);
215}
216
218{
219 {
220 Tree_Node<int>::Iterator it = nullptr;
222 ASSERT_THROW(it.get_curr(), overflow_error);
223 ASSERT_THROW(it.next(), overflow_error);
224 }
225
226 {
227 Tree_Node<int> p(0);
228 auto it = p.get_it();
229 ASSERT_TRUE(it.has_curr());
230 ASSERT_EQ(it.get_pos(), 0);
231 ASSERT_NO_THROW(it.next());
232 ASSERT_FALSE(it.has_curr());
233 ASSERT_EQ(it.get_pos(), 1);
234 ASSERT_THROW(it.get_curr(), overflow_error);
235 ASSERT_THROW(it.next(), overflow_error);
236 }
237
238 {
240 Tree_Node<int> p1(1);
241 p0.insert_leftmost_child(&p1);
242 auto it = p0.get_it();
243 ASSERT_TRUE(it.has_curr());
244 ASSERT_EQ(it.get_curr(), &p0);
245 ASSERT_NO_THROW(it.next());
246 ASSERT_TRUE(it.has_curr());
247 ASSERT_EQ(it.get_curr(), &p1);
248 ASSERT_NO_THROW(it.next());
249 ASSERT_FALSE(it.has_curr());
250 ASSERT_THROW(it.get_curr(), overflow_error);
251 ASSERT_THROW(it.next(), overflow_error);
252
253 ASSERT_NO_THROW(it.reset_first());
254 ASSERT_TRUE(it.has_curr());
255 ASSERT_EQ(it.get_curr(), &p0);
256 ASSERT_NO_THROW(it.next());
257 ASSERT_TRUE(it.has_curr());
258 ASSERT_EQ(it.get_curr(), &p1);
259 ASSERT_NO_THROW(it.next());
260 ASSERT_FALSE(it.has_curr());
261 ASSERT_THROW(it.get_curr(), overflow_error);
262 ASSERT_THROW(it.next(), overflow_error);
263 }
264}
265
267{
268 auto itl = l.get_it();
269 size_t k = 0;
270 for (auto it = root->get_it(); it.has_curr(); it.next(), itl.next(), ++k)
271 ASSERT_EQ(it.get_curr()->get_key(), itl.get_curr());
272 ASSERT_GT(k, 0);
273}
274
276{
277 {
278 Tree_Node<int> * root = nullptr;
279 ASSERT_EQ(clone_tree(root), nullptr);
280 }
281 {
283 auto rootp = clone_tree(&root);
284 ASSERT_NE(rootp, nullptr);
285 ASSERT_EQ(root.get_key(), rootp->get_key());
287 }
288}
289
291{
292 int i = 0;
293 ASSERT_TRUE(root->level_traverse([&i] (auto p)
294 {
295 return p->get_key() == i++;
296 }));
297 ASSERT_EQ(i, 31);
298}
299
301{
302 Tree_Node<int> * clone = clone_tree(root);
303 using It = Tree_Node<int>::Iterator;
304 using Pit = Pair_Iterator<It>;
305 for (Pit it{It(root), It(clone)}; it.has_curr(); it.next())
306 {
307 auto p = it.get_curr();
308 ASSERT_EQ(p.first->get_key(), p.second->get_key());
309 }
310 destroy_tree(clone);
311}
312
314{
315 {
316 Tree_Node<int> * root = nullptr;
317 ASSERT_EQ(root, nullptr);
318 }
319 {
321 size_t k = 0;
322 ASSERT_TRUE(root.traverse([&k] (auto p) { k++; return p->get_key() == 5; }));
323 ASSERT_EQ(k, 1);
324 }
325}
326
328{
330
331 auto * t1 = new Node("root");
332 t1->insert_rightmost_child(new Node("A"));
333 t1->insert_rightmost_child(new Node("B"));
334
335 auto * t2 = new Node("ROOT");
336 t2->insert_rightmost_child(new Node("a"));
337 t2->insert_rightmost_child(new Node("b"));
338
339 auto nocase = [] (const std::string & a, const std::string & b)
340 {
341 if (a.size() != b.size())
342 return false;
343 for (size_t i = 0; i < a.size(); ++i)
344 if (std::tolower(static_cast<unsigned char>(a[i])) !=
345 std::tolower(static_cast<unsigned char>(b[i])))
346 return false;
347 return true;
348 };
349
350 ASSERT_TRUE((are_tree_equal<Node, decltype(nocase)>(t1, t2, nocase)));
351
354}
355
357{
358 auto it = l.get_it();
359 size_t k = 0;
360 auto ret = root->traverse([&it, &k] (auto p)
361 {
362 bool r = p->get_key() == it.get_curr();
363 it.next(); ++k;
364 return r;
365 });
367 ASSERT_EQ(k, l.size());
368}
369
371{
372 int d[100];
373 size_t sz;
374 auto p = search_deway(root, 14, d, 100, sz);
375 ASSERT_EQ(p->get_key(), 14);
376 ASSERT_EQ(sz, 3);
377 ASSERT_EQ(d[0], 0);
378 ASSERT_EQ(d[1], 1);
379 ASSERT_EQ(d[2], 3);
380}
381
382/* 0
383
384 1 2 3 4 5
385
3866 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
387
388*/
389
391{
392 auto t1 = clone_tree(root1);
393 auto t2 = clone_tree(root2);
394 auto t3 = clone_tree(root3);
395
396 t1->insert_tree_to_right(t3);
397 t1->insert_tree_to_right(t2);
398
400 DynList<Tree_Node<int>*> flist = t1->trees();
401
402 zip_for_each([] (auto t) { ASSERT_EQ(get<0>(t), get<1>(t)); }, tlist, flist);
403
405}
406
408{
409 auto t = clone_tree(root1);
410 auto t2 = clone_tree(root2);
411
412 t->join(t2);
413
414 DynList<int> l = { 0, 1, 2, 3, 4, 5, 31, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
415 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
416 30, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43 };
417
419 t->level_traverse([&order] (auto p) { order.append(p->get_key()); return true; });
420
422
424}
425
426
String manipulation utilities.
Zip iterators and functional operations for multiple containers.
WeightedDigraph::Node Node
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
Iterator that zips two other iterators.
auto get_curr() const
Get current pair (bounds-checked).
Iterator over the children of this.
bool has_curr() const noexcept
Tree_Node * get_curr() const
Generic m-ary trees.
constexpr bool is_leftmost() const noexcept
Returns true if this is the leftmost node among its siblings.
bool traverse(Operation op)
Preorder traversal over all nodes executing op.
Dlink * get_sibling_list() noexcept
Tree_Node * get_left_sibling() const noexcept
Returns the left sibling of this.
constexpr bool is_root() const noexcept
Returns true if this is the root of the general tree.
Tree_Node * get_left_child() const noexcept
Returns the leftmost child of this.
constexpr bool is_rightmost() const noexcept
Returns true if this is the rightmost node among its siblings.
Tree_Node * get_child(const size_t i) const noexcept
Returns the i-th child of this.
void insert_leftmost_child(Tree_Node *p) noexcept
Inserts p as the leftmost child of this.
constexpr bool is_leaf() const noexcept
Returns true if this is a leaf node.
Dlink * get_child_list() noexcept
Tree_Node * get_right_sibling() const noexcept
Returns the right sibling of this.
Tree_Node * get_left_tree() const noexcept
Returns the tree to the left of this.
void insert_rightmost_child(Tree_Node *p) noexcept
Inserts p as the rightmost child of this.
Tree_Node * get_right_tree() const noexcept
Returns the tree to the right of this.
Tree_Node * get_parent() const noexcept
Returns the parent of this.
Container< Tree_Node * > children_nodes() const
Returns a list with the child nodes of this.
Tree_Node * get_right_child() const noexcept
Returns the rightmost child of this.
void insert_right_sibling(Tree_Node *p) noexcept
Inserts p as the right sibling of this.
Iterator get_it() const
Container< T > children() const
Returns a list with the contents of the children of this.
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Definition ah-dry.H:190
void deway(Tree_Node< int > *p, int prefix[], const int &len, const size_t &dim)
Recursively compute and print Deway numbering for a tree node.
Definition deway.C:117
#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
void destroy_tree(Node *root)
Destroys (frees memory) the tree whose root is root.
bool are_tree_equal(Node *t1, Node *t2, Eq &eq)
Returns true if t1 is equal to t2.
void destroy_forest(Node *root)
Destroys (frees memory) the forest whose first tree is root.
Node * search_deway(Node *root, const typename Node::key_type &key, int deway[], const size_t &size, size_t &n)
Searches key in a forest and computes the Dewey number of the node containing the key.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
void zip_for_each(Op &&op, const Cs &... cs)
Apply op to every zipped tuple.
Definition ah-zip.H:392
bool eq(const C1 &c1, const C2 &c2, Eq e=Eq())
Check equality of two containers using a predicate.
bool traverse(Node *root, Op op)
static void clone_tree(Node *src, Node *tgt)
std::ostream & join(const C &c, const std::string &sep, std::ostream &out)
Join elements of an Aleph-style container into a stream.
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
bool traverse(Operation &operation) noexcept(traverse_is_noexcept< Operation >())
Traverse the container via its iterator and performs a conditioned operation on each item.
Definition ah-dry.H:95
General tree (n-ary tree) node.
DynList< int > l
TEST_F(Simple_Tree, Iterators)
Definition tree-node.cc:266