Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_spanning_tree.H
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
52# ifndef TPL_SPANNING_TREE_H
53# define TPL_SPANNING_TREE_H
54
55# include <tpl_graph.H>
56# include <tpl_graph_utils.H>
57# include <ah-errors.H>
58
59namespace Aleph {
60
110template <class GT, class SA = Dft_Show_Arc<GT>>
112{
114 GT * gptr = nullptr;
115 GT * tptr = nullptr;
116
117 // Recursive DFS helper to build the spanning tree
118 bool build_tree(typename GT::Node * gnode, typename GT::Arc * garc,
119 typename GT::Node * tnode)
120 {
121 // Mark node and arc as part of spanning tree
122 NODE_BITS(gnode).set_bit(Spanning_Tree, true);
123 ARC_BITS(garc).set_bit(Spanning_Tree, true);
124
125 // Create corresponding node in tree and establish mapping
126 auto tree_tgt_node = tptr->insert_node(gnode->get_info());
128
129 // Create corresponding arc in tree and establish mapping
130 auto tarc = tptr->insert_arc(tnode, tree_tgt_node, garc->get_info());
132
134
135 // Check if spanning tree is complete (all nodes covered)
137 return true;
138
139 // Invariant: tree must be acyclic (nodes > arcs)
141
142 // Explore adjacent nodes via DFS
144 i.has_curr() and tptr->get_num_nodes() < gptr->get_num_nodes();
145 i.next_ne())
146 {
147 auto arc = i.get_current_arc_ne();
148 if (IS_ARC_VISITED(arc, Spanning_Tree))
149 continue;
150
151 auto arc_tgt_node = i.get_tgt_node();
153 continue; // Target already visited via another arc
154
155 if (build_tree(arc_tgt_node, arc, tnode))
156 return true;
157 }
158
159 return false;
160 }
161
162 // Main algorithm entry point
163 bool build_tree(GT & g, typename GT::Node * gnode, GT & tree)
164 {
165 gptr = &g;
166 tptr = &tree;
167
168 // Reset all control bits for fresh traversal
169 gptr->reset_nodes();
170 gptr->reset_arcs();
171
172 // Ensure output tree is empty
174
175 // Mark starting node as visited
176 NODE_BITS(gnode).set_bit(Spanning_Tree, true);
177
178 // Create root node in tree and establish mapping
179 auto tnode = tree.insert_node(gnode->get_info());
181
182 // Explore all adjacent arcs via DFS
184 i.has_curr() and tptr->get_num_nodes() < gptr->get_num_nodes();
185 i.next_ne())
186 {
187 auto arc = i.get_current_arc_ne();
188 if (IS_ARC_VISITED(arc, Spanning_Tree))
189 continue;
190
191 auto arc_tgt_node = i.get_tgt_node();
193 continue; // Target already visited via another arc
194
195 if (build_tree(arc_tgt_node, arc, tnode))
196 return true;
197 }
198
199 return true;
200 }
201
202public:
203
209 Find_Depth_First_Spanning_Tree(SA arc_filter = SA()) : sa(arc_filter) { /* empty */ }
210
229 typename GT::Node * operator () (GT & g, GT & tree)
230 {
232 << "Find_Depth_First_Spanning_Tree: graph is empty";
233
234 auto start = g.get_first_node();
235 if (not build_tree(g, start, tree))
236 return nullptr;
237
238 return start;
239 }
240
258 typename GT::Node * operator () (GT & g, typename GT::Node * gnode, GT & tree)
259 {
260 ah_invalid_argument_if(gnode == nullptr)
261 << "Find_Depth_First_Spanning_Tree: source node cannot be null";
262
263 this->build_tree(g, gnode, tree);
264 return static_cast<typename GT::Node *>(NODE_COOKIE(gnode));
265 }
266};
267
268
313template <class GT, class SA = Dft_Show_Arc<GT>>
315{
317
318 // Main BFS algorithm to build spanning tree
319 void build_tree(GT & g, typename GT::Node * gp, GT & tree)
320 {
321 // Reset control bits for fresh traversal
324
325 // Ensure output tree is empty
326 clear_graph(tree);
327
328 // Create root node in tree and establish mapping
329 auto tp = tree.insert_node(gp->get_info());
330 GT::map_nodes(gp, tp);
331
332 // Initialize queue with arcs adjacent to starting node
334 for (Node_Arc_Iterator<GT, SA> i(gp, sa); i.has_curr(); i.next_ne())
335 q.put(i.get_current_arc_ne());
336
337 // Mark starting node as visited
338 NODE_BITS(gp).set_bit(Spanning_Tree, true);
339
340 // BFS loop
341 while (not q.is_empty())
342 {
343 auto garc = q.get();
344 ARC_BITS(garc).set_bit(Spanning_Tree, true);
345 auto gsrc = g.get_src_node(garc);
346 auto gtgt = g.get_tgt_node(garc);
347
348 // Skip if both endpoints already visited
351 continue;
352
353 // Ensure gsrc is the visited node and gtgt is the new one
355 std::swap(gsrc, gtgt);
356
357 auto tsrc = mapped_node<GT>(gsrc);
358 NODE_BITS(gtgt).set_bit(Spanning_Tree, true);
359
360 // Create new node in tree and establish mapping
361 auto ttgt = tree.insert_node(gtgt->get_info());
363
364 // Create new arc in tree and establish mapping
365 auto tarc = tree.insert_arc(tsrc, ttgt, garc->get_info());
367
368 // Check if spanning tree is complete
369 if (tree.get_num_nodes() == g.get_num_nodes())
370 break;
371
372 // Enqueue arcs adjacent to newly added node
373 for (Node_Arc_Iterator<GT, SA> i(gtgt, sa); i.has_curr(); i.next_ne())
374 {
375 auto current_arc = i.get_current_arc_ne();
376 if (IS_ARC_VISITED(current_arc, Spanning_Tree))
377 continue;
378
379 // Skip arcs where both endpoints are already visited
380 if (IS_NODE_VISITED(g.get_src_node(current_arc), Spanning_Tree) and
382 continue;
383 q.put(current_arc);
384 }
385 }
386 }
387
388public:
389
395 Find_Breadth_First_Spanning_Tree(SA arc_filter = SA()) : sa(arc_filter) { /* empty */ }
396
414 void operator () (GT & g, typename GT::Node * gnode, GT & tree)
415 {
416 ah_invalid_argument_if(gnode == nullptr)
417 << "Find_Breadth_First_Spanning_Tree: source node cannot be null";
418
419 this->build_tree(g, gnode, tree);
420 }
421
434 typename GT::Node * operator () (GT & g, GT & tree)
435 {
437 << "Find_Breadth_First_Spanning_Tree: graph is empty";
438
439 auto start = g.get_first_node();
440 this->build_tree(g, start, tree);
441 return static_cast<typename GT::Node *>(NODE_COOKIE(start));
442 }
443};
444
464template <class GT>
466{
467public:
468
482
494 {
495 ah_invalid_argument_if(arcs == nullptr)
496 << "Build_Spanning_Tree: arcs array cannot be null";
498 }
499};
500
501} // end namespace Aleph
502
503# endif // TPL_SPANNING_TREE_H
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
#define ah_invalid_argument_if(C)
Throws std::invalid_argument if condition holds.
Definition ah-errors.H:639
EepicNode< long > * build_tree()
Definition btreepic.C:1435
Build a spanning tree from an array of arcs.
GT operator()(const DynArray< typename GT::Arc * > &arcs) const
Construct spanning tree from array of arc pointers.
Dynamic queue of elements of generic type T based on single linked list.
T & put(const T &data)
The type of element.
T get()
Remove the oldest item of the queue.
bool is_empty() const noexcept
Return true if this is empty.
void next_ne() noexcept
Advances the iterator to the next filtered element (noexcept version).
Compute a breadth-first spanning tree of a graph.
void build_tree(GT &g, typename GT::Node *gp, GT &tree)
void operator()(GT &g, typename GT::Node *gnode, GT &tree)
Build a breadth-first spanning tree starting from a specific node.
Find_Breadth_First_Spanning_Tree(SA arc_filter=SA())
Construct a BFS spanning tree builder with optional arc filter.
Compute a depth-first spanning tree of a graph.
GT::Node * operator()(GT &g, GT &tree)
Build a depth-first spanning tree starting from the first node.
Find_Depth_First_Spanning_Tree(SA arc_filter=SA())
Construct a DFS spanning tree builder with optional arc filter.
bool build_tree(typename GT::Node *gnode, typename GT::Arc *garc, typename GT::Node *tnode)
bool build_tree(GT &g, typename GT::Node *gnode, GT &tree)
Node * get_first_node() const
Return any node in the graph.
Definition tpl_graph.H:576
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Definition tpl_graph.H:524
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
Definition tpl_graph.H:604
void reset_bit_nodes(int bit) const noexcept
Reset bit to zero for all the nodes of graph.
Definition graph-dry.H:1040
void reset_arcs() const
Reset all the arcs of graph (the control bits, the state, the counter and the cookie)
Definition graph-dry.H:927
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Definition graph-dry.H:731
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:695
static void map_arcs(A1 *p, A2 *q) noexcept
Map the arcs through their cookies.
Definition graph-dry.H:1026
void reset_bit_arcs(int bit) const noexcept
Reset bit to zero for all the arcs of graph.
Definition graph-dry.H:1046
constexpr size_t get_num_arcs() const noexcept
Definition graph-dry.H:778
void reset_nodes() const
Reset all the nodes of graph (the control bits, the state, the counter and the cookie)
Definition graph-dry.H:920
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:737
static void map_nodes(N1 *p, N2 *q) noexcept
Map the nodes through their cookies.
Definition graph-dry.H:995
DynArray< Graph::Arc * > arcs
Definition graphpic.C:408
#define IS_NODE_VISITED(p, bit)
Determine whether the control bit is set or not to one.
#define ARC_BITS(p)
Return the control bits of arc p.
#define NODE_COOKIE(p)
Return the node cookie
void clear_graph(GT &g) noexcept
Clean a graph: all its nodes and arcs are removed and freed.
Definition tpl_graph.H:3549
#define IS_ARC_VISITED(p, bit)
Determine whether the bit field is or not set to one.
#define NODE_BITS(p)
Get the control bits of a node.
@ Spanning_Tree
Definition aleph-graph.H:79
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
DynList< T > maps(const C &c, Op op)
Classic map operation.
Arc of graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:222
Filtered iterator of adjacent arcs of a node.
Definition tpl_graph.H:1119
Generic graph and digraph implementations.
Utility algorithms and operations for graphs.