From 45d2e7653aa29116cb6af3e2945c5c93aa63cc19 Mon Sep 17 00:00:00 2001 From: likespro Date: Mon, 18 Nov 2024 15:44:03 +0200 Subject: [PATCH] Added new, optimized version of DijkstraAlgorithm --- .../graphs/DijkstraOptimizedAlgorithm.java | 66 +++++++++++++++++++ .../DijkstraOptimizedAlgorithmTest.java | 64 ++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 src/main/java/com/thealgorithms/datastructures/graphs/DijkstraOptimizedAlgorithm.java create mode 100644 src/test/java/com/thealgorithms/datastructures/graphs/DijkstraOptimizedAlgorithmTest.java diff --git a/src/main/java/com/thealgorithms/datastructures/graphs/DijkstraOptimizedAlgorithm.java b/src/main/java/com/thealgorithms/datastructures/graphs/DijkstraOptimizedAlgorithm.java new file mode 100644 index 000000000000..a686b808a970 --- /dev/null +++ b/src/main/java/com/thealgorithms/datastructures/graphs/DijkstraOptimizedAlgorithm.java @@ -0,0 +1,66 @@ +package com.thealgorithms.datastructures.graphs; + +import java.util.Arrays; +import java.util.Set; +import java.util.TreeSet; +import org.apache.commons.lang3.tuple.Pair; + +/** + * Dijkstra's algorithm for finding the shortest path from a single source vertex to all other vertices in a graph. + */ +public class DijkstraOptimizedAlgorithm { + + private final int vertexCount; + + /** + * Constructs a Dijkstra object with the given number of vertices. + * + * @param vertexCount The number of vertices in the graph. + */ + public DijkstraOptimizedAlgorithm(int vertexCount) { + this.vertexCount = vertexCount; + } + + /** + * Executes Dijkstra's algorithm on the provided graph to find the shortest paths from the source vertex to all other vertices. + * + * The graph is represented as an adjacency matrix where {@code graph[i][j]} represents the weight of the edge from vertex {@code i} + * to vertex {@code j}. A value of 0 indicates no edge exists between the vertices. + * + * @param graph The graph represented as an adjacency matrix. + * @param source The source vertex. + * @return An array where the value at each index {@code i} represents the shortest distance from the source vertex to vertex {@code i}. + * @throws IllegalArgumentException if the source vertex is out of range. + */ + public int[] run(int[][] graph, int source) { + if (source < 0 || source >= vertexCount) { + throw new IllegalArgumentException("Incorrect source"); + } + + int[] distances = new int[vertexCount]; + boolean[] processed = new boolean[vertexCount]; + Set> unprocessed = new TreeSet<>(); + + Arrays.fill(distances, Integer.MAX_VALUE); + Arrays.fill(processed, false); + distances[source] = 0; + unprocessed.add(Pair.of(0, source)); + + while (!unprocessed.isEmpty()) { + Pair distanceAndU = unprocessed.iterator().next(); + unprocessed.remove(distanceAndU); + int u = distanceAndU.getRight(); + processed[u] = true; + + for (int v = 0; v < vertexCount; v++) { + if (!processed[v] && graph[u][v] != 0 && distances[u] != Integer.MAX_VALUE && distances[u] + graph[u][v] < distances[v]) { + unprocessed.remove(Pair.of(distances[v], v)); + distances[v] = distances[u] + graph[u][v]; + unprocessed.add(Pair.of(distances[v], v)); + } + } + } + + return distances; + } +} diff --git a/src/test/java/com/thealgorithms/datastructures/graphs/DijkstraOptimizedAlgorithmTest.java b/src/test/java/com/thealgorithms/datastructures/graphs/DijkstraOptimizedAlgorithmTest.java new file mode 100644 index 000000000000..bf4e2828e069 --- /dev/null +++ b/src/test/java/com/thealgorithms/datastructures/graphs/DijkstraOptimizedAlgorithmTest.java @@ -0,0 +1,64 @@ +package com.thealgorithms.datastructures.graphs; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class DijkstraOptimizedAlgorithmTest { + + private DijkstraOptimizedAlgorithm dijkstraOptimizedAlgorithm; + private int[][] graph; + + @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}, + }; + + dijkstraOptimizedAlgorithm = new DijkstraOptimizedAlgorithm(graph.length); + } + + @Test + void testRunAlgorithm() { + int[] expectedDistances = {0, 4, 12, 19, 21, 11, 9, 8, 14}; + assertArrayEquals(expectedDistances, dijkstraOptimizedAlgorithm.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 + }; + + DijkstraOptimizedAlgorithm dijkstraDisconnected = new DijkstraOptimizedAlgorithm(disconnectedGraph.length); + + // Testing from vertex 0 + int[] expectedDistances = {0, 3, 4, Integer.MAX_VALUE}; // Node 3 is unreachable + assertArrayEquals(expectedDistances, dijkstraDisconnected.run(disconnectedGraph, 0)); + } + + @Test + void testSingleVertexGraph() { + int[][] singleVertexGraph = {{0}}; + DijkstraOptimizedAlgorithm dijkstraSingleVertex = new DijkstraOptimizedAlgorithm(1); + + int[] expectedDistances = {0}; // The only vertex's distance to itself is 0 + assertArrayEquals(expectedDistances, dijkstraSingleVertex.run(singleVertexGraph, 0)); + } + + @Test + void testInvalidSourceVertex() { + assertThrows(IllegalArgumentException.class, () -> dijkstraOptimizedAlgorithm.run(graph, -1)); + assertThrows(IllegalArgumentException.class, () -> dijkstraOptimizedAlgorithm.run(graph, graph.length)); + } +}