public static string[] GetBuildOrder(string[] projects, string[,] dependencies) { //TODO: check cycles! var graph = new Common.Graph <string, int>(); for (int i = 0; i < dependencies.GetUpperBound(0) + 1; i++) { graph.AddDirectedEdge(new Common.Edge <string, int>(dependencies[i, 0], dependencies[i, 1], 0)); } var visited = new HashSet <string>(); var ordering = new string[projects.Length]; var indexOrdering = projects.Length - 1; // find all non visited nodes with no connections to them // and set them to return List, then mark them as visited // in short, implement topological sort foreach (var project in projects) { if (!visited.Contains(project)) { // create list of visited nodes starting from 'project' node var visitedNodes = new List <string>(); execDFS(project, visited, visitedNodes, graph); foreach (var vn in visitedNodes) { ordering[indexOrdering] = vn; indexOrdering = indexOrdering - 1; } } } return(ordering); }
// Perform a depth first search on a graph with n nodes. // This impl returns number of connected nodes starting from firstNode public static int DFS(T[] nodes, Common.Edge <T, W>[] dependencies, T firstNode) { // Example // nodes = { a, b, c, d, e, f } // dependencies = { {a, d}, {f, b}, {b, d}, {f, a}, {d, c}} // DFS(params, a).Count == 5 // connected to 5 other nodes // DFS(params, e).Count == 1 // not connected to any other nodes var graph = new Common.Graph <T, W>(); for (int i = 0; i < dependencies.Length; i++) { graph.AddDirectedEdge(dependencies[i]); } var numberOfNodes = nodes.Length; // initialize visited list/map var visited = new Dictionary <T, bool>(); foreach (var p in nodes) { visited[p] = false; } var count = 0; // non recursive solution, here we use Stack var stack = new pv.Common.Stack <T>(); // lets use homemade stack stack.Push(firstNode); visited[firstNode] = true; while (!stack.IsEmpty()) { var node = stack.Pop(); // famous doSomething :) e.g. count++ count++; if (graph.ContainsKey(node)) { foreach (var edge in graph[node]) { if (!visited[edge.To]) { stack.Push(edge.To); visited[edge.To] = true; } } } } return(count); }
private static void execDFS(string project, HashSet <string> visited, List <string> visitedNodes, Common.Graph <string, int> graph) { visited.Add(project); var edges = graph.ContainsKey(project) ? graph[project] : null; if (edges != null) { foreach (var edge in edges) { if (!visited.Contains(edge.To)) { execDFS(edge.To, visited, visitedNodes, graph); } } } visitedNodes.Add(project); }