Last active
February 5, 2021 10:53
-
-
Save mikehadlow/2b2feb5e7da5d033dcc711140f3f148a to your computer and use it in GitHub Desktop.
Topological Sort
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Based on the Depth First Search from this Wikipedia article: https://en.wikipedia.org/wiki/Topological_sorting