Skip to content

Instantly share code, notes, and snippets.

@mikehadlow
Last active February 5, 2021 10:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikehadlow/2b2feb5e7da5d033dcc711140f3f148a to your computer and use it in GitHub Desktop.
Save mikehadlow/2b2feb5e7da5d033dcc711140f3f148a to your computer and use it in GitHub Desktop.
Topological Sort
using System;
using System.Collections.Generic;
using System.Linq;
namespace Trading.Backend.Events.Contracts.Tests
{
public static class TopologicalTest
{
public static void ShouldCorrectlyOrderNodes()
{
// A
// / \
// B C F
// \ / \ /
// D E
var d = new Node<string>("D");
var e = new Node<string>("E");
var f = new Node<string>("F");
f.Dependencies.Add(e);
var b = new Node<string>("B");
b.Dependencies.Add(d);
var c = new Node<string>("C");
c.Dependencies.Add(d);
c.Dependencies.Add(e);
var a = new Node<string>("A");
a.Dependencies.Add(b);
a.Dependencies.Add(c);
//var list = new[] { a, b, c, d, e, f };
var list = new[] { f, e, d, c, b, a };
var sorted = Topological.Sort(list);
// should output E F D C B A
foreach(var item in sorted)
{
Console.WriteLine(item);
}
}
}
public static class Topological
{
public static IEnumerable<T> Sort<T>(IEnumerable<Node<T>> input)
{
var sorted = new List<Node<T>>();
while (input.Any(x => x.Mark != NodeMark.Permanent))
{
var n = input.First(x => x.Mark == NodeMark.Unmarked);
Visit(n, sorted);
}
return sorted.Select(x => x.Value);
static void Visit<U>(Node<U> n, List<Node<U>> stack)
{
if (n.Mark == NodeMark.Permanent) return;
if (n.Mark == NodeMark.Temp) throw new ApplicationException("Circular Dependency Detected!");
n.Mark = NodeMark.Temp;
foreach(var m in n.Dependencies)
{
Visit(m, stack);
}
n.Mark = NodeMark.Permanent;
stack.Add(n);
}
}
}
public class Node<T>
{
public NodeMark Mark { get; set; }
public T Value { get; }
public List<Node<T>> Dependencies { get; }
public Node(T value)
{
Value = value;
Mark = NodeMark.Unmarked;
Dependencies = new List<Node<T>>();
}
}
public enum NodeMark
{
Unmarked,
Temp,
Permanent
}
}
@mikehadlow
Copy link
Author

Based on the Depth First Search from this Wikipedia article: https://en.wikipedia.org/wiki/Topological_sorting

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment