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 <tpl_dynListQueue.H>
56#include <tpl_graph.H>
57
58namespace Aleph {
59
75template <class GT,
76 template <typename, class> class Itor = Out_Iterator,
77 class SA = Dft_Show_Arc<GT>>
79{
80 SA & sa;
81 const GT * gptr;
82
83public:
84
89 : sa(__sa), gptr(nullptr) { /* empty */ }
90
95 : sa(__sa), gptr(nullptr) { /* empty */ }
96
97private:
98
102 template <template <class> class List>
103 void topological_sort(typename GT::Node * curr,
105 {
106 assert(gptr != nullptr);
107
108 if (IS_NODE_VISITED(curr, Depth_First))
109 return;
110
111 NODE_BITS(curr).set_bit(Depth_First, 1); // mark as visited
112
113 const auto & n = gptr->get_num_nodes();
114
115 // recursively visit adjacent nodes in postfix order
116 for (Itor<GT,SA> it(curr,sa); it.has_curr() and list.size() < n; it.next_ne())
117 topological_sort(it.get_tgt_node_ne(), list);
118
119 list.insert(curr); // postfix insertion of node that became a sink
120 }
121
122public:
123
138 template <template <class> class List>
140 {
141 g.reset_bit_nodes(Depth_First); // initialize visit marks
142
143 gptr = &g;
145
146 // traverse all nodes
147 const auto & n = gptr->get_num_nodes();
148 for (auto it = g.get_node_it(); it.has_curr() and list.size() < n;
149 it.next_ne())
150 {
151 auto curr = it.get_current_node_ne();
153 topological_sort(curr, list);
154 }
155
156 return list;
157 }
158
164 {
165 perform<DynDlist>(g).swap(list);
166 }
167};
168
188template <class GT,
189 template <typename, class> class Itor = Out_Iterator,
190 class SA = Dft_Show_Arc<GT>>
192{
194
195public:
196
201 : sa(__sa) { /* empty */ }
202
207 : sa(__sa) { /* empty */ }
208
224 template <template <class> class List>
226 {
228
230
231 // traverse all arcs and count in-degrees
232 for (Arc_Iterator<GT,SA> it(g, sa); it.has_curr(); it.next_ne())
233 NODE_COUNTER(it.get_tgt_node_ne())++;
234
235 // find nodes with in-degree 0 and enqueue them
236 DynListQueue<typename GT::Node*> q; // queue of sources
237 for (auto it = g.get_node_it(); it.has_curr(); it.next_ne())
238 {
239 auto p = it.get_current_node_ne();
240 if (NODE_COUNTER(p) == 0) // is it a source node?
241 q.put(p); // yes => enqueue it
242 }
243
244 while (not q.is_empty())
245 {
246 auto p = q.get(); // dequeue last source
247
248 assert(NODE_COUNTER(p) == 0);
249
250 list.append(p); // insert in topological order
251
252 // decrement in-degree of each node adjacent to p
253 for (Itor<GT, SA> it(p, sa); it.has_curr(); it.next_ne())
254 {
255 auto tgt = it.get_tgt_node_ne();
256 if (--NODE_COUNTER(tgt) == 0) // does tgt become a source?
257 q.put(tgt); // yes => enqueue it
258 }
259 }
260
261 return list;
262 }
263
281 template <template <class> class RankList = DynList,
282 template <class> class List = DynList>
284 {
286
287 // traverse all nodes to count in-degrees
288 for (typename GT::Node_Iterator i(g); i.has_curr(); i.next_ne())
289 for (Itor<GT, SA> j(i.get_current_node_ne(), sa);
290 j.has_curr(); j.next_ne())
291 NODE_COUNTER(j.get_tgt_node())++;
292
293 // find nodes with in-degree 0 and enqueue them
294 DynListQueue<typename GT::Node*> q; // queue of sources
295 for (typename GT::Node_Iterator it(g); it.has_curr(); it.next_ne())
296 {
297 auto p = it.get_current_node_ne();
298 if (NODE_COUNTER(p) == 0) // is it a source node?
299 q.put(p); // yes => enqueue it
300 }
301
303 while (not q.is_empty())
304 {
307
308 while (not q.is_empty()) // extract all nodes at level i
309 {
310 auto p = q.get(); // dequeue last source
311 rank.append(p); // insert in current rank
312
313 // decrement in-degree of each node adjacent to p
314 for (Itor<GT, SA> it(p, sa); it.has_curr(); it.next_ne())
315 {
316 auto tgt = it.get_tgt_node_ne();
317 if (--NODE_COUNTER(tgt) == 0) // does tgt become a source?
318 aq.put(tgt); // yes => enqueue in auxiliary queue
319 }
320 }
321
322 ranks.append(std::move(rank));
323 q.swap(aq);
324 assert(aq.is_empty());
325 }
326
327 return ranks;
328 }
329
335 {
336 auto result = this->ranks<>(g);
337 list.empty();
338 for (auto it = result.get_it(); it.has_curr(); it.next_ne())
339 list.append(std::move(it.get_curr()));
340 }
341
347 {
348 this->ranks<DynList>(g).swap(list);
349 }
350
356 {
357 this->perform<DynDlist>(g).swap(list);
358 }
359};
360
361} // end namespace Aleph
362
363#endif // TOPOLOGICAL_SORT_H
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.
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
T & put(const T &item)
Definition htlist.H:1532
DynList & swap(DynList &l) noexcept
Swap this with l.
Definition htlist.H:1448
void next_ne() noexcept
Advances the iterator to the next filtered element (noexcept version).
constexpr bool is_empty() const noexcept
Return true if list is empty.
Definition htlist.H:523
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
Filtered iterator for outcoming arcs of a node.
Definition tpl_graph.H:1750
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:1040
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:695
void reset_counter_nodes() const noexcept
Reset all the counters to zero for all the nodes of graph.
Definition graph-dry.H:1064
auto get_node_it() const noexcept
Obtains an iterator to the nodes of graph.
Definition graph-dry.H:2780
List_Graph< Graph_Node< int >, Graph_Arc< int > > GT
#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.
#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
DynList< T > maps(const C &c, Op op)
Classic map operation.
Filtered iterator on all the arcs of a graph.
Definition tpl_graph.H:1164
Default filter for filtered iterators on arcs.
Definition tpl_graph.H:1000
Dynamic queue implementation based on linked lists.
Generic graph and digraph implementations.