Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
graph-traverse.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
43# ifndef GRAPH_TRAVERSE_H
44# define GRAPH_TRAVERSE_H
45
46# include <tuple>
47# include <cassert>
48# include <tpl_agraph.H>
49# include <tpl_dynListStack.H>
50# include <tpl_dynListQueue.H>
51
52namespace // local constants to avoid collisions with aleph-graph.H
53{
54 constexpr unsigned char GT_Unprocessed = 0;
55 constexpr unsigned char GT_Processing = 1;
56 constexpr unsigned char GT_Processed = 2;
57}
58
72template <class GT, class Itor,
73 template <typename T> class Q = DynListStack,
76{
77 GT & g;
79
80public:
83
91 template <class Node_Op>
92 size_t operator ()(typename GT::Node *start, Node_Op & op)
93 {
94 assert(start != nullptr);
95 g.reset_nodes();
96 g.reset_arcs();
97
98 size_t count = 1;
99 start->set_state(GT_Processed);
100 if (not op(start))
101 return count;
102
104 for (Itor it(start, sa); it.has_curr(); it.next_ne())
105 {
106 typename GT::Arc *a = it.get_curr();
107 typename GT::Node *tgt = g.get_connected_node(a, start);
110 q.put(a);
111 }
112
113 const size_t n = g.vsize();
114 while (not q.is_empty() and count < n)
115 {
116 typename GT::Arc *arc = q.get();
117 assert(arc->state() == GT_Processing);
119
120 typename GT::Node *s = g.get_src_node(arc);
121 typename GT::Node *t = g.get_tgt_node(arc);
122 if (s->state() == GT_Processed and t->state() == GT_Processed)
123 continue;
124
125 typename GT::Node *curr = s->state() == GT_Processed ? t : s;
126 assert(curr->state() == GT_Processing);
127 ++count;
128 curr->set_state(GT_Processed);
129 if (not op(curr))
130 return count;
131
132 for (Itor it(curr, sa); it.has_curr(); it.next_ne())
133 {
134 typename GT::Arc *a = it.get_curr();
135 if (a->state() != GT_Unprocessed)
136 continue;
137 typename GT::Node *tgt = g.get_connected_node(a, curr);
138 if (tgt->state() == GT_Unprocessed)
139 {
140 assert(a->state() != GT_Processing);
141 q.put(a);
144 }
145 else
147 }
148 }
149
150 return count;
151 }
152
154 template <class Node_Op>
155 size_t operator ()(typename GT::Node *start, Node_Op && op = Node_Op())
156 {
157 return (*this)(start, op);
158 }
159
169 template <class Op>
170 size_t exec(typename GT::Node *start, Op & op)
171 {
172 assert(start != nullptr);
173 g.reset_nodes();
174 g.reset_arcs();
175
176 size_t count = 1;
177 start->set_state(GT_Processed);
178 if (not op(start, nullptr))
179 return count;
180
181 using Pair = std::tuple<typename GT::Node *, typename GT::Arc *>;
182 Q<Pair> q;
183 for (Itor it(start, sa); it.has_curr(); it.next_ne())
184 {
185 typename GT::Arc *a = it.get_curr();
186 typename GT::Node *tgt = g.get_connected_node(a, start);
189 q.put(std::make_tuple(start, a));
190 }
191
192 const size_t n = g.vsize();
193 while (not q.is_empty() and count < n)
194 {
195 const Pair p = q.get();
196 typename GT::Arc *arc = get<1>(p);
197 assert(arc->state() == GT_Processing);
198 assert(get<0>(p)->state() == GT_Processed);
200
201 typename GT::Node *curr = g.get_connected_node(arc, get<0>(p));
202 assert(curr->state() == GT_Processing);
203 ++count;
204 curr->set_state(GT_Processed);
205 if (not op(curr, arc))
206 return count;
207
208 for (Itor it(curr, sa); it.has_curr(); it.next_ne())
209 {
210 typename GT::Arc *a = it.get_curr();
211 if (a->state() != GT_Unprocessed)
212 continue;
213 if (typename GT::Node *tgt = g.get_connected_node(a, curr); tgt->state() == GT_Unprocessed)
214 {
215 assert(a->state() != GT_Processing);
217 tgt->set_state(GT_Processing);
218 q.put(std::make_tuple(curr, a));
219 }
220 else
222 }
223 }
224
225 return count;
226 }
227
229 template <class Operation>
230 size_t exec(typename GT::Node *start, Operation && op = Operation())
231 {
232 return exec(start, op);
233 }
234
242 template <class Node_Op, class Arc_Op>
243 std::tuple<size_t, size_t> operator ()(typename GT::Node *start,
244 Node_Op & node_op, Arc_Op & arc_op)
245 {
246 assert(start != nullptr);
247 g.reset_nodes();
248 g.reset_arcs();
250
251 size_t node_count = 1;
252 size_t arc_count = 0;
253
254 start->set_state(GT_Processed);
255 if (not node_op(start))
256 return std::make_tuple(1, 0);
257
258 for (Itor it(start, sa); it.has_curr(); it.next_ne())
259 {
260 typename GT::Arc *a = it.get_curr();
261 typename GT::Node *tgt = g.get_connected_node(a, start);
264 q.put(a);
265 ++arc_count;
266 if (not arc_op(a))
267 return std::make_tuple(node_count, arc_count);
268 }
269
270 while (not q.is_empty())
271 {
272 typename GT::Arc *arc = q.get();
273 assert(arc->state() == GT_Processing);
275
276 typename GT::Node *s = g.get_src_node(arc);
277 typename GT::Node *t = g.get_tgt_node(arc);
278 if (s->state() == GT_Processed and t->state() == GT_Processed)
279 continue;
280
281 typename GT::Node *curr = s->state() == GT_Processed ? t : s;
282 assert(curr->state() == GT_Processing);
283 ++node_count;
284 curr->set_state(GT_Processed);
285 if (not node_op(curr))
286 return std::make_tuple(node_count, arc_count);
287
288 for (Itor it(curr, sa); it.has_curr(); it.next_ne())
289 {
290 typename GT::Arc *a = it.get_curr();
291 if (a->state() != GT_Unprocessed)
292 continue;
293 typename GT::Node *tgt = g.get_connected_node(a, curr);
294 if (tgt->state() != GT_Processed)
295 {
296 q.put(a);
299 ++arc_count;
300 if (not arc_op(a))
301 return std::make_tuple(node_count, arc_count);
302 }
303 else
305 }
306 }
307
308 return std::make_tuple(node_count, arc_count);
309 }
310
312 template <class Node_Op, class Arc_Op>
313 std::tuple<size_t, size_t> operator ()(typename GT::Node *start,
314 Node_Op && node_op = Node_Op(),
315 Arc_Op && arc_op = Arc_Op())
316 {
317 return (*this)(start, node_op, arc_op);
318 }
319};
320
321
322template <class GT, class Itor,
325
326template <class GT, class Itor,
329
330
331# endif // GRAPH_TRAVERSE_H
Dynamic stack of elements of generic type T based on a singly linked list.
constexpr bool is_empty() const noexcept
Return true if list is empty.
Definition htlist.H:523
void set_state(unsigned int s) noexcept
Set the state of arc to value s
Definition graph-dry.H:589
unsigned int state() const noexcept
Return the state of arc.
Definition graph-dry.H:586
unsigned int state() const noexcept
Return the state's value.
Definition graph-dry.H:500
void set_state(unsigned int s) noexcept
Set the state to value s
Definition graph-dry.H:503
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
Node * get_connected_node(Arc *arc, Node *node) const noexcept
Return the adjacent node to node through arc.
Definition graph-dry.H:772
constexpr size_t vsize() const noexcept
Definition graph-dry.H:698
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
Traverse a graph depth-first or breadth-first and execute a visit function.
size_t operator()(typename GT::Node *start, Node_Op &op)
Traverse the graph starting from start and execute op on each node.
Graph_Traverse(GT &__g, Show_Arc __sa=Show_Arc())
Construct a traverser with a graph and arc filter.
size_t exec(typename GT::Node *start, Operation &&op=Operation())
This is an overloaded member function, provided for convenience. It differs from the above function o...
size_t exec(typename GT::Node *start, Op &op)
Execute operation op(curr, arc) where curr is the visited node and arc is the incoming arc.
List_Graph< Graph_Node< int >, Graph_Arc< int > > GT
DynList< T > maps(const C &c, Op op)
Classic map operation.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
Default filter for filtered iterators on arcs.
Definition tpl_graph.H:1000
Arc of graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:222
Array-based graph implementation.
Dynamic queue implementation based on linked lists.
Dynamic stack implementation based on linked lists.