-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
TopologicalSorter.cs
50 lines (41 loc) · 1.65 KB
/
TopologicalSorter.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/***
* Computes one topological sorting of a DAG (Directed Acyclic Graph).
* This class depends on the CyclesDetector static class.
*/
using System;
using System.Collections.Generic;
using DataStructures.Graphs;
namespace Algorithms.Graphs
{
public static class TopologicalSorter
{
/// <summary>
/// Private recursive helper.
/// </summary>
private static void _topoSortHelper<T>(IGraph<T> graph, T source, ref DataStructures.Lists.Stack<T> topoSortStack, ref HashSet<T> visited) where T : IComparable<T>
{
visited.Add(source);
foreach (var adjacent in graph.Neighbours(source))
if (!visited.Contains(adjacent))
_topoSortHelper<T>(graph, adjacent, ref topoSortStack, ref visited);
topoSortStack.Push(source);
}
/// <summary>
/// The Topological Sorting algorithm
/// </summary>
public static IEnumerable<T> Sort<T>(IGraph<T> Graph) where T : IComparable<T>
{
// If the graph is either null or is not a DAG, throw exception.
if (Graph == null)
throw new ArgumentNullException();
if (!Graph.IsDirected || CyclesDetector.IsCyclic<T>(Graph))
throw new Exception("The graph is not a DAG.");
var visited = new HashSet<T>();
var topoSortStack = new DataStructures.Lists.Stack<T>();
foreach (var vertex in Graph.Vertices)
if (!visited.Contains(vertex))
_topoSortHelper<T>(Graph, vertex, ref topoSortStack, ref visited);
return topoSortStack;
}
}
}