Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
<arg>-Xlint:all</arg>
<arg>-Xlint:-auxiliaryclass</arg>
<arg>-Werror</arg>

</compilerArgs>
</configuration>
</plugin>
Expand Down
73 changes: 35 additions & 38 deletions src/main/java/com/thealgorithms/datastructures/graphs/Cycles.java
Original file line number Diff line number Diff line change
@@ -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<ArrayList<Integer>> cycles = new ArrayList<ArrayList<Integer>>();

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<List<Integer>> 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 <Start Node> <End Node>");

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<Integer> 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<Integer> temp) {
private void dfs(int start, int curr, List<Integer> 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<Integer>(temp));
cycles.add(new ArrayList<>(temp));
} else {
if (!visited[i]) {
dfs(start, i, temp);
Expand All @@ -62,18 +45,24 @@ private void dfs(Integer start, Integer curr, ArrayList<Integer> temp) {
}
}

if (temp.size() > 0) {
if (!temp.isEmpty()) {
temp.remove(temp.size() - 1);
}
visited[curr] = false;
}

public List<List<Integer>> 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<Integer> 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();
}
}
Expand All @@ -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();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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<List<Integer>> 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<Integer> 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<List<Integer>> 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<List<Integer>> 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));
}
}
Loading