Skip to content

Commit 608fe18

Browse files
Implement topological sort with DAG validation and cycle detection
1 parent f9a9ccb commit 608fe18

File tree

2 files changed

+466
-0
lines changed

2 files changed

+466
-0
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package com.thealgorithms.graph;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import java.util.Stack;
6+
7+
/**
8+
* Topological Sort Algorithm
9+
*
10+
* Topological sorting of a directed graph is a linear ordering of its vertices
11+
* such that for every directed edge (u,v) from vertex u to vertex v, u comes
12+
* before v in the ordering.
13+
*
14+
* A topological sort is possible only in a directed acyclic graph (DAG).
15+
* This file contains code of finding topological sort using Depth First Search technique.
16+
*/
17+
public class TopologicalSort {
18+
19+
/**
20+
* Class that represents a directed graph and provides methods for
21+
* manipulating the graph
22+
*/
23+
public static class Graph {
24+
private final int n; // Number of nodes
25+
private final List<List<Integer>> adj; // Adjacency list representation
26+
27+
/**
28+
* Constructor for the Graph class
29+
* @param nodes Number of nodes in the graph
30+
*/
31+
public Graph(int nodes) {
32+
this.n = nodes;
33+
this.adj = new ArrayList<>(nodes);
34+
for (int i = 0; i < nodes; i++) {
35+
adj.add(new ArrayList<>());
36+
}
37+
}
38+
39+
/**
40+
* Function that adds an edge between two nodes or vertices of graph
41+
* @param u Start node of the edge
42+
* @param v End node of the edge
43+
*/
44+
public void addEdge(int u, int v) {
45+
adj.get(u).add(v);
46+
}
47+
48+
/**
49+
* Get the adjacency list of the graph
50+
* @return The adjacency list
51+
*/
52+
public List<List<Integer>> getAdjacencyList() {
53+
return adj;
54+
}
55+
56+
/**
57+
* Get the number of nodes in the graph
58+
* @return The number of nodes
59+
*/
60+
public int getNumNodes() {
61+
return n;
62+
}
63+
}
64+
65+
/**
66+
* Function to perform Depth First Search on the graph
67+
* @param v Starting vertex for depth-first search
68+
* @param visited Array representing whether each node has been visited
69+
* @param recStack Array representing nodes in current recursion stack
70+
* @param graph Adjacency list of the graph
71+
* @param stack Stack containing the vertices for topological sorting
72+
* @return true if cycle is detected, false otherwise
73+
*/
74+
private static boolean dfs(int v, boolean[] visited, boolean[] recStack,
75+
List<List<Integer>> graph, Stack<Integer> stack) {
76+
visited[v] = true;
77+
recStack[v] = true;
78+
79+
for (int neighbour : graph.get(v)) {
80+
if (!visited[neighbour]) {
81+
if (dfs(neighbour, visited, recStack, graph, stack)) {
82+
return true; // Cycle detected
83+
}
84+
} else if (recStack[neighbour]) {
85+
return true; // Back edge found - cycle detected
86+
}
87+
}
88+
89+
recStack[v] = false; // Remove from recursion stack
90+
stack.push(v);
91+
return false;
92+
}
93+
94+
/**
95+
* Function to get the topological sort of the graph
96+
* @param g Graph object
97+
* @return A list containing the topological order of nodes
98+
* @throws IllegalArgumentException if cycle is detected
99+
*/
100+
public static List<Integer> sort(Graph g) {
101+
int n = g.getNumNodes();
102+
List<List<Integer>> adj = g.getAdjacencyList();
103+
boolean[] visited = new boolean[n];
104+
boolean[] recStack = new boolean[n];
105+
Stack<Integer> stack = new Stack<>();
106+
107+
for (int i = 0; i < n; i++) {
108+
if (!visited[i]) {
109+
if (dfs(i, visited, recStack, adj, stack)) {
110+
throw new IllegalArgumentException("cycle detected in graph");
111+
}
112+
}
113+
}
114+
115+
List<Integer> ans = new ArrayList<>();
116+
while (!stack.isEmpty()) {
117+
int elem = stack.pop();
118+
ans.add(elem);
119+
}
120+
121+
return ans;
122+
}
123+
124+
}

0 commit comments

Comments
 (0)