101 Logo
onenoughtone

Topological Sort Pattern

What is Topological Sort?

Topological Sort is a linear ordering of vertices in a directed acyclic graph (DAG) such that for every directed edge (u, v), vertex u comes before vertex v in the ordering.

In simpler terms, it's an ordering of vertices that respects the dependencies between them.

When to Use Topological Sort

Topological Sort is useful when:

  • You need to schedule tasks with dependencies
  • You need to find the order of compilation for files with dependencies
  • You need to determine the order of courses with prerequisites
  • You need to resolve dependencies in a build system

DFS-based Topological Sort

Here's an implementation of topological sort using DFS:

function topologicalSort(graph) { // Set to keep track of visited vertices const visited = new Set(); // Stack to store the topological order const stack = []; // Visit all vertices for (const vertex in graph) { if (!visited.has(vertex)) { dfs(graph, vertex, visited, stack); } } // Reverse the stack to get the topological order return stack.reverse(); } function dfs(graph, vertex, visited, stack) { // Mark the vertex as visited visited.add(vertex); // Visit all neighbors for (const neighbor of graph[vertex]) { if (!visited.has(neighbor)) { dfs(graph, neighbor, visited, stack); } } // After visiting all neighbors, push the vertex to the stack stack.push(vertex); } // Example usage: const graph = { 'A': ['C'], 'B': ['C', 'D'], 'C': ['E'], 'D': ['F'], 'E': ['F', 'H'], 'F': ['G'], 'G': [], 'H': [] }; const order = topologicalSort(graph); console.log(order); // Output: ['B', 'A', 'D', 'C', 'E', 'F', 'G', 'H']

Important Properties

  • DAG Requirement: Topological sort is only possible for directed acyclic graphs (DAGs). If the graph has a cycle, there is no valid topological ordering.
  • Non-uniqueness: A graph can have multiple valid topological orderings.
  • Source and Sink: A source is a vertex with no incoming edges, and a sink is a vertex with no outgoing edges. In a topological ordering, sources come first and sinks come last.

Time and Space Complexity

Time Complexity:

O(V + E), where V is the number of vertices and E is the number of edges in the graph.

Space Complexity:

O(V), where V is the number of vertices in the graph, for storing the visited set and the stack.

Application: Course Schedule II

A common application of topological sort is the Course Schedule II problem, where we need to find the order in which to take courses given their prerequisites.

function findOrder(numCourses, prerequisites) { // Build the adjacency list representation of the graph const graph = Array(numCourses).fill().map(() => []); for (const [course, prereq] of prerequisites) { graph[prereq].push(course); } // 0 = not visited, 1 = visiting (in recursion stack), 2 = visited const visited = Array(numCourses).fill(0); // Stack to store the topological order const stack = []; // Check for cycles and build the topological order for (let i = 0; i < numCourses; i++) { if (visited[i] === 0 && hasCycle(graph, i, visited, stack)) { return []; // Return empty array if there's a cycle } } // Reverse the stack to get the topological order return stack.reverse(); } function hasCycle(graph, vertex, visited, stack) { // Mark the vertex as visiting visited[vertex] = 1; // Visit all neighbors for (const neighbor of graph[vertex]) { // If the neighbor is not visited, check if there's a cycle in the subtree if (visited[neighbor] === 0) { if (hasCycle(graph, neighbor, visited, stack)) { return true; } } // If the neighbor is in the recursion stack, a cycle is found else if (visited[neighbor] === 1) { return true; } } // Mark the vertex as visited visited[vertex] = 2; // After visiting all neighbors, push the vertex to the stack stack.push(vertex); // No cycle found in this subtree return false; } // Example usage: const numCourses = 4; const prerequisites = [[1, 0], [2, 0], [3, 1], [3, 2]]; const order = findOrder(numCourses, prerequisites); console.log(order); // Output: [0, 1, 2, 3]
IntroVisualizePatternsPractice
101 Logo
onenoughtone