From a9f7f37ac534e36576dfa111af80a708a1ac6cf2 Mon Sep 17 00:00:00 2001 From: prashantdubeypng Date: Mon, 8 Dec 2025 12:19:01 +0530 Subject: [PATCH 1/3] Add unit tests for graph algorithms (BFS, DFS, Dijkstra, Bellman-Ford) #7133 - Created BellmanFordTest.java with 10 test methods covering various graph scenarios - Created ConnectedComponentTest.java with 15 test methods for DFS-based component counting - Enhanced MatrixGraphsTest.java with additional BFS/DFS test cases - Enhanced DijkstraAlgorithmTest.java with comprehensive shortest path tests Fixes #7133 --- .../graphs/BellmanFordTest.java | 158 +++++++++++++ .../graphs/ConnectedComponentTest.java | 204 ++++++++++++++++ .../graphs/DijkstraAlgorithmTest.java | 182 +++++++++++++-- .../graphs/MatrixGraphsTest.java | 217 +++++++++++++++++- 4 files changed, 744 insertions(+), 17 deletions(-) create mode 100644 src/test/java/com/thealgorithms/datastructures/graphs/BellmanFordTest.java create mode 100644 src/test/java/com/thealgorithms/datastructures/graphs/ConnectedComponentTest.java diff --git a/src/test/java/com/thealgorithms/datastructures/graphs/BellmanFordTest.java b/src/test/java/com/thealgorithms/datastructures/graphs/BellmanFordTest.java new file mode 100644 index 000000000000..c824241c680d --- /dev/null +++ b/src/test/java/com/thealgorithms/datastructures/graphs/BellmanFordTest.java @@ -0,0 +1,158 @@ +package com.thealgorithms.datastructures.graphs; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.junit.jupiter.api.Test; + +/** + * Unit tests for the BellmanFord algorithm implementation. + * Tests cover various graph scenarios including: + * - Simple weighted graphs + * - Graphs with negative weights + * - Single vertex graphs + * - Disconnected graphs + * - Linear path graphs + */ +class BellmanFordTest { + + @Test + void testSimpleGraph() { + // Create a simple graph with 5 vertices and 8 edges + // Graph visualization: + // 1 + // /|\ + // 6 | 7 + // / | \ + // 0 5 2 + // \ | / + // 8 | -2 + // \|/ + // 4---3 + // 9 + BellmanFord bellmanFord = new BellmanFord(5, 8); + bellmanFord.addEdge(0, 1, 6); + bellmanFord.addEdge(0, 4, 8); + bellmanFord.addEdge(1, 2, 7); + bellmanFord.addEdge(1, 4, 5); + bellmanFord.addEdge(2, 3, -2); + bellmanFord.addEdge(2, 4, -3); + bellmanFord.addEdge(3, 4, 9); + bellmanFord.addEdge(4, 3, 7); + + // Verify edge array creation + assertNotNull(bellmanFord.getEdgeArray()); + assertEquals(8, bellmanFord.getEdgeArray().length); + } + + @Test + void testGraphWithNegativeWeights() { + // Graph with negative edge weights (but no negative cycle) + BellmanFord bellmanFord = new BellmanFord(4, 5); + bellmanFord.addEdge(0, 1, 4); + bellmanFord.addEdge(0, 2, 5); + bellmanFord.addEdge(1, 2, -3); + bellmanFord.addEdge(2, 3, 4); + bellmanFord.addEdge(1, 3, 6); + + assertNotNull(bellmanFord.getEdgeArray()); + assertEquals(5, bellmanFord.getEdgeArray().length); + } + + @Test + void testSingleVertexGraph() { + // Graph with single vertex and no edges + BellmanFord bellmanFord = new BellmanFord(1, 0); + assertNotNull(bellmanFord.getEdgeArray()); + assertEquals(0, bellmanFord.getEdgeArray().length); + } + + @Test + void testLinearGraph() { + // Linear graph: 0 -> 1 -> 2 -> 3 + BellmanFord bellmanFord = new BellmanFord(4, 3); + bellmanFord.addEdge(0, 1, 2); + bellmanFord.addEdge(1, 2, 3); + bellmanFord.addEdge(2, 3, 4); + + assertNotNull(bellmanFord.getEdgeArray()); + assertEquals(3, bellmanFord.getEdgeArray().length); + } + + @Test + void testEdgeAddition() { + BellmanFord bellmanFord = new BellmanFord(3, 3); + + bellmanFord.addEdge(0, 1, 5); + bellmanFord.addEdge(1, 2, 3); + bellmanFord.addEdge(0, 2, 10); + + // Verify all edges were added + assertNotNull(bellmanFord.getEdgeArray()); + assertEquals(3, bellmanFord.getEdgeArray().length); + } + + @Test + void testGraphWithZeroWeightEdges() { + // Graph with zero weight edges + BellmanFord bellmanFord = new BellmanFord(3, 3); + bellmanFord.addEdge(0, 1, 0); + bellmanFord.addEdge(1, 2, 0); + bellmanFord.addEdge(0, 2, 1); + + assertNotNull(bellmanFord.getEdgeArray()); + assertEquals(3, bellmanFord.getEdgeArray().length); + } + + @Test + void testLargerGraph() { + // Larger graph with 6 vertices + BellmanFord bellmanFord = new BellmanFord(6, 9); + bellmanFord.addEdge(0, 1, 5); + bellmanFord.addEdge(0, 2, 3); + bellmanFord.addEdge(1, 3, 6); + bellmanFord.addEdge(1, 2, 2); + bellmanFord.addEdge(2, 4, 4); + bellmanFord.addEdge(2, 5, 2); + bellmanFord.addEdge(2, 3, 7); + bellmanFord.addEdge(3, 4, -1); + bellmanFord.addEdge(4, 5, -2); + + assertNotNull(bellmanFord.getEdgeArray()); + assertEquals(9, bellmanFord.getEdgeArray().length); + } + + @Test + void testVertexAndEdgeCount() { + BellmanFord bellmanFord = new BellmanFord(10, 15); + assertEquals(10, bellmanFord.vertex); + assertEquals(15, bellmanFord.edge); + } + + @Test + void testMultipleEdgesBetweenSameVertices() { + // Graph allowing multiple edges between same vertices + BellmanFord bellmanFord = new BellmanFord(2, 3); + bellmanFord.addEdge(0, 1, 5); + bellmanFord.addEdge(0, 1, 3); + bellmanFord.addEdge(1, 0, 2); + + assertNotNull(bellmanFord.getEdgeArray()); + assertEquals(3, bellmanFord.getEdgeArray().length); + } + + @Test + void testCompleteGraph() { + // Complete graph with 4 vertices (6 edges for undirected equivalent) + BellmanFord bellmanFord = new BellmanFord(4, 6); + bellmanFord.addEdge(0, 1, 1); + bellmanFord.addEdge(0, 2, 2); + bellmanFord.addEdge(0, 3, 3); + bellmanFord.addEdge(1, 2, 4); + bellmanFord.addEdge(1, 3, 5); + bellmanFord.addEdge(2, 3, 6); + + assertNotNull(bellmanFord.getEdgeArray()); + assertEquals(6, bellmanFord.getEdgeArray().length); + } +} diff --git a/src/test/java/com/thealgorithms/datastructures/graphs/ConnectedComponentTest.java b/src/test/java/com/thealgorithms/datastructures/graphs/ConnectedComponentTest.java new file mode 100644 index 000000000000..b5cfdd9de04f --- /dev/null +++ b/src/test/java/com/thealgorithms/datastructures/graphs/ConnectedComponentTest.java @@ -0,0 +1,204 @@ +package com.thealgorithms.datastructures.graphs; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.junit.jupiter.api.Test; + +/** + * Unit tests for the Graph class in ConnectedComponent.java. + * Tests the depth-first search implementation and connected component counting. + * Covers various graph topologies including: + * - Single connected components + * - Multiple disconnected components + * - Self-loops + * - Linear chains + * - Cyclic graphs + */ +class ConnectedComponentTest { + + @Test + void testSingleConnectedComponent() { + Graph graph = new Graph<>(); + graph.addEdge(1, 2); + graph.addEdge(2, 3); + graph.addEdge(3, 4); + graph.addEdge(4, 1); + + assertEquals(1, graph.countGraphs()); + } + + @Test + void testTwoDisconnectedComponents() { + Graph graph = new Graph<>(); + // Component 1: 1-2-3 + graph.addEdge(1, 2); + graph.addEdge(2, 3); + // Component 2: 4-5 + graph.addEdge(4, 5); + + assertEquals(2, graph.countGraphs()); + } + + @Test + void testThreeDisconnectedComponents() { + Graph graph = new Graph<>(); + // Component 1: a-b-c-d-e + graph.addEdge('a', 'b'); + graph.addEdge('a', 'e'); + graph.addEdge('b', 'e'); + graph.addEdge('b', 'c'); + graph.addEdge('c', 'd'); + graph.addEdge('d', 'a'); + // Component 2: x-y-z + graph.addEdge('x', 'y'); + graph.addEdge('x', 'z'); + // Component 3: w (self-loop) + graph.addEdge('w', 'w'); + + assertEquals(3, graph.countGraphs()); + } + + @Test + void testSingleNodeSelfLoop() { + Graph graph = new Graph<>(); + graph.addEdge(1, 1); + + assertEquals(1, graph.countGraphs()); + } + + @Test + void testLinearChain() { + Graph graph = new Graph<>(); + graph.addEdge(1, 2); + graph.addEdge(2, 3); + graph.addEdge(3, 4); + graph.addEdge(4, 5); + + assertEquals(1, graph.countGraphs()); + } + + @Test + void testStarTopology() { + // Star graph with center node 0 connected to nodes 1, 2, 3, 4 + Graph graph = new Graph<>(); + graph.addEdge(0, 1); + graph.addEdge(0, 2); + graph.addEdge(0, 3); + graph.addEdge(0, 4); + + assertEquals(1, graph.countGraphs()); + } + + @Test + void testCompleteGraph() { + // Complete graph K4: every node connected to every other node + Graph graph = new Graph<>(); + graph.addEdge(1, 2); + graph.addEdge(1, 3); + graph.addEdge(1, 4); + graph.addEdge(2, 3); + graph.addEdge(2, 4); + graph.addEdge(3, 4); + + assertEquals(1, graph.countGraphs()); + } + + @Test + void testStringVertices() { + Graph graph = new Graph<>(); + // Component 1 + graph.addEdge("New York", "Los Angeles"); + graph.addEdge("Los Angeles", "Chicago"); + // Component 2 + graph.addEdge("London", "Paris"); + // Component 3 + graph.addEdge("Tokyo", "Tokyo"); + + assertEquals(3, graph.countGraphs()); + } + + @Test + void testEmptyGraph() { + Graph graph = new Graph<>(); + assertEquals(0, graph.countGraphs()); + } + + @Test + void testDepthFirstSearchBasic() { + Graph graph = new Graph<>(); + graph.addEdge(1, 2); + graph.addEdge(2, 3); + + // Get the first node and perform DFS + assertNotNull(graph.nodeList); + assertEquals(3, graph.nodeList.size()); + } + + @Test + void testManyIsolatedComponents() { + Graph graph = new Graph<>(); + // Create 5 isolated components (each is a self-loop) + graph.addEdge(1, 1); + graph.addEdge(2, 2); + graph.addEdge(3, 3); + graph.addEdge(4, 4); + graph.addEdge(5, 5); + + assertEquals(5, graph.countGraphs()); + } + + @Test + void testBidirectionalEdges() { + Graph graph = new Graph<>(); + // Note: This is a directed graph representation + // Adding edge 1->2 does not automatically add 2->1 + graph.addEdge(1, 2); + graph.addEdge(2, 1); + graph.addEdge(2, 3); + graph.addEdge(3, 2); + + assertEquals(1, graph.countGraphs()); + } + + @Test + void testCyclicGraph() { + Graph graph = new Graph<>(); + // Create a cycle: 1 -> 2 -> 3 -> 4 -> 1 + graph.addEdge(1, 2); + graph.addEdge(2, 3); + graph.addEdge(3, 4); + graph.addEdge(4, 1); + + assertEquals(1, graph.countGraphs()); + } + + @Test + void testMultipleCycles() { + Graph graph = new Graph<>(); + // Cycle 1: 1 -> 2 -> 3 -> 1 + graph.addEdge(1, 2); + graph.addEdge(2, 3); + graph.addEdge(3, 1); + // Cycle 2: 4 -> 5 -> 4 + graph.addEdge(4, 5); + graph.addEdge(5, 4); + + assertEquals(2, graph.countGraphs()); + } + + @Test + void testIntegerGraphFromMainExample() { + // Recreate the example from main method + Graph graph = new Graph<>(); + graph.addEdge(1, 2); + graph.addEdge(2, 3); + graph.addEdge(2, 4); + graph.addEdge(3, 5); + graph.addEdge(7, 8); + graph.addEdge(8, 10); + graph.addEdge(10, 8); + + assertEquals(2, graph.countGraphs()); + } +} diff --git a/src/test/java/com/thealgorithms/datastructures/graphs/DijkstraAlgorithmTest.java b/src/test/java/com/thealgorithms/datastructures/graphs/DijkstraAlgorithmTest.java index c5df9acdf33b..538e382c6bd1 100644 --- a/src/test/java/com/thealgorithms/datastructures/graphs/DijkstraAlgorithmTest.java +++ b/src/test/java/com/thealgorithms/datastructures/graphs/DijkstraAlgorithmTest.java @@ -1,6 +1,7 @@ package com.thealgorithms.datastructures.graphs; import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.BeforeEach; @@ -14,15 +15,15 @@ public class DijkstraAlgorithmTest { @BeforeEach void setUp() { graph = new int[][] { - {0, 4, 0, 0, 0, 0, 0, 8, 0}, - {4, 0, 8, 0, 0, 0, 0, 11, 0}, - {0, 8, 0, 7, 0, 4, 0, 0, 2}, - {0, 0, 7, 0, 9, 14, 0, 0, 0}, - {0, 0, 0, 9, 0, 10, 0, 0, 0}, - {0, 0, 4, 14, 10, 0, 2, 0, 0}, - {0, 0, 0, 0, 0, 2, 0, 1, 6}, - {8, 11, 0, 0, 0, 0, 1, 0, 7}, - {0, 0, 2, 0, 0, 0, 6, 7, 0}, + { 0, 4, 0, 0, 0, 0, 0, 8, 0 }, + { 4, 0, 8, 0, 0, 0, 0, 11, 0 }, + { 0, 8, 0, 7, 0, 4, 0, 0, 2 }, + { 0, 0, 7, 0, 9, 14, 0, 0, 0 }, + { 0, 0, 0, 9, 0, 10, 0, 0, 0 }, + { 0, 0, 4, 14, 10, 0, 2, 0, 0 }, + { 0, 0, 0, 0, 0, 2, 0, 1, 6 }, + { 8, 11, 0, 0, 0, 0, 1, 0, 7 }, + { 0, 0, 2, 0, 0, 0, 6, 7, 0 }, }; dijkstraAlgorithm = new DijkstraAlgorithm(graph.length); @@ -30,29 +31,29 @@ void setUp() { @Test void testRunAlgorithm() { - int[] expectedDistances = {0, 4, 12, 19, 21, 11, 9, 8, 14}; + int[] expectedDistances = { 0, 4, 12, 19, 21, 11, 9, 8, 14 }; assertArrayEquals(expectedDistances, dijkstraAlgorithm.run(graph, 0)); } @Test void testGraphWithDisconnectedNodes() { int[][] disconnectedGraph = { - {0, 3, 0, 0}, {3, 0, 1, 0}, {0, 1, 0, 0}, {0, 0, 0, 0} // Node 3 is disconnected + { 0, 3, 0, 0 }, { 3, 0, 1, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 } // Node 3 is disconnected }; DijkstraAlgorithm dijkstraDisconnected = new DijkstraAlgorithm(disconnectedGraph.length); // Testing from vertex 0 - int[] expectedDistances = {0, 3, 4, Integer.MAX_VALUE}; // Node 3 is unreachable + int[] expectedDistances = { 0, 3, 4, Integer.MAX_VALUE }; // Node 3 is unreachable assertArrayEquals(expectedDistances, dijkstraDisconnected.run(disconnectedGraph, 0)); } @Test void testSingleVertexGraph() { - int[][] singleVertexGraph = {{0}}; + int[][] singleVertexGraph = { { 0 } }; DijkstraAlgorithm dijkstraSingleVertex = new DijkstraAlgorithm(1); - int[] expectedDistances = {0}; // The only vertex's distance to itself is 0 + int[] expectedDistances = { 0 }; // The only vertex's distance to itself is 0 assertArrayEquals(expectedDistances, dijkstraSingleVertex.run(singleVertexGraph, 0)); } @@ -61,4 +62,157 @@ void testInvalidSourceVertex() { assertThrows(IllegalArgumentException.class, () -> dijkstraAlgorithm.run(graph, -1)); assertThrows(IllegalArgumentException.class, () -> dijkstraAlgorithm.run(graph, graph.length)); } + + @Test + void testLinearGraph() { + // Linear graph: 0 - 1 - 2 - 3 + // with weights: 2 3 4 + int[][] linearGraph = { + { 0, 2, 0, 0 }, + { 2, 0, 3, 0 }, + { 0, 3, 0, 4 }, + { 0, 0, 4, 0 } + }; + + DijkstraAlgorithm dijkstraLinear = new DijkstraAlgorithm(4); + int[] distances = dijkstraLinear.run(linearGraph, 0); + + assertArrayEquals(new int[] { 0, 2, 5, 9 }, distances); + } + + @Test + void testStarTopology() { + // Star graph: center node 0 connected to all others + // 1(2) + // | + // 3(4)-0-2(3) + // | + // 4(5) + int[][] starGraph = { + { 0, 2, 3, 4, 5 }, + { 2, 0, 0, 0, 0 }, + { 3, 0, 0, 0, 0 }, + { 4, 0, 0, 0, 0 }, + { 5, 0, 0, 0, 0 } + }; + + DijkstraAlgorithm dijkstraStar = new DijkstraAlgorithm(5); + int[] distances = dijkstraStar.run(starGraph, 0); + + assertArrayEquals(new int[] { 0, 2, 3, 4, 5 }, distances); + } + + @Test + void testCompleteGraphK4() { + // Complete graph K4 with varying weights + int[][] completeGraph = { + { 0, 1, 2, 3 }, + { 1, 0, 4, 5 }, + { 2, 4, 0, 6 }, + { 3, 5, 6, 0 } + }; + + DijkstraAlgorithm dijkstraComplete = new DijkstraAlgorithm(4); + int[] distances = dijkstraComplete.run(completeGraph, 0); + + // Direct paths from 0 are shortest + assertArrayEquals(new int[] { 0, 1, 2, 3 }, distances); + } + + @Test + void testDifferentSourceVertex() { + // Test running from different source vertices + int[][] simpleGraph = { + { 0, 5, 0, 0 }, + { 5, 0, 3, 0 }, + { 0, 3, 0, 2 }, + { 0, 0, 2, 0 } + }; + + DijkstraAlgorithm dijkstra = new DijkstraAlgorithm(4); + + // From vertex 0 + int[] distFrom0 = dijkstra.run(simpleGraph, 0); + assertArrayEquals(new int[] { 0, 5, 8, 10 }, distFrom0); + + // From vertex 2 + int[] distFrom2 = dijkstra.run(simpleGraph, 2); + assertArrayEquals(new int[] { 8, 3, 0, 2 }, distFrom2); + + // From vertex 3 + int[] distFrom3 = dijkstra.run(simpleGraph, 3); + assertArrayEquals(new int[] { 10, 5, 2, 0 }, distFrom3); + } + + @Test + void testUnitWeightGraph() { + // Graph with all unit weights (like BFS distance) + int[][] unitGraph = { + { 0, 1, 1, 0 }, + { 1, 0, 1, 1 }, + { 1, 1, 0, 1 }, + { 0, 1, 1, 0 } + }; + + DijkstraAlgorithm dijkstraUnit = new DijkstraAlgorithm(4); + int[] distances = dijkstraUnit.run(unitGraph, 0); + + assertArrayEquals(new int[] { 0, 1, 1, 2 }, distances); + } + + @Test + void testTwoVertexGraph() { + int[][] twoVertexGraph = { + { 0, 7 }, + { 7, 0 } + }; + + DijkstraAlgorithm dijkstraTwo = new DijkstraAlgorithm(2); + int[] distances = dijkstraTwo.run(twoVertexGraph, 0); + + assertArrayEquals(new int[] { 0, 7 }, distances); + } + + @Test + void testShortcutPath() { + // Graph where direct path is longer than indirect path + // 0 --(10)--> 2 + // 0 --(1)--> 1 --(2)--> 2 + int[][] shortcutGraph = { + { 0, 1, 10 }, + { 1, 0, 2 }, + { 10, 2, 0 } + }; + + DijkstraAlgorithm dijkstraShortcut = new DijkstraAlgorithm(3); + int[] distances = dijkstraShortcut.run(shortcutGraph, 0); + + // The shortest path to vertex 2 should be 3 (via vertex 1), not 10 (direct) + assertArrayEquals(new int[] { 0, 1, 3 }, distances); + } + + @Test + void testSourceToSourceDistanceIsZero() { + // Verify distance from source to itself is always 0 + int[] distances = dijkstraAlgorithm.run(graph, 0); + assertEquals(0, distances[0]); + + distances = dijkstraAlgorithm.run(graph, 5); + assertEquals(0, distances[5]); + } + + @Test + void testLargeWeights() { + // Graph with large weights + int[][] largeWeightGraph = { + { 0, 1000, 0 }, + { 1000, 0, 2000 }, + { 0, 2000, 0 } + }; + + DijkstraAlgorithm dijkstraLarge = new DijkstraAlgorithm(3); + int[] distances = dijkstraLarge.run(largeWeightGraph, 0); + + assertArrayEquals(new int[] { 0, 1000, 3000 }, distances); + } } diff --git a/src/test/java/com/thealgorithms/datastructures/graphs/MatrixGraphsTest.java b/src/test/java/com/thealgorithms/datastructures/graphs/MatrixGraphsTest.java index cc8a2df872ce..21c2c5d7ca57 100644 --- a/src/test/java/com/thealgorithms/datastructures/graphs/MatrixGraphsTest.java +++ b/src/test/java/com/thealgorithms/datastructures/graphs/MatrixGraphsTest.java @@ -99,9 +99,9 @@ void testToString() { graph.addEdge(1, 2); String expected = " 0 1 2 \n" - + "0 : 0 1 0 \n" - + "1 : 1 0 1 \n" - + "2 : 0 1 0 \n"; + + "0 : 0 1 0 \n" + + "1 : 1 0 1 \n" + + "2 : 0 1 0 \n"; assertEquals(expected, graph.toString()); } @@ -137,4 +137,215 @@ void testDisconnectedGraph() { assertTrue(dfs.containsAll(Arrays.asList(0, 1))); assertTrue(bfs.containsAll(Arrays.asList(0, 1))); } + + @Test + void testSingleVertexGraphDfs() { + AdjacencyMatrixGraph graph = new AdjacencyMatrixGraph(1); + + List dfs = graph.depthFirstOrder(0); + assertEquals(1, dfs.size()); + assertEquals(0, dfs.getFirst()); + } + + @Test + void testSingleVertexGraphBfs() { + AdjacencyMatrixGraph graph = new AdjacencyMatrixGraph(1); + + List bfs = graph.breadthFirstOrder(0); + assertEquals(1, bfs.size()); + assertEquals(0, bfs.getFirst()); + } + + @Test + void testBfsLevelOrder() { + // Create a graph where BFS should visit level by level + // 0 + // /|\ + // 1 2 3 + // | + // 4 + AdjacencyMatrixGraph graph = new AdjacencyMatrixGraph(5); + graph.addEdge(0, 1); + graph.addEdge(0, 2); + graph.addEdge(0, 3); + graph.addEdge(1, 4); + + List bfs = graph.breadthFirstOrder(0); + assertEquals(5, bfs.size()); + assertEquals(0, bfs.get(0)); + // Level 1 vertices (1, 2, 3) should appear before level 2 vertex (4) + int indexOf4 = bfs.indexOf(4); + assertTrue(bfs.indexOf(1) < indexOf4); + assertTrue(bfs.indexOf(2) < indexOf4); + assertTrue(bfs.indexOf(3) < indexOf4); + } + + @Test + void testDfsStartFromDifferentVertices() { + AdjacencyMatrixGraph graph = new AdjacencyMatrixGraph(4); + graph.addEdge(0, 1); + graph.addEdge(1, 2); + graph.addEdge(2, 3); + + // DFS from vertex 0 + List dfs0 = graph.depthFirstOrder(0); + assertEquals(4, dfs0.size()); + assertEquals(0, dfs0.get(0)); + + // DFS from vertex 2 + List dfs2 = graph.depthFirstOrder(2); + assertEquals(4, dfs2.size()); + assertEquals(2, dfs2.get(0)); + + // DFS from vertex 3 + List dfs3 = graph.depthFirstOrder(3); + assertEquals(4, dfs3.size()); + assertEquals(3, dfs3.get(0)); + } + + @Test + void testBfsStartFromDifferentVertices() { + AdjacencyMatrixGraph graph = new AdjacencyMatrixGraph(4); + graph.addEdge(0, 1); + graph.addEdge(1, 2); + graph.addEdge(2, 3); + + // BFS from vertex 0 + List bfs0 = graph.breadthFirstOrder(0); + assertEquals(4, bfs0.size()); + assertEquals(0, bfs0.get(0)); + + // BFS from vertex 2 + List bfs2 = graph.breadthFirstOrder(2); + assertEquals(4, bfs2.size()); + assertEquals(2, bfs2.get(0)); + } + + @Test + void testStarTopologyBfs() { + // Star graph: 0 is center connected to 1, 2, 3, 4 + AdjacencyMatrixGraph graph = new AdjacencyMatrixGraph(5); + graph.addEdge(0, 1); + graph.addEdge(0, 2); + graph.addEdge(0, 3); + graph.addEdge(0, 4); + + List bfs = graph.breadthFirstOrder(0); + assertEquals(5, bfs.size()); + assertEquals(0, bfs.get(0)); + // All neighbors should be at distance 1 + assertTrue(bfs.containsAll(Arrays.asList(1, 2, 3, 4))); + } + + @Test + void testStarTopologyDfs() { + // Star graph: 0 is center connected to 1, 2, 3, 4 + AdjacencyMatrixGraph graph = new AdjacencyMatrixGraph(5); + graph.addEdge(0, 1); + graph.addEdge(0, 2); + graph.addEdge(0, 3); + graph.addEdge(0, 4); + + List dfs = graph.depthFirstOrder(0); + assertEquals(5, dfs.size()); + assertEquals(0, dfs.get(0)); + assertTrue(dfs.containsAll(Arrays.asList(1, 2, 3, 4))); + } + + @Test + void testNegativeStartVertexDfs() { + AdjacencyMatrixGraph graph = new AdjacencyMatrixGraph(5); + graph.addEdge(0, 1); + + List dfs = graph.depthFirstOrder(-1); + assertTrue(dfs.isEmpty()); + } + + @Test + void testNegativeStartVertexBfs() { + AdjacencyMatrixGraph graph = new AdjacencyMatrixGraph(5); + graph.addEdge(0, 1); + + List bfs = graph.breadthFirstOrder(-1); + assertTrue(bfs.isEmpty()); + } + + @Test + void testCompleteGraphKFour() { + // Complete graph K4: every vertex connected to every other vertex + AdjacencyMatrixGraph graph = new AdjacencyMatrixGraph(4); + graph.addEdge(0, 1); + graph.addEdge(0, 2); + graph.addEdge(0, 3); + graph.addEdge(1, 2); + graph.addEdge(1, 3); + graph.addEdge(2, 3); + + assertEquals(6, graph.numberOfEdges()); + + List dfs = graph.depthFirstOrder(0); + List bfs = graph.breadthFirstOrder(0); + + assertEquals(4, dfs.size()); + assertEquals(4, bfs.size()); + assertTrue(dfs.containsAll(Arrays.asList(0, 1, 2, 3))); + assertTrue(bfs.containsAll(Arrays.asList(0, 1, 2, 3))); + } + + @Test + void testLargerGraphTraversal() { + // Create a larger graph with 10 vertices + AdjacencyMatrixGraph graph = new AdjacencyMatrixGraph(10); + graph.addEdge(0, 1); + graph.addEdge(0, 2); + graph.addEdge(1, 3); + graph.addEdge(1, 4); + graph.addEdge(2, 5); + graph.addEdge(2, 6); + graph.addEdge(3, 7); + graph.addEdge(4, 8); + graph.addEdge(5, 9); + + List dfs = graph.depthFirstOrder(0); + List bfs = graph.breadthFirstOrder(0); + + assertEquals(10, dfs.size()); + assertEquals(10, bfs.size()); + assertEquals(0, dfs.get(0)); + assertEquals(0, bfs.get(0)); + } + + @Test + void testSelfLoop() { + AdjacencyMatrixGraph graph = new AdjacencyMatrixGraph(3); + graph.addEdge(0, 0); // Self loop + graph.addEdge(0, 1); + graph.addEdge(1, 2); + + List dfs = graph.depthFirstOrder(0); + List bfs = graph.breadthFirstOrder(0); + + assertEquals(3, dfs.size()); + assertEquals(3, bfs.size()); + } + + @Test + void testLinearGraphTraversal() { + // Linear graph: 0 - 1 - 2 - 3 - 4 + AdjacencyMatrixGraph graph = new AdjacencyMatrixGraph(5); + graph.addEdge(0, 1); + graph.addEdge(1, 2); + graph.addEdge(2, 3); + graph.addEdge(3, 4); + + List dfs = graph.depthFirstOrder(0); + List bfs = graph.breadthFirstOrder(0); + + assertEquals(5, dfs.size()); + assertEquals(5, bfs.size()); + + // In a linear graph, BFS and DFS starting from 0 should be the same + assertEquals(Arrays.asList(0, 1, 2, 3, 4), dfs); + assertEquals(Arrays.asList(0, 1, 2, 3, 4), bfs); + } } From becead1d66ce7820a3a41901f342a5a298fd3c7b Mon Sep 17 00:00:00 2001 From: LucasAHorn Date: Tue, 9 Dec 2025 19:47:32 -0600 Subject: [PATCH 2/3] fix: format files using clang --- .github/pull_request_template.md | 12 +-- .../graphs/DijkstraAlgorithmTest.java | 101 ++++++------------ .../graphs/MatrixGraphsTest.java | 6 +- 3 files changed, 41 insertions(+), 78 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index d9cc4c3c35c5..98a76d35850c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -8,9 +8,9 @@ In order to reduce the number of notifications sent to the maintainers, please: -- [ ] I have read [CONTRIBUTING.md](https://github.com/TheAlgorithms/Java/blob/master/CONTRIBUTING.md). -- [ ] This pull request is all my own work -- I have not plagiarized it. -- [ ] All filenames are in PascalCase. -- [ ] All functions and variable names follow Java naming conventions. -- [ ] All new algorithms have a URL in their comments that points to Wikipedia or other similar explanations. -- [ ] All new code is formatted with `clang-format -i --style=file path/to/your/file.java` \ No newline at end of file +- [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` \ No newline at end of file diff --git a/src/test/java/com/thealgorithms/datastructures/graphs/DijkstraAlgorithmTest.java b/src/test/java/com/thealgorithms/datastructures/graphs/DijkstraAlgorithmTest.java index 538e382c6bd1..a189091c17d3 100644 --- a/src/test/java/com/thealgorithms/datastructures/graphs/DijkstraAlgorithmTest.java +++ b/src/test/java/com/thealgorithms/datastructures/graphs/DijkstraAlgorithmTest.java @@ -15,15 +15,15 @@ public class DijkstraAlgorithmTest { @BeforeEach void setUp() { graph = new int[][] { - { 0, 4, 0, 0, 0, 0, 0, 8, 0 }, - { 4, 0, 8, 0, 0, 0, 0, 11, 0 }, - { 0, 8, 0, 7, 0, 4, 0, 0, 2 }, - { 0, 0, 7, 0, 9, 14, 0, 0, 0 }, - { 0, 0, 0, 9, 0, 10, 0, 0, 0 }, - { 0, 0, 4, 14, 10, 0, 2, 0, 0 }, - { 0, 0, 0, 0, 0, 2, 0, 1, 6 }, - { 8, 11, 0, 0, 0, 0, 1, 0, 7 }, - { 0, 0, 2, 0, 0, 0, 6, 7, 0 }, + {0, 4, 0, 0, 0, 0, 0, 8, 0}, + {4, 0, 8, 0, 0, 0, 0, 11, 0}, + {0, 8, 0, 7, 0, 4, 0, 0, 2}, + {0, 0, 7, 0, 9, 14, 0, 0, 0}, + {0, 0, 0, 9, 0, 10, 0, 0, 0}, + {0, 0, 4, 14, 10, 0, 2, 0, 0}, + {0, 0, 0, 0, 0, 2, 0, 1, 6}, + {8, 11, 0, 0, 0, 0, 1, 0, 7}, + {0, 0, 2, 0, 0, 0, 6, 7, 0}, }; dijkstraAlgorithm = new DijkstraAlgorithm(graph.length); @@ -31,29 +31,29 @@ void setUp() { @Test void testRunAlgorithm() { - int[] expectedDistances = { 0, 4, 12, 19, 21, 11, 9, 8, 14 }; + int[] expectedDistances = {0, 4, 12, 19, 21, 11, 9, 8, 14}; assertArrayEquals(expectedDistances, dijkstraAlgorithm.run(graph, 0)); } @Test void testGraphWithDisconnectedNodes() { int[][] disconnectedGraph = { - { 0, 3, 0, 0 }, { 3, 0, 1, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 } // Node 3 is disconnected + {0, 3, 0, 0}, {3, 0, 1, 0}, {0, 1, 0, 0}, {0, 0, 0, 0} // Node 3 is disconnected }; DijkstraAlgorithm dijkstraDisconnected = new DijkstraAlgorithm(disconnectedGraph.length); // Testing from vertex 0 - int[] expectedDistances = { 0, 3, 4, Integer.MAX_VALUE }; // Node 3 is unreachable + int[] expectedDistances = {0, 3, 4, Integer.MAX_VALUE}; // Node 3 is unreachable assertArrayEquals(expectedDistances, dijkstraDisconnected.run(disconnectedGraph, 0)); } @Test void testSingleVertexGraph() { - int[][] singleVertexGraph = { { 0 } }; + int[][] singleVertexGraph = {{0}}; DijkstraAlgorithm dijkstraSingleVertex = new DijkstraAlgorithm(1); - int[] expectedDistances = { 0 }; // The only vertex's distance to itself is 0 + int[] expectedDistances = {0}; // The only vertex's distance to itself is 0 assertArrayEquals(expectedDistances, dijkstraSingleVertex.run(singleVertexGraph, 0)); } @@ -67,17 +67,12 @@ void testInvalidSourceVertex() { void testLinearGraph() { // Linear graph: 0 - 1 - 2 - 3 // with weights: 2 3 4 - int[][] linearGraph = { - { 0, 2, 0, 0 }, - { 2, 0, 3, 0 }, - { 0, 3, 0, 4 }, - { 0, 0, 4, 0 } - }; + int[][] linearGraph = {{0, 2, 0, 0}, {2, 0, 3, 0}, {0, 3, 0, 4}, {0, 0, 4, 0}}; DijkstraAlgorithm dijkstraLinear = new DijkstraAlgorithm(4); int[] distances = dijkstraLinear.run(linearGraph, 0); - assertArrayEquals(new int[] { 0, 2, 5, 9 }, distances); + assertArrayEquals(new int[] {0, 2, 5, 9}, distances); } @Test @@ -88,89 +83,65 @@ void testStarTopology() { // 3(4)-0-2(3) // | // 4(5) - int[][] starGraph = { - { 0, 2, 3, 4, 5 }, - { 2, 0, 0, 0, 0 }, - { 3, 0, 0, 0, 0 }, - { 4, 0, 0, 0, 0 }, - { 5, 0, 0, 0, 0 } - }; + int[][] starGraph = {{0, 2, 3, 4, 5}, {2, 0, 0, 0, 0}, {3, 0, 0, 0, 0}, {4, 0, 0, 0, 0}, {5, 0, 0, 0, 0}}; DijkstraAlgorithm dijkstraStar = new DijkstraAlgorithm(5); int[] distances = dijkstraStar.run(starGraph, 0); - assertArrayEquals(new int[] { 0, 2, 3, 4, 5 }, distances); + assertArrayEquals(new int[] {0, 2, 3, 4, 5}, distances); } @Test void testCompleteGraphK4() { // Complete graph K4 with varying weights - int[][] completeGraph = { - { 0, 1, 2, 3 }, - { 1, 0, 4, 5 }, - { 2, 4, 0, 6 }, - { 3, 5, 6, 0 } - }; + int[][] completeGraph = {{0, 1, 2, 3}, {1, 0, 4, 5}, {2, 4, 0, 6}, {3, 5, 6, 0}}; DijkstraAlgorithm dijkstraComplete = new DijkstraAlgorithm(4); int[] distances = dijkstraComplete.run(completeGraph, 0); // Direct paths from 0 are shortest - assertArrayEquals(new int[] { 0, 1, 2, 3 }, distances); + assertArrayEquals(new int[] {0, 1, 2, 3}, distances); } @Test void testDifferentSourceVertex() { // Test running from different source vertices - int[][] simpleGraph = { - { 0, 5, 0, 0 }, - { 5, 0, 3, 0 }, - { 0, 3, 0, 2 }, - { 0, 0, 2, 0 } - }; + int[][] simpleGraph = {{0, 5, 0, 0}, {5, 0, 3, 0}, {0, 3, 0, 2}, {0, 0, 2, 0}}; DijkstraAlgorithm dijkstra = new DijkstraAlgorithm(4); // From vertex 0 int[] distFrom0 = dijkstra.run(simpleGraph, 0); - assertArrayEquals(new int[] { 0, 5, 8, 10 }, distFrom0); + assertArrayEquals(new int[] {0, 5, 8, 10}, distFrom0); // From vertex 2 int[] distFrom2 = dijkstra.run(simpleGraph, 2); - assertArrayEquals(new int[] { 8, 3, 0, 2 }, distFrom2); + assertArrayEquals(new int[] {8, 3, 0, 2}, distFrom2); // From vertex 3 int[] distFrom3 = dijkstra.run(simpleGraph, 3); - assertArrayEquals(new int[] { 10, 5, 2, 0 }, distFrom3); + assertArrayEquals(new int[] {10, 5, 2, 0}, distFrom3); } @Test void testUnitWeightGraph() { // Graph with all unit weights (like BFS distance) - int[][] unitGraph = { - { 0, 1, 1, 0 }, - { 1, 0, 1, 1 }, - { 1, 1, 0, 1 }, - { 0, 1, 1, 0 } - }; + int[][] unitGraph = {{0, 1, 1, 0}, {1, 0, 1, 1}, {1, 1, 0, 1}, {0, 1, 1, 0}}; DijkstraAlgorithm dijkstraUnit = new DijkstraAlgorithm(4); int[] distances = dijkstraUnit.run(unitGraph, 0); - assertArrayEquals(new int[] { 0, 1, 1, 2 }, distances); + assertArrayEquals(new int[] {0, 1, 1, 2}, distances); } @Test void testTwoVertexGraph() { - int[][] twoVertexGraph = { - { 0, 7 }, - { 7, 0 } - }; + int[][] twoVertexGraph = {{0, 7}, {7, 0}}; DijkstraAlgorithm dijkstraTwo = new DijkstraAlgorithm(2); int[] distances = dijkstraTwo.run(twoVertexGraph, 0); - assertArrayEquals(new int[] { 0, 7 }, distances); + assertArrayEquals(new int[] {0, 7}, distances); } @Test @@ -178,17 +149,13 @@ void testShortcutPath() { // Graph where direct path is longer than indirect path // 0 --(10)--> 2 // 0 --(1)--> 1 --(2)--> 2 - int[][] shortcutGraph = { - { 0, 1, 10 }, - { 1, 0, 2 }, - { 10, 2, 0 } - }; + int[][] shortcutGraph = {{0, 1, 10}, {1, 0, 2}, {10, 2, 0}}; DijkstraAlgorithm dijkstraShortcut = new DijkstraAlgorithm(3); int[] distances = dijkstraShortcut.run(shortcutGraph, 0); // The shortest path to vertex 2 should be 3 (via vertex 1), not 10 (direct) - assertArrayEquals(new int[] { 0, 1, 3 }, distances); + assertArrayEquals(new int[] {0, 1, 3}, distances); } @Test @@ -204,15 +171,11 @@ void testSourceToSourceDistanceIsZero() { @Test void testLargeWeights() { // Graph with large weights - int[][] largeWeightGraph = { - { 0, 1000, 0 }, - { 1000, 0, 2000 }, - { 0, 2000, 0 } - }; + int[][] largeWeightGraph = {{0, 1000, 0}, {1000, 0, 2000}, {0, 2000, 0}}; DijkstraAlgorithm dijkstraLarge = new DijkstraAlgorithm(3); int[] distances = dijkstraLarge.run(largeWeightGraph, 0); - assertArrayEquals(new int[] { 0, 1000, 3000 }, distances); + assertArrayEquals(new int[] {0, 1000, 3000}, distances); } } diff --git a/src/test/java/com/thealgorithms/datastructures/graphs/MatrixGraphsTest.java b/src/test/java/com/thealgorithms/datastructures/graphs/MatrixGraphsTest.java index 21c2c5d7ca57..eaff0222bd36 100644 --- a/src/test/java/com/thealgorithms/datastructures/graphs/MatrixGraphsTest.java +++ b/src/test/java/com/thealgorithms/datastructures/graphs/MatrixGraphsTest.java @@ -99,9 +99,9 @@ void testToString() { graph.addEdge(1, 2); String expected = " 0 1 2 \n" - + "0 : 0 1 0 \n" - + "1 : 1 0 1 \n" - + "2 : 0 1 0 \n"; + + "0 : 0 1 0 \n" + + "1 : 1 0 1 \n" + + "2 : 0 1 0 \n"; assertEquals(expected, graph.toString()); } From 604d3fed62b8a8fb69781ae4cd195111d9cbf5ee Mon Sep 17 00:00:00 2001 From: LucasAHorn Date: Tue, 9 Dec 2025 19:53:56 -0600 Subject: [PATCH 3/3] fix: removing my changes on pull_request_template --- .github/pull_request_template.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 98a76d35850c..d9cc4c3c35c5 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -8,9 +8,9 @@ In order to reduce the number of notifications sent to the maintainers, please: -- [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` \ No newline at end of file +- [ ] I have read [CONTRIBUTING.md](https://github.com/TheAlgorithms/Java/blob/master/CONTRIBUTING.md). +- [ ] This pull request is all my own work -- I have not plagiarized it. +- [ ] All filenames are in PascalCase. +- [ ] All functions and variable names follow Java naming conventions. +- [ ] All new algorithms have a URL in their comments that points to Wikipedia or other similar explanations. +- [ ] All new code is formatted with `clang-format -i --style=file path/to/your/file.java` \ No newline at end of file