riversong code showcase
This commit is contained in:
63
Source/Engine/Helpers/TopologicalSort.cs
Normal file
63
Source/Engine/Helpers/TopologicalSort.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace DanieleMarotta.RiversongCodeShowcase
|
||||
{
|
||||
public class TopologicalSort<T>
|
||||
{
|
||||
private HashSet<T> _currentDependencies;
|
||||
|
||||
private HashSet<T> _closed;
|
||||
|
||||
public TopologicalSort(IEqualityComparer<T> comparer)
|
||||
{
|
||||
_currentDependencies = new HashSet<T>(comparer);
|
||||
_closed = new HashSet<T>(comparer);
|
||||
}
|
||||
|
||||
public TopologicalSort() : this(EqualityComparer<T>.Default)
|
||||
{
|
||||
}
|
||||
|
||||
public static TopologicalSort<T> Default { get; } = new();
|
||||
|
||||
public IEnumerable<T> Sort(IEnumerable<T> source, Func<T, List<T>> dependenciesGetter, ICollection<T> sorted = null)
|
||||
{
|
||||
sorted ??= new List<T>();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var item in source) Visit(item, dependenciesGetter, sorted);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_currentDependencies.Clear();
|
||||
_closed.Clear();
|
||||
}
|
||||
|
||||
return sorted;
|
||||
}
|
||||
|
||||
private void Visit(T item, Func<T, List<T>> dependenciesGetter, ICollection<T> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user