mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-06 09:06:51 +08:00
Enhance docs, add tests in KahnsAlgorithm (#5965)
This commit is contained in:
@ -9,96 +9,120 @@ import java.util.Queue;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A class that represents the adjaceny list of a graph
|
||||
* A class representing the adjacency list of a directed graph. The adjacency list
|
||||
* maintains a mapping of vertices to their adjacent vertices.
|
||||
*
|
||||
* @param <E> the type of vertices, extending Comparable to ensure that vertices
|
||||
* can be compared
|
||||
*/
|
||||
class AdjacencyList<E extends Comparable<E>> {
|
||||
|
||||
Map<E, ArrayList<E>> adj;
|
||||
|
||||
/**
|
||||
* Constructor to initialize the adjacency list.
|
||||
*/
|
||||
AdjacencyList() {
|
||||
adj = new LinkedHashMap<E, ArrayList<E>>();
|
||||
adj = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function adds an Edge to the adjaceny list
|
||||
* Adds a directed edge from one vertex to another in the adjacency list.
|
||||
* If the vertex does not exist, it will be added to the list.
|
||||
*
|
||||
* @param from , the vertex the edge is from
|
||||
* @param to, the vertex the edge is going to
|
||||
* @param from the starting vertex of the directed edge
|
||||
* @param to the destination vertex of the directed edge
|
||||
*/
|
||||
void addEdge(E from, E to) {
|
||||
try {
|
||||
adj.get(from).add(to);
|
||||
} catch (Exception E) {
|
||||
adj.put(from, new ArrayList<E>());
|
||||
adj.get(from).add(to);
|
||||
if (!adj.containsKey(from)) {
|
||||
adj.put(from, new ArrayList<>());
|
||||
}
|
||||
adj.get(from).add(to);
|
||||
if (!adj.containsKey(to)) {
|
||||
adj.put(to, new ArrayList<E>());
|
||||
adj.put(to, new ArrayList<>());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param v, A vertex in a graph
|
||||
* @return returns an ArrayList of all the adjacents of vertex v
|
||||
* Retrieves the list of adjacent vertices for a given vertex.
|
||||
*
|
||||
* @param v the vertex whose adjacent vertices are to be fetched
|
||||
* @return an ArrayList of adjacent vertices for vertex v
|
||||
*/
|
||||
ArrayList<E> getAdjacents(E v) {
|
||||
return adj.get(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return returns a set of all vertices in the graph
|
||||
* Retrieves the set of all vertices present in the graph.
|
||||
*
|
||||
* @return a set containing all vertices in the graph
|
||||
*/
|
||||
Set<E> getVertices() {
|
||||
return adj.keySet();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class that performs topological sorting on a directed graph using Kahn's algorithm.
|
||||
*
|
||||
* @param <E> the type of vertices, extending Comparable to ensure that vertices
|
||||
* can be compared
|
||||
*/
|
||||
class TopologicalSort<E extends Comparable<E>> {
|
||||
|
||||
AdjacencyList<E> graph;
|
||||
Map<E, Integer> inDegree;
|
||||
|
||||
/**
|
||||
* Constructor to initialize the topological sorting class with a given graph.
|
||||
*
|
||||
* @param graph the directed graph represented as an adjacency list
|
||||
*/
|
||||
TopologicalSort(AdjacencyList<E> graph) {
|
||||
this.graph = graph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the in degree of all vertices
|
||||
* Calculates the in-degree of all vertices in the graph. The in-degree is
|
||||
* the number of edges directed into a vertex.
|
||||
*/
|
||||
void calculateInDegree() {
|
||||
inDegree = new HashMap<>();
|
||||
for (E vertex : graph.getVertices()) {
|
||||
if (!inDegree.containsKey(vertex)) {
|
||||
inDegree.put(vertex, 0);
|
||||
}
|
||||
inDegree.putIfAbsent(vertex, 0);
|
||||
for (E adjacent : graph.getAdjacents(vertex)) {
|
||||
try {
|
||||
inDegree.put(adjacent, inDegree.get(adjacent) + 1);
|
||||
} catch (Exception e) {
|
||||
inDegree.put(adjacent, 1);
|
||||
}
|
||||
inDegree.put(adjacent, inDegree.getOrDefault(adjacent, 0) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an ArrayList with vertices arranged in topological order
|
||||
* Returns an ArrayList containing the vertices of the graph arranged in
|
||||
* topological order. Topological sorting ensures that for any directed edge
|
||||
* (u, v), vertex u appears before vertex v in the ordering.
|
||||
*
|
||||
* @return an ArrayList of vertices in topological order
|
||||
* @throws IllegalStateException if the graph contains a cycle
|
||||
*/
|
||||
ArrayList<E> topSortOrder() {
|
||||
calculateInDegree();
|
||||
Queue<E> q = new LinkedList<E>();
|
||||
Queue<E> q = new LinkedList<>();
|
||||
|
||||
for (final var entry : inDegree.entrySet()) {
|
||||
for (var entry : inDegree.entrySet()) {
|
||||
if (entry.getValue() == 0) {
|
||||
q.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<E> answer = new ArrayList<>();
|
||||
int processedVertices = 0;
|
||||
|
||||
while (!q.isEmpty()) {
|
||||
E current = q.poll();
|
||||
answer.add(current);
|
||||
processedVertices++;
|
||||
|
||||
for (E adjacent : graph.getAdjacents(current)) {
|
||||
inDegree.put(adjacent, inDegree.get(adjacent) - 1);
|
||||
if (inDegree.get(adjacent) == 0) {
|
||||
@ -107,12 +131,16 @@ class TopologicalSort<E extends Comparable<E>> {
|
||||
}
|
||||
}
|
||||
|
||||
if (processedVertices != graph.getVertices().size()) {
|
||||
throw new IllegalStateException("Graph contains a cycle, topological sort not possible");
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A driver class that sorts a given graph in topological order.
|
||||
* A driver class that sorts a given graph in topological order using Kahn's algorithm.
|
||||
*/
|
||||
public final class KahnsAlgorithm {
|
||||
private KahnsAlgorithm() {
|
||||
@ -130,7 +158,7 @@ public final class KahnsAlgorithm {
|
||||
|
||||
TopologicalSort<String> topSort = new TopologicalSort<>(graph);
|
||||
|
||||
// Printing the order
|
||||
// Printing the topological order
|
||||
for (String s : topSort.topSortOrder()) {
|
||||
System.out.print(s + " ");
|
||||
}
|
||||
|
Reference in New Issue
Block a user