Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
topological_sort.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 TOPOLOGICAL_SORT_H
53#define TOPOLOGICAL_SORT_H
54
55# include <ah-graph-concepts.H>
56
57#include <tpl_dynListQueue.H>
58#include <tpl_graph.H>
59
60namespace Aleph {
61
77template <AlephGraph GT,
78 template <typename, class> class Itor = Out_Iterator,
81{
82 SA & sa;
83 const GT * gptr;
84
85public:
86
90 Topological_Sort(SA && __sa = SA())
91 : sa(__sa), gptr(nullptr) { /* empty */ }
92
97 : sa(__sa), gptr(nullptr) { /* empty */ }
98
99private:
100
104 template <template <class> class List>
105 void topological_sort(typename GT::Node * curr,
107 {
108 assert(gptr != nullptr);
109
110 if (IS_NODE_VISITED(curr, Depth_First))
111 return;
112
113 NODE_BITS(curr).set_bit(Depth_First, 1); // mark as visited
114
115 const auto & n = gptr->get_num_nodes();
116
117 // recursively visit adjacent nodes in postfix order
118 for (Itor<GT,SA> it(curr,sa); it.has_curr() and list.size() < n; it.next_ne())
119 topological_sort(it.get_tgt_node_ne(), list);
120
121 list.insert(curr); // postfix insertion of node that became a sink
122 }
123
124public:
125
140 template <template <class> class List>
142 {
143 g.reset_bit_nodes(Depth_First); // initialize visit marks
144
145 gptr = &g;
147
148 // traverse all nodes
149 const auto & n = gptr->get_num_nodes();
150 for (auto it = g.get_node_it(); it.has_curr() and list.size() < n;
151 it.next_ne())
152 {
153 auto curr = it.get_current_node_ne();
155 topological_sort(curr, list);
156 }
157
158 return list;
159 }
160
166 {
167 perform<DynDlist>(g).swap(list);
168 }
169};
170
190template <AlephGraph GT,
191 template <typename, class> class Itor = Out_Iterator,
194{
195 SA & sa;
196
197public:
198
203 : sa(__sa) { /* empty */ }
204
209 : sa(__sa) { /* empty */ }
210
226 template <template <class> class List>
228 {
230
232
233 // traverse all arcs and count in-degrees
234 for (Arc_Iterator<GT,SA> it(g, sa); it.has_curr(); it.next_ne())
235 NODE_COUNTER(it.get_tgt_node_ne())++;
236
237 // find nodes with in-degree 0 and enqueue them
238 DynListQueue<typename GT::Node*> q; // queue of sources
239 for (auto it = g.get_node_it(); it.has_curr(); it.next_ne())
240 {
241 auto p = it.get_current_node_ne();
242 if (NODE_COUNTER(p) == 0) // is it a source node?
243 q.put(p); // yes => enqueue it
244 }
245
246 while (not q.is_empty())
247 {
248 auto p = q.get(); // dequeue last source
249
250 assert(NODE_COUNTER(p) == 0);
251
252 list.append(p); // insert in topological order
253
254 // decrement in-degree of each node adjacent to p
255 for (Itor<GT, SA> it(p, sa); it.has_curr(); it.next_ne())
256 {
257 auto tgt = it.get_tgt_node_ne();
258 if (--NODE_COUNTER(tgt) == 0) // does tgt become a source?
259 q.put(tgt); // yes => enqueue it
260 }
261 }
262
263 return list;
264 }
265
283 template <template <class> class RankList = DynList,
284 template <class> class List = DynList>
286 {
288
289 // traverse all nodes to count in-degrees
290 for (typename GT::Node_Iterator i(g); i.has_curr(); i.next_ne())
291 for (Itor<GT, SA> j(i.get_current_node_ne(), sa);
292 j.has_curr(); j.next_ne())
293 NODE_COUNTER(j.get_tgt_node())++;
294
295 // find nodes with in-degree 0 and enqueue them
296 DynListQueue<typename GT::Node*> q; // queue of sources
297 for (typename GT::Node_Iterator it(g); it.has_curr(); it.next_ne())
298 {
299 auto p = it.get_current_node_ne();
300 if (NODE_COUNTER(p) == 0) // is it a source node?
301 q.put(p); // yes => enqueue it
302 }
303
305 while (not q.is_empty())
306 {
309
310 while (not q.is_empty()) // extract all nodes at level i
311 {
312 auto p = q.get(); // dequeue last source
313 rank.append(p); // insert in current rank
314
315 // decrement in-degree of each node adjacent to p
316 for (Itor<GT, SA> it(p, sa); it.has_curr(); it.next_ne())
317 {
318 auto tgt = it.get_tgt_node_ne();
319 if (--NODE_COUNTER(tgt) == 0) // does tgt become a source?
320 aq.put(tgt); // yes => enqueue in auxiliary queue
321 }
322 }
323
324 ranks.append(std::move(rank));
325 q.swap(aq);
326 assert(aq.is_empty());
327 }
328
329 return ranks;
330 }
331
337 {
338 auto result = this->ranks<>(g);
339 list.empty();
340 for (auto it = result.get_it(); it.has_curr(); it.next_ne())
341 list.append(std::move(it.get_curr()));
342 }
343
349 {
350 this->ranks<DynList>(g).swap(list);
351 }
352
358 {
359 this->perform<DynDlist>(g).swap(list);
360 }
361};
362
363} // end namespace Aleph
364
365#endif // TOPOLOGICAL_SORT_H
C++20 concepts for the protocol shared by graph algorithms.
List_Graph< Graph_Node< Node_Info >, Graph_Arc< Arc_Info > > GT
Node belonging to a double circular linked list with header node.
Definition tpl_dnode.H:106
Dynamic doubly linked list with O(1) size and bidirectional access.
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.
void swap(DynListQueue &__q) noexcept
Swap this with __q in constant time.
bool is_empty() const noexcept
Return true if this is empty.
Doubly-linked list (defined in tpl_dynList.H).
Definition htlist.H:1155
void next_ne() noexcept
Advances the iterator to the next filtered element (noexcept version).
Filtered iterator for outcoming arcs of a node.
Definition tpl_graph.H:1831
Computes topological ordering using breadth-first search (Kahn's algorithm).
void operator()(const GT &g, DynList< DynList< typename GT::Node * > > &list)
Operator() overload returning ranks as DynList of DynList.
Q_Topological_Sort(SA &&__sa=SA())
Constructor with rvalue arc filter.
Q_Topological_Sort(SA &__sa)
Constructor with lvalue arc filter.
void operator()(const GT &g, DynDlist< typename GT::Node * > &list)
Operator() overload for backward compatibility (flat list).
void operator()(const GT &g, DynDlist< DynList< typename GT::Node * > > &list)
Operator() overload returning ranks as DynDlist of DynList.
List< typename GT::Node * > perform(const GT &g)
Compute topological ordering using BFS (Kahn's algorithm).
RankList< List< typename GT::Node * > > ranks(const GT &g)
Compute rank-based topological ordering.
Computes topological ordering using depth-first search.
void topological_sort(typename GT::Node *curr, List< typename GT::Node * > &list)
Recursive helper for DFS-based topological sort.
List< typename GT::Node * > perform(const GT &g)
Compute topological ordering using DFS.
Topological_Sort(SA &&__sa=SA())
Constructor with rvalue arc filter.
void operator()(const GT &g, DynDlist< typename GT::Node * > &list)
Operator() overload for backward compatibility.
Topological_Sort(SA &__sa)
Constructor with lvalue arc filter.
void reset_bit_nodes(int bit) const noexcept
Reset bit to zero for all the nodes of graph.
Definition graph-dry.H:1088
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:737
void reset_counter_nodes() const noexcept
Reset all the counters to zero for all the nodes of graph.
Definition graph-dry.H:1112
auto get_node_it() const noexcept
Obtains an iterator to the nodes of graph.
Definition graph-dry.H:2886
#define NODE_COUNTER(p)
Get the counter of a node.
#define IS_NODE_VISITED(p, bit)
Determine whether the control bit is set or not to one.
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
#define NODE_BITS(p)
Get the control bits of a node.
@ Depth_First
Definition aleph-graph.H:73
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
and
Check uniqueness with explicit hash + equality functors.
Filtered iterator on all the arcs of a graph.
Definition tpl_graph.H:1165
Default filter for filtered iterators on arcs.
Definition tpl_graph.H:1001
Dynamic queue implementation based on linked lists.
Generic graph and digraph implementations.