Elementa v8.0.0
Minimalistic library for any C++ application (C++11 and up)
Loading...
Searching...
No Matches
trees.h
Go to the documentation of this file.
1
3#include "elementa/license.inc"
4#include "elementa/checks.inc"
5
6#ifndef ELEMENTA_ADTS_TREES_H
7#define ELEMENTA_ADTS_TREES_H
8
9#include <memory>
10#include <algorithm>
15
17
18
19namespace elementa
20{
21
22namespace adts
23{
24
46/* ***************************************************************************
47
48 Abstract template class: Tree
49
50*******************************************************************************/
51
53
63template <class Vertex, class Edge>
64class Tree
65{
66 public:
67
73
75 using Ptr = std::shared_ptr<Tree>;
76
78 using Forest = std::vector<Ptr>;
79
87
96 Tree(const BGraph & exemplar):
97 pgraph_{reinterpret_cast<BGraph *>(exemplar.emptyClone())} {}
98
100 Tree(const Tree & oth):pgraph_{nullptr}
101 { copyFrom(oth); }
102
104 Tree(Tree && oth): pgraph_{nullptr}
105 { moveFrom(std::move(oth)); }
106
108 Tree & operator=(const Tree & oth)
109 { if (this != & oth) copyFrom(oth); return(*this); }
110
113 { if (this != & oth) moveFrom(std::move(oth)); return(*this); }
114
116 virtual ~Tree(void)
117 { delete pgraph_; }
118
126 bool empty(void) const
128 ELE_CODE_TRACE({},"PGraph_=" << elementa::base::to_number(pgraph_));
129 return(pgraph_->empty()); }
130
132 BGraph & graph(void) const { return(*pgraph_); }
133
135 typename BGraph::viterator root(void) const;
136
138
139 graphs::size_edge depth(const typename BGraph::viterator & n)const;
140
148 void clear(void) { pgraph_->clear(); }
149
151
152 typename BGraph::viterator setRoot(const Vertex & v);
153
155
157 const typename BGraph::viterator & parent,
158 const Vertex & v, const Edge & e);
159
161 void eraseNode(const typename BGraph::viterator & node);
162
164
166 void splice(Tree & oth, const Edge & edgeval);
167
171 private:
172
173 BGraph * pgraph_;
174
175 void copyFrom(const Tree & oth)
176 { if (pgraph_ != nullptr) delete pgraph_;
177 pgraph_ = reinterpret_cast<BGraph *>(oth.pgraph_->clone()); }
178
179 void moveFrom(Tree && oth)
180 { if (pgraph_ != nullptr) delete pgraph_;
181 pgraph_ = oth.pgraph_;
182 oth.pgraph_ = reinterpret_cast<BGraph *>(pgraph_->emptyClone()); }
183};
184
185
186/* ***************************************************************************
187
188 Template class: Szer_TreeText
189
190*******************************************************************************/
191
193
194template <class Vertex, class Edge>
195class Szer_TreeText: public elementa::base::Serializer< Tree<Vertex,Edge> >
196{
197 public:
198
200
202
207 { szerv_ = &szerv; szere_ = &szere; }
208
210 void ser(elementa::base::OutSerCh & chout, const TreeType & tree);
211
212 // No deserialization.
213
214 private:
215
218
219static_assert(
220 (sizeof(graphs::size_vertex)<=8) &&
221 (sizeof(graphs::size_edge)<=8),
222 "Serialization requires 64 bits or less for size_vertex and size_edge");
223};
224
225
226
227/* ===========================================================================
228
229 ========== IMPLEMENTATION OF TEMPLATES ==========
230
231============================================================================= */
232
233
234/* ***************************************************************************
235
236 Template class: Tree
237
238*******************************************************************************/
239
240template <class Vertex, class Edge>
243{
244 if (pgraph_->size_vertices()==0) return(pgraph_->vrangeAll().end());
245 return(pgraph_->vrangeAll().begin());
246}
247
248template <class Vertex, class Edge>
250 const typename Tree<Vertex,Edge>::BGraph::viterator & n) const
251{
252 graphs::size_edge res{0};
255 do
256 {
257 eparent = pgraph_->erangeEntering(node).begin();
258 if (!eparent.isEnd())
259 {
260 ++res;
261 node = pgraph_->origin(eparent);
262 }
263 } while (!eparent.isEnd());
264 return(res);
265}
266
267template <class Vertex, class Edge>
271
272 if (pgraph_->size_vertices() == 0)
273 {
274 ELE_CODE_TRACE({},"Creating root node in empty tree.");
275 return(pgraph_->insert(v));
276 }
277 ELE_CODE_TRACE({},"Changing existing root node content.");
278 typename BGraph::viterator it = pgraph_->vrangeAll().begin();
279 *it = v;
280 return(it);
281}
282
283template <class Vertex, class Edge>
286 const typename Tree<Vertex,Edge>::BGraph::viterator & parent,
287 const Vertex & v, const Edge & e)
289
290 ELE_CODE_TRACE({},"Adding new child to parent " << parent.to_string());
291 if ( (!parent.valid()) || (parent.isEnd()) )
292 ELE_CODE_INVARG("Cannot add a child to an invalid parent");
293 ELE_CODE_TRACE({},"Inserting new vertex in the tree (to parent " <<
294 parent.to_string() << ")" << std::endl);
295 auto it = pgraph_->insert(v);
296 ELE_CODE_TRACE({},std::endl << "New vertex inserted in the tree. Parent: "<<
297 parent.to_string() << ". Child: " << it.to_string());
298 ELE_CODE_TRACE({},"Inserting new edge to connect vertex in the tree");
299 pgraph_->connect(parent,it,e);
300 ELE_CODE_TRACE({},"Child added.");
301 return(it);
302}
303
304template <class Vertex, class Edge>
306 const typename Tree<Vertex,Edge>::BGraph::viterator & node)
308
309 typename BGraph::VectorOfVIts vinds;
310 auto eit = pgraph_->erangeDepthFirst(node).begin();
311 typename BGraph::viterator v0,v1;
312 while (!eit.isEnd())
313 {
314 ELE_CODE_TRACE({},"eraseNode adding a connection");
315 pgraph_->connection(eit,v0,v1);
316 if (std::find(vinds.begin(),vinds.end(),v0) == vinds.end())
317 vinds.push_back(v0);
318 if (std::find(vinds.begin(),vinds.end(),v1) == vinds.end())
319 vinds.push_back(v1);
320 ++eit;
321 }
322 ELE_CODE_TRACE({},"erasing all collected connections");
323 pgraph_->erase(vinds);
324}
325
326template <class Vertex, class Edge>
327void Tree<Vertex,Edge>::splice(Tree & oth, const Edge & edge)
329
330 if (oth.empty()) return;
331
332 ELE_CODE_TRACE({},"Copying root iterators for merging");
333 typename Tree<Vertex,Edge>::BGraph::VectorOfVIts svits,svothits;
334 svothits.push_back(oth.root());
335 svits.push_back(root());
336 ELE_CODE_TRACE({},"My root: " << root().to_string() << ", inside svits: " <<
337 svits[0].to_string());
338 ELE_CODE_TRACE({},"Oth root: " << root().to_string() <<
339 ", inside svothits: "<< svothits[0].to_string());
340 ELE_CODE_TRACE({},"Doing the graph splice");
341 pgraph_->splice(*oth.pgraph_,&svothits,nullptr,&svits,nullptr);
342 ELE_CODE_TRACE({},"Doing the graph connect");
343 pgraph_->connect(svits[0],svothits[0],edge);
344 ELE_CODE_TRACE({},"Graph merge done, other tree clearing");
345 oth.clear();
346}
347
348
349/* ***************************************************************************
350
351 Template class: Szer_TreeText
352
353*******************************************************************************/
354
355template <class Vertex, class Edge>
357 const TreeType & tree)
359
360 ELE_CODE_TRACE({},"");
361
362 if (tree.empty()) return;
363
364 ELE_CODE_TRACE({},"Tree to serialize is not empty: " <<
365 tree.graph().size_vertices() << " vertices, " <<
366 tree.graph().size_edges() << " edges");
367
368 auto writenewline = [](elementa::base::OutSerCh & chout)
369 {
370 chout.put('\n');
372 };
373
374 auto writebranch = [](elementa::base::OutSerCh & chout,
375 graphs::size_edge start,
376 // how many tabs before leaving parent
377 unsigned length) // how many chars until child
378 {
379 if (start > 0)
380 {
381 for (unsigned char g = 0; g<2; ++g)
382 {
383 for (unsigned f = 0; f < start; ++f)
384 {
385 chout.put('\t');
387 }
388 chout.put('|');
390 if (g == 0)
391 {
392 chout.put('\n');
394 }
395 }
396 }
397 if (length > 0)
398 {
399 for (unsigned f = 0; f < length; ++f)
400 {
401 chout.put('_'); // must be shorter than '\t'
403 }
404 }
405 };
406
407 auto vit = tree.root();
408 ELE_CODE_TRACE({},"Serializing root: " << vit.to_string());
409 szerv_->ser(chout,*vit);
410 ELE_CODE_TRACE({},"Root serialized ok");
411 writenewline(chout);
412
413 ELE_CODE_TRACE({},"Serializing others from root: " << vit.to_string());
414 const auto & gr = const_cast<TreeType &>(tree).graph(); // const just wiped
415 // out temporarily
416 // to get graph()
417
418 auto eit = gr.erangeDepthFirst(vit).begin();
419 bool changelevel{true};
420 graphs::size_edge level{0};
421 while (!eit.isEnd())
422 {
423 // serializes destination node of eit with its previous branch
424 auto vchildit = gr.destination(eit);
425 if (changelevel) level = tree.depth(vchildit);
426 writebranch(chout,level,2);
427 chout.put('(');
429 szere_->ser(chout,*eit);
430 chout.put(')');
432 chout.put(' ');
434 szerv_->ser(chout,*vchildit);
435 writenewline(chout);
436
437 changelevel = ( (!gr.toLeaf(eit)) ||
438 (gr.toLastChild(eit,gr.origin(eit))) );
439
440 ++eit;
441 }
442}
443
444 // Trees
446
447
448} // end adts namespace
449
450} // end elementa namespace
451
452
453#endif
454
455
eiterator begin(void) const
Must return an iterator pointing to the first element.
Definition: graphs.h:471
eiterator begin(void) const
Must return an iterator pointing to the first element.
Definition: graphs.h:419
viterator end(void) const
Must return an iterator pointing past the last element.
Definition: graphs.h:299
viterator begin(void) const
Must return an iterator pointing to the first element.
Definition: graphs.h:298
A vector of vertex iterators (might be repeated).
Definition: graphs.h:131
virtual Clonable * emptyClone(void) const
Derived classes can override this to provide a clone that is "empty".
Definition: clonable.h:93
#define ELE_CODE_TRACE_OFF
Place this inside local scope (e.g., routine) to deactivate traces there.
Definition: debugging.h:283
#define ELE_CODE_PLACE
Produces a std::string with the place of source where the macro is placed.
Definition: debugging.h:194
#define ELE_CODE_INVARG(expl)
To throw an invalid-argument exception with an explanation.
Definition: exceptions.h:310
LongestUnsigned to_number(const void *p)
Convert a pointer address to a number.
ERange_Entering erangeEntering(const viterator &v) const
Return a range to iterate on edges entering a vertex, no special order.
Definition: graphs.h:742
virtual viterator insert(const Vertex &v)=0
Must insert one more vertex in the graph, unconnected to any other.
virtual eiterator connect(const viterator &itv0, const viterator &itv1, const Edge &e)=0
Must add a new edge in the graph connecting two existing vertices.
virtual void connection(const eiterator &it, viterator &vorg, viterator &vdest) const
Fill VORG and VDEST with VRange_All iterators to the edge vertices.
Definition: graphs.h:574
virtual void splice(Graph &oth, VectorOfVIts *svothits=nullptr, VectorOfEIts *seothits=nullptr, VectorOfVIts *svits=nullptr, VectorOfEIts *seits=nullptr)=0
Must add another graph to the one existing in this object.
virtual size_edge size_edges(void) const =0
Must return the number of edges.
ERange_DepthFirst erangeDepthFirst(const viterator &v) const
Return a range to iterate on edges in depth-first fashion.
Definition: graphs.h:746
virtual size_vertex size_vertices(void) const =0
Must return the number of vertices.
elementa::base::MultIterator< Vertex > viterator
Vertex iterator. ForwardLegacyIterator.
Definition: graphs.h:118
virtual void erase(const viterator &itv)=0
Must delete the given vertex and all edges connected to it.
VRange_All vrangeAll(void) const
Return a range to iterate on all Vertex data, no special order.
Definition: graphs.h:721
virtual viterator origin(const eiterator &it) const =0
Must return a VRange_All iterator to the origin vertex of an edge.
All graph classes derive from this one.
Definition: graphs.h:107
size_t size_vertex
For holding numbers of vertices of a graph.
Definition: graphs.h:68
size_t size_edge
For holding numbers of edges of a graph.
Definition: graphs.h:71
bool isEnd(void) const
Check for end. If it is invalid or points not to end, return false.
Definition: iterators.h:395
std::string to_string(void) const
Return a string with info about the iterator.
Definition: iterators.h:398
bool valid(void) const
Return true if the iterator is in valid state.
Definition: iterators.h:365
A mutable iterator that can have multiple iteration behaviors. Forward case.
Definition: iterators.h:299
std::ostream OutSerCh
"Base class" that represents any output serial channel in Elementa.
Definition: basics.h:247
void serch_isgood(RootSerCh &serchconst, const std::string &place="", const RTTextWithEnum::Combination &flags={RTTextWith::kAll_})
Throw an exception if the channel is not good; do nothing otherwise.
Base abstract class / interface for any serializer.
Definition: serializers.h:189
bool empty(void) const
Return TRUE if the tree is empty.
Definition: trees.h:126
graphs::Graph< Vertex, Edge > BGraph
Base Graph class of any particular graph implementation used in the tree.
Definition: trees.h:72
virtual ~Tree(void)
Virtual destructor.
Definition: trees.h:116
Tree(const BGraph &exemplar)
Constructor.
Definition: trees.h:96
Tree(const Tree &oth)
Copy constructor.
Definition: trees.h:100
Tree(Tree &&oth)
Move constructor.
Definition: trees.h:104
BGraph & graph(void) const
return a reference to the internal graph.
Definition: trees.h:132
std::shared_ptr< Tree > Ptr
Pointer to a tree.
Definition: trees.h:75
Tree & operator=(const Tree &oth)
Copy assignment.
Definition: trees.h:108
void clear(void)
Clear the tree.
Definition: trees.h:148
Tree & operator=(Tree &&oth)
Move assignment.
Definition: trees.h:112
std::vector< Ptr > Forest
A forest is a set of pointers to trees.
Definition: trees.h:78
Szer_TreeText(elementa::base::Serializer< Vertex > &szerv, elementa::base::Serializer< Edge > &szere)
Constructor: configure the serializer.
Definition: trees.h:205
Serializer of any tree as a text with a tree-like structure.
Definition: trees.h:196
This class is the base for any tree implementation.
Definition: trees.h:65
BGraph::viterator addChild(const typename BGraph::viterator &parent, const Vertex &v, const Edge &e)
Add a new child to a given node, as the last child of the node.
Definition: trees.h:285
BGraph::viterator setRoot(const Vertex &v)
If the tree has a root, changes its value by V; otherwise, add V as root.
Definition: trees.h:269
graphs::size_edge depth(const typename BGraph::viterator &n) const
Return the depth of the given node in the tree (0 for root).
Definition: trees.h:249
void eraseNode(const typename BGraph::viterator &node)
Erase a node and all its descendants.
Definition: trees.h:305
BGraph::viterator root(void) const
Return an iterator to the root of the tree or to end() if empty.
Definition: trees.h:242
void splice(Tree &oth, const Edge &edgeval)
Move OTH to this tree, connecting its root to this root, and clearing it.
Definition: trees.h:327
void ser(elementa::base::OutSerCh &chout, const TreeType &tree)
Serialize.
Definition: trees.h:356