Skip to content

Instantly share code, notes, and snippets.

@vnprc
Last active October 20, 2016 09:56
Show Gist options
  • Save vnprc/69a6d45bd8daabd45dbca8dd451584bf to your computer and use it in GitHub Desktop.
Save vnprc/69a6d45bd8daabd45dbca8dd451584bf to your computer and use it in GitHub Desktop.
An implementation of Kahn's topographical sort algorithm
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
public class TopologicalSort {
public List<Node> topographicalSort(Set<Node> nodes)
throws GraphException {
//map number of incoming dependencies for each node
Map<Node, Integer> inDegrees = new HashMap<>();
for (Node node : nodes) {
for (Node child : node.getDependencies()) {
//add or increment inDegree
inDegrees.compute(child, (key, oldValue) -> oldValue == null ? 1 : oldValue + 1);
}
//make sure all nodes are added
inDegrees.computeIfAbsent(node, value -> 0);
}
//add all nodes with no incoming dependencies
Queue<Node> queue = new LinkedList<>();
for (Node node : nodes) {
if (inDegrees.get(node) == 0) {
queue.add(node);
}
}
//iteratively subtract dependencies to leaf nodes, add new leaf nodes
LinkedList<Node> results = new LinkedList<>();
while (!queue.isEmpty()) {
Node node = queue.remove();
results.addFirst(node);
for (Node child : node.getDependencies()) {
inDegrees.compute(child, (key, value) -> value - 1);
if (inDegrees.get(child) == 0) {
queue.add(child);
}
}
}
//final check for cycles
if (results.size() != nodes.size()) {
throw new GraphException("Cyclical graph detected");
}
return results;
}
public class GraphException extends Exception {
public GraphException(String message) {
super(message);
}
}
public static class Node {
private String name;
private Set<Node> dependencies = new HashSet<>();
public Node(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void addDependency(Node node) {
dependencies.add(node);
}
public Set<Node> getDependencies() {
return dependencies;
}
@Override
public String toString() {
return name;
}
}
public static void main(String[] args) throws GraphException {
Node a = new Node("A");
Node b = new Node("B");
Node c = new Node("C");
Node d = new Node("D");
Node e = new Node("E");
Node f = new Node("F");
Node g = new Node("G");
Node h = new Node("H");
b.addDependency(a);
d.addDependency(c);
d.addDependency(b);
e.addDependency(d);
f.addDependency(d);
f.addDependency(c);
g.addDependency(f);
g.addDependency(b);
h.addDependency(e);
Set<Node> nodes = new HashSet<>(Arrays.asList(a, b, c, d, e, f, g, h));
System.out.println(new TopologicalSort().topographicalSort(nodes));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment