diff --git a/pom.xml b/pom.xml index 170e3900b77f..978c774d6caa 100644 --- a/pom.xml +++ b/pom.xml @@ -76,6 +76,7 @@ -Xlint:all -Xlint:-auxiliaryclass -Werror + diff --git a/src/main/java/com/thealgorithms/datastructures/graphs/Cycles.java b/src/main/java/com/thealgorithms/datastructures/graphs/Cycles.java index aea2b74bd13b..9278a64f08bf 100644 --- a/src/main/java/com/thealgorithms/datastructures/graphs/Cycles.java +++ b/src/main/java/com/thealgorithms/datastructures/graphs/Cycles.java @@ -1,59 +1,42 @@ package com.thealgorithms.datastructures.graphs; import java.util.ArrayList; -import java.util.Scanner; +import java.util.List; class Cycle { private final int nodes; - private int[][] adjacencyMatrix; - private boolean[] visited; - ArrayList> cycles = new ArrayList>(); - - Cycle() { - Scanner in = new Scanner(System.in); - System.out.print("Enter the no. of nodes: "); - nodes = in.nextInt(); - System.out.print("Enter the no. of Edges: "); - final int edges = in.nextInt(); - - adjacencyMatrix = new int[nodes][nodes]; - visited = new boolean[nodes]; + private final int[][] adjacencyMatrix; + private final boolean[] visited; + private final List> cycles = new ArrayList<>(); + Cycle(int nodes, int[][] adjacencyMatrix) { + this.nodes = nodes; + this.adjacencyMatrix = new int[nodes][nodes]; + // Deep copy matrix to avoid side-effects for (int i = 0; i < nodes; i++) { - visited[i] = false; - } - - System.out.println("Enter the details of each edges "); - - for (int i = 0; i < edges; i++) { - int start; - int end; - start = in.nextInt(); - end = in.nextInt(); - adjacencyMatrix[start][end] = 1; + System.arraycopy(adjacencyMatrix[i], 0, this.adjacencyMatrix[i], 0, nodes); } - in.close(); + this.visited = new boolean[nodes]; } public void start() { for (int i = 0; i < nodes; i++) { - ArrayList temp = new ArrayList<>(); - dfs(i, i, temp); + dfs(i, i, new ArrayList<>()); for (int j = 0; j < nodes; j++) { - adjacencyMatrix[i][j] = 0; - adjacencyMatrix[j][i] = 0; + this.adjacencyMatrix[i][j] = 0; + this.adjacencyMatrix[j][i] = 0; } } } - private void dfs(Integer start, Integer curr, ArrayList temp) { + private void dfs(int start, int curr, List temp) { temp.add(curr); visited[curr] = true; for (int i = 0; i < nodes; i++) { if (adjacencyMatrix[curr][i] == 1) { if (i == start) { - cycles.add(new ArrayList(temp)); + cycles.add(new ArrayList<>(temp)); } else { if (!visited[i]) { dfs(start, i, temp); @@ -62,18 +45,24 @@ private void dfs(Integer start, Integer curr, ArrayList temp) { } } - if (temp.size() > 0) { + if (!temp.isEmpty()) { temp.remove(temp.size() - 1); } visited[curr] = false; } + public List> getCycles() { + return cycles; + } + public void printAll() { - for (int i = 0; i < cycles.size(); i++) { - for (int j = 0; j < cycles.get(i).size(); j++) { - System.out.print(cycles.get(i).get(j) + " -> "); + for (List cycle : cycles) { + for (Integer node : cycle) { + System.out.print(node + " -> "); + } + if (!cycle.isEmpty()) { + System.out.println(cycle.get(0)); } - System.out.println(cycles.get(i).get(0)); System.out.println(); } } @@ -84,7 +73,15 @@ private Cycles() { } public static void main(String[] args) { - Cycle c = new Cycle(); + // Example usage with a triangle graph: 0 -> 1 -> 2 -> 0 + int nodes = 3; + int[][] matrix = { + { 0, 1, 1 }, + { 1, 0, 1 }, + { 1, 1, 0 } + }; + + Cycle c = new Cycle(nodes, matrix); c.start(); c.printAll(); } diff --git a/src/test/java/com/thealgorithms/datastructures/graphs/CyclesTest.java b/src/test/java/com/thealgorithms/datastructures/graphs/CyclesTest.java new file mode 100644 index 000000000000..96ae89e54e08 --- /dev/null +++ b/src/test/java/com/thealgorithms/datastructures/graphs/CyclesTest.java @@ -0,0 +1,76 @@ +package com.thealgorithms.datastructures.graphs; + +import org.junit.jupiter.api.Test; +import java.util.List; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class CyclesTest { + + @Test + void testTriangleCycle() { + // Triangle graph: 0-1, 1-2, 2-0 + int nodes = 3; + int[][] matrix = { + { 0, 1, 1 }, + { 1, 0, 1 }, + { 1, 1, 0 } + }; + + Cycle c = new Cycle(nodes, matrix); + c.start(); + List> cycles = c.getCycles(); + + // Should find at least one cycle: [0, 1, 2] + // Note: The algorithm modifies the matrix as it goes, so it finds elementary + // cycles. + // For a triangle, it finds 0-1-2. + + assertFalse(cycles.isEmpty(), "Should detect at least one cycle"); + // Verify the cycle content + boolean foundTriangle = false; + for (List cycle : cycles) { + if (cycle.size() == 3 && cycle.contains(0) && cycle.contains(1) && cycle.contains(2)) { + foundTriangle = true; + break; + } + } + assertTrue(foundTriangle, "Should detect the 0-1-2 triangle"); + } + + @Test + void testNoCycle() { + // Line graph: 0 -> 1 -> 2 + int nodes = 3; + int[][] matrix = { + { 0, 1, 0 }, + { 0, 0, 1 }, + { 0, 0, 0 } + }; + + Cycle c = new Cycle(nodes, matrix); + c.start(); + List> cycles = c.getCycles(); + + assertTrue(cycles.isEmpty(), "Should not detect any cycles in a line graph"); + } + + @Test + void testSelfLoop() { + // Node 0 has self loop + int nodes = 1; + int[][] matrix = { + { 1 } + }; + + Cycle c = new Cycle(nodes, matrix); + c.start(); + List> cycles = c.getCycles(); + + assertFalse(cycles.isEmpty(), "Should detect self loop"); + assertEquals(1, cycles.size()); + assertEquals(1, cycles.get(0).size()); + assertEquals(0, cycles.get(0).get(0)); + } +}