Repository: TheAlgorithms/Java
Pull request #5825 (2024-10-14 17:20:14)

added graph algorithm
<!--
Thank you for your contribution!
In order to reduce the number of notifications sent to the maintainers, please:
- create your PR as draft, cf. https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests,
- make sure that all of the CI checks pass,
- mark your PR as ready for review, cf. https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request#marking-a-pull-request-as-ready-for-review
-->

<!-- For completed items, change [ ] to [x] -->

- [x] I have read [CONTRIBUTING.md](https://github.com/TheAlgorithms/Java/blob/master/CONTRIBUTING.md).
- [x] This pull request is all my own work -- I have not plagiarized it.
- [x] All filenames are in PascalCase.
- [x] All functions and variable names follow Java naming conventions.
- [x] All new algorithms have a URL in their comments that points to Wikipedia or other similar explanations.
- [x] All new code is formatted with `clang-format -i --style=file path/to/your/file.java`

coffee-loves-code-2003: I have done with JUnit tests and all Prechecks.
coffee-loves-code-2003: Can anyone review this branch???



Patch:
diff --git a/src/main/java/com/thealgorithms/graph/StronglyConnectedComponentOptimized.java b/src/main/java/com/thealgorithms/graph/StronglyConnectedComponentOptimized.java
new file mode 100644
index 00000000..87d4e89d
--- /dev/null
+++ b/src/main/java/com/thealgorithms/graph/StronglyConnectedComponentOptimized.java
@@ -0,0 +1,84 @@
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Stack;
+
+/**
+ * Finds the strongly connected components in a directed graph.
+ *
+ * @param adjList The adjacency list representation of the graph.
+ * @param n The number of nodes in the graph.
+ * @return The number of strongly connected components.
+ */
+public class StronglyConnectedComponentOptimized {
+
+    public void btrack(HashMap<Integer, List<Integer>> adjList, int[] visited, Stack<Integer> dfsCallsNodes, int currentNode) {
+        visited[currentNode] = 1;
+        List<Integer> neighbors = adjList.get(currentNode);
+        // Check for null before iterating
+        if (neighbors != null) {
+            for (int neighbor : neighbors) {
+                if (visited[neighbor] == -1) {
+                    btrack(adjList, visited, dfsCallsNodes, neighbor);
+                }
+            }
+        }
+        dfsCallsNodes.add(currentNode);
+    }
+
+    public void btrack2(HashMap<Integer, List<Integer>> adjRevList, int[] visited, int currentNode, List<Integer> newScc) {
+        visited[currentNode] = 1;
+        newScc.add(currentNode);
+        List<Integer> neighbors = adjRevList.get(currentNode);
+        // Check for null before iterating
+        if (neighbors != null) {
+            for (int neighbor : neighbors) {
+                if (visited[neighbor] == -1) {
+                    btrack2(adjRevList, visited, neighbor, newScc);
+                }
+            }
+        }
+    }
+
+    public int getOutput(HashMap<Integer, List<Integer>> adjList, int n) {
+        int[] visited = new int[n];
+        Arrays.fill(visited, -1);
+        Stack<Integer> dfsCallsNodes = new Stack<>();
+
+        for (int i = 0; i < n; i++) {
+            if (visited[i] == -1) {
+                btrack(adjList, visited, dfsCallsNodes, i);
+            }
+        }
+
+        HashMap<Integer, List<Integer>> adjRevList = new HashMap<>();
+        for (int i = 0; i < n; i++) {
+            adjRevList.put(i, new ArrayList<>());
+        }
+
+        for (int i = 0; i < n; i++) {
+            List<Integer> neighbors = adjList.get(i);
+            // Check for null before iterating
+            if (neighbors != null) {
+                for (int neighbor : neighbors) {
+                    adjRevList.get(neighbor).add(i);
+                }
+            }
+        }
+
+        Arrays.fill(visited, -1);
+        int stronglyConnectedComponents = 0;
+
+        while (!dfsCallsNodes.isEmpty()) {
+            int node = dfsCallsNodes.pop();
+            if (visited[node] == -1) {
+                List<Integer> newScc = new ArrayList<>();
+                btrack2(adjRevList, visited, node, newScc);
+                stronglyConnectedComponents++;
+            }
+        }
+
+        return stronglyConnectedComponents;
+    }
+}


Test patch:
diff --git a/src/test/java/com/thealgorithms/graph/StronglyConnectedComponentOptimizedTest.java b/src/test/java/com/thealgorithms/graph/StronglyConnectedComponentOptimizedTest.java
new file mode 100644
index 00000000..6f1c8a9d
--- /dev/null
+++ b/src/test/java/com/thealgorithms/graph/StronglyConnectedComponentOptimizedTest.java
@@ -0,0 +1,78 @@
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class StronglyConnectedComponentOptimizedTest {
+
+    private StronglyConnectedComponentOptimized sccOptimized;
+
+    @BeforeEach
+    public void setUp() {
+        sccOptimized = new StronglyConnectedComponentOptimized();
+    }
+
+    @Test
+    public void testSingleComponent() {
+        // Create a simple graph with 3 nodes, all forming one SCC
+        HashMap<Integer, List<Integer>> adjList = new HashMap<>();
+        adjList.put(0, new ArrayList<>(List.of(1)));
+        adjList.put(1, new ArrayList<>(List.of(2)));
+        adjList.put(2, new ArrayList<>(List.of(0)));
+
+        int result = sccOptimized.getOutput(adjList, 3);
+
+        // The entire graph is one strongly connected component
+        assertEquals(1, result, "There should be 1 strongly connected component.");
+    }
+
+    @Test
+    public void testTwoComponents() {
+        // Create a graph with 4 nodes and two SCCs: {0, 1, 2} and {3}
+        HashMap<Integer, List<Integer>> adjList = new HashMap<>();
+        adjList.put(0, new ArrayList<>(List.of(1)));
+        adjList.put(1, new ArrayList<>(List.of(2)));
+        adjList.put(2, new ArrayList<>(List.of(0)));
+        adjList.put(3, new ArrayList<>());
+
+        int result = sccOptimized.getOutput(adjList, 4);
+
+        // There are 2 SCCs: {0, 1, 2} and {3}
+        assertEquals(2, result, "There should be 2 strongly connected components.");
+    }
+
+    @Test
+    public void testDisconnectedGraph() {
+        // Create a graph with 4 nodes that are all disconnected
+        HashMap<Integer, List<Integer>> adjList = new HashMap<>();
+        adjList.put(0, new ArrayList<>());
+        adjList.put(1, new ArrayList<>());
+        adjList.put(2, new ArrayList<>());
+        adjList.put(3, new ArrayList<>());
+
+        int result = sccOptimized.getOutput(adjList, 4);
+
+        // Each node is its own strongly connected component
+        assertEquals(4, result, "There should be 4 strongly connected components.");
+    }
+
+    @Test
+    public void testComplexGraph() {
+        // Create a more complex graph with multiple SCCs
+        HashMap<Integer, List<Integer>> adjList = new HashMap<>();
+        adjList.put(0, new ArrayList<>(List.of(1)));
+        adjList.put(1, new ArrayList<>(List.of(2)));
+        adjList.put(2, new ArrayList<>(List.of(0, 3)));
+        adjList.put(3, new ArrayList<>(List.of(4)));
+        adjList.put(4, new ArrayList<>(List.of(5)));
+        adjList.put(5, new ArrayList<>(List.of(3)));
+
+        int result = sccOptimized.getOutput(adjList, 6);
+
+        // There are 2 SCCs: {0, 1, 2} and {3, 4, 5}
+        assertEquals(2, result, "There should be 2 strongly connected components.");
+    }
+}