// ReSharper disable once SuggestBaseTypeForParameter private static IList <T> createTopologicalOrdering <T>(IDirectedAcyclicGraph <T> graph) where T : IEquatable <T> { // The topological ordering from low to high. var ordering = new List <T>(graph.Count); var elements = new HashSet <T>(graph.Elements); var orderedElementIndices = new Dictionary <T, int>(); while (ordering.Count < graph.Count) { // All the remaining elements which have all their predecessors added to the topological ordering // already. This includes elements which have no predecessors at all. This is equivalent to the set // of sources in a directed acyclic graph where all already elements and adjacent arrows have been // removed. var sources = elements.Where(allPredecessorsHaveBeenOrdered); // For each considered element, we look at the place of all their predecessors in the partial // topological ordering we have constructed so far. // * We first consider the most recently added predecessor of each element. That is, the predecessor // of said element that is the highest in the current partial topological ordering. // * Of all these predecessors, we pick the predecessor that is lowest in the ordering. If // there is only one element with said predecessor, that element is added to the ordering next. // * Ties are broken by looking at the next highest ordered predecessor of all tied elements. // * If all predecessors of 2 or more elements are the same, we pick the element with the least // predecessors. // This selection process is implemented by representing the predecessors of an element as a // decreasing number sequence of the predecessors' indices, and selecting the lowest of those in a // reflected lexicographic ordering. var next = sources.MinBy(createDecreasingNumberSequenceOfPredecessorIndices); orderedElementIndices.Add(next, ordering.Count); ordering.Add(next); elements.Remove(next); } return(ordering); bool allPredecessorsHaveBeenOrdered(T e) => graph.GetDirectPredecessorsOf(e) .All(n => orderedElementIndices.ContainsKey(n)); DecreasingNumberSequence createDecreasingNumberSequenceOfPredecessorIndices(T e) { var predecessorIndices = graph.GetDirectPredecessorsOf(e).Select(n => orderedElementIndices[n]); return(DecreasingNumberSequence.FromUnsortedNumbers(predecessorIndices)); } }