using System; using System.Collections.Generic; using System.Text; namespace DanieleMarotta.RiversongCodeShowcase { public class TopologicalSort { private HashSet _currentDependencies; private HashSet _closed; public TopologicalSort(IEqualityComparer comparer) { _currentDependencies = new HashSet(comparer); _closed = new HashSet(comparer); } public TopologicalSort() : this(EqualityComparer.Default) { } public static TopologicalSort Default { get; } = new(); public IEnumerable Sort(IEnumerable source, Func> dependenciesGetter, ICollection sorted = null) { sorted ??= new List(); try { foreach (var item in source) Visit(item, dependenciesGetter, sorted); } finally { _currentDependencies.Clear(); _closed.Clear(); } return sorted; } private void Visit(T item, Func> dependenciesGetter, ICollection sorted) { if (!_currentDependencies.Add(item)) { var ex = new StringBuilder(); ex.AppendLine(item.ToString()); foreach (var dependency in _currentDependencies) ex.AppendLine(dependency.ToString()); throw new InvalidOperationException(ex.ToString()); } var dependencies = dependenciesGetter.Invoke(item); if (dependencies != null) foreach (var dependency in dependencies) Visit(dependency, dependenciesGetter, sorted); _currentDependencies.Remove(item); if (_closed.Add(item)) sorted.Add(item); } } }