mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-06 09:06:51 +08:00
Add optimized version of DijkstraAlgorithm (#6088)
This commit is contained in:
@ -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<Pair<Integer, Integer>> 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<Integer, Integer> 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;
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user