internal class Program
{
static async Task Main(string[] args)
{
var a = new Item("A");
var c = new Item("C");
var f = new Item("F");
var h = new Item("H");
var d = new Item("D", new Item("A"));
var g = new Item("G", new Item("F"), new Item("H"));
var e = new Item("E", new Item("D", new Item("A")),
new Item("G", new Item("F"), new Item("H")));
var b = new Item("B", new Item("C"), new Item("E", new Item("D", new Item("A")),
new Item("G", new Item("F"), new Item("H"))));
var unsorted = new[] { a, b, c, d, e, f, g, h };
var sorted = TopologicalSort.Sort(unsorted, x => x.Dependencies);
Console.WriteLine(string.Join(',', sorted.Select(x => x.Name)));
Console.ReadLine();
}
}
/// <summary>
/// 拓扑排序
/// </summary>
public class TopologicalSort
{
public static IList<T> Sort<T>(
IEnumerable<T> source,
Func<T, IEnumerable<T>> getDependencies,
IEqualityComparer<T> comparer = null)
{
var sorted = new List<T>();
var visited = new Dictionary<T, bool>(comparer);
foreach (var item in source)
{
Visit(item, getDependencies, sorted, visited);
}
return sorted;
}
public static void Visit<T>(
T item,
Func<T, IEnumerable<T>> getDependencies,
List<T> sorted,
Dictionary<T, bool> visited)
{
bool inProcess;
var alreadyVisited = visited.TryGetValue(item, out inProcess);
if (alreadyVisited)
{
if (inProcess)
{
throw new ArgumentException("Cyclic dependency found.");
}
}
else
{
visited[item] = true;
var dependencies = getDependencies(item);
if (dependencies != null)
{
foreach (var dependency in dependencies)
{
Visit(dependency, getDependencies, sorted, visited);
}
}
visited[item] = false;
sorted.Add(item);
}
}
}
public class Item
{
public string Name { get; private set; }
public Item[] Dependencies { get; private set; }
public Item(string name, params Item[] dependencies)
{
Name = name;
Dependencies = dependencies;
}
}
public class ItemEqualityComparer : EqualityComparer<Item>
{
public override bool Equals(Item x, Item y)
{
return (x == null && y == null) || (x != null && y != null && x.Name == y.Name);
}
public override int GetHashCode(Item obj)
{
return obj == null ? 0 : obj.Name.GetHashCode();
}
}