Skip to content

Commit 18a2009

Browse files
committed
Add A* Search Algorithm for Weighted Graph Pathfinding
1 parent f0cda94 commit 18a2009

2 files changed

Lines changed: 50 additions & 52 deletions

File tree

src/main/java/com/thealgorithms/others/AStarSearch.java

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
package com.thealgorithms.others;
22

3-
import java.util.*;
3+
import java.util.ArrayList;
4+
import java.util.Collections;
5+
import java.util.Comparator;
6+
import java.util.HashMap;
7+
import java.util.List;
8+
import java.util.Map;
9+
import java.util.Objects;
10+
import java.util.PriorityQueue;
411

512
/**
613
* A* (A-Star) Search Algorithm implementation for finding the shortest path
@@ -26,7 +33,10 @@
2633
*
2734
* @author Suraj Devatha
2835
*/
29-
public class AStarSearch {
36+
public final class AStarSearch {
37+
38+
private AStarSearch() {
39+
}
3040

3141
/**
3242
* Finds shortest path using A*.
@@ -37,20 +47,13 @@ public class AStarSearch {
3747
* @param heuristic heuristic function
3848
* @return list of nodes representing shortest path
3949
*/
40-
public static List<Node> findPath(
41-
Map<Node, List<Edge>> graph,
42-
Node start,
43-
Node goal,
44-
Heuristic heuristic
45-
) {
50+
public static List<Node> findPath(Map<Node, List<Edge>> graph, Node start, Node goal, Heuristic heuristic) {
4651

4752
Map<Node, Double> gScore = new HashMap<>();
4853
Map<Node, Double> fScore = new HashMap<>();
4954
Map<Node, Node> cameFrom = new HashMap<>();
5055

51-
PriorityQueue<Node> openSet = new PriorityQueue<>(
52-
Comparator.comparingDouble(fScore::get)
53-
);
56+
PriorityQueue<Node> openSet = new PriorityQueue<>(Comparator.comparingDouble(fScore::get));
5457

5558
gScore.put(start, 0.0);
5659
fScore.put(start, heuristic.estimate(start, goal));
@@ -118,8 +121,12 @@ static class Node {
118121

119122
@Override
120123
public boolean equals(Object o) {
121-
if (this == o) return true;
122-
if (!(o instanceof Node)) return false;
124+
if (this == o) {
125+
return true;
126+
}
127+
if (!(o instanceof Node)) {
128+
return false;
129+
}
123130
Node node = (Node) o;
124131
return Objects.equals(id, node.id);
125132
}

src/test/java/com/thealgorithms/others/AStarSearchTest.java

Lines changed: 30 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package com.thealgorithms.others;
22

3-
import org.junit.jupiter.api.BeforeAll;
4-
import org.junit.jupiter.api.Test;
5-
6-
import java.util.*;
7-
83
import static org.junit.jupiter.api.Assertions.assertEquals;
94
import static org.junit.jupiter.api.Assertions.assertTrue;
105

6+
import java.util.Arrays;
7+
import java.util.Collections;
8+
import java.util.HashMap;
9+
import java.util.List;
10+
import java.util.Map;
11+
import org.junit.jupiter.api.BeforeAll;
12+
import org.junit.jupiter.api.Test;
13+
1114
/**
1215
* Test cases for AStarSearch algorithm.
1316
*/
@@ -18,82 +21,70 @@ class AStarSearchTest {
1821
*/
1922
private static final AStarSearch.Heuristic ZERO_HEURISTIC = (node, goal) -> 0;
2023
private static Map<AStarSearch.Node, List<AStarSearch.Edge>> graph;
21-
private static AStarSearch.Node A;
22-
private static AStarSearch.Node B;
23-
private static AStarSearch.Node C;
24-
private static AStarSearch.Node D;
24+
25+
private static AStarSearch.Node nodeA;
26+
private static AStarSearch.Node nodeB;
27+
private static AStarSearch.Node nodeC;
28+
private static AStarSearch.Node nodeD;
2529

2630
@BeforeAll
2731
static void setUp() {
2832
graph = new HashMap<>();
2933

30-
A = new AStarSearch.Node("A");
31-
B = new AStarSearch.Node("B");
32-
C = new AStarSearch.Node("C");
33-
D = new AStarSearch.Node("D");
34+
nodeA = new AStarSearch.Node("A");
35+
nodeB = new AStarSearch.Node("B");
36+
nodeC = new AStarSearch.Node("C");
37+
nodeD = new AStarSearch.Node("D");
3438

35-
graph.put(A, Arrays.asList(
36-
new AStarSearch.Edge(B, 1),
37-
new AStarSearch.Edge(C, 4)
38-
));
39+
graph.put(nodeA, Arrays.asList(new AStarSearch.Edge(nodeB, 1), new AStarSearch.Edge(nodeC, 4)));
3940

40-
graph.put(B, Arrays.asList(
41-
new AStarSearch.Edge(C, 2),
42-
new AStarSearch.Edge(D, 5)
43-
));
41+
graph.put(nodeB, Arrays.asList(new AStarSearch.Edge(nodeC, 2), new AStarSearch.Edge(nodeD, 5)));
4442

45-
graph.put(C, Arrays.asList(
46-
new AStarSearch.Edge(D, 1)
47-
));
43+
graph.put(nodeC, Arrays.asList(new AStarSearch.Edge(nodeD, 1)));
4844

49-
graph.put(D, Collections.emptyList());
45+
graph.put(nodeD, Collections.emptyList());
5046
}
5147

5248
@Test
5349
void testPathExists() {
54-
List<AStarSearch.Node> path =
55-
AStarSearch.findPath(graph, A, D, ZERO_HEURISTIC);
50+
List<AStarSearch.Node> path = AStarSearch.findPath(graph, nodeA, nodeD, ZERO_HEURISTIC);
5651

5752
// Expected shortest path: A -> B -> C -> D
58-
List<AStarSearch.Node> expected = Arrays.asList(A, B, C, D);
53+
List<AStarSearch.Node> expected = Arrays.asList(nodeA, nodeB, nodeC, nodeD);
5954

6055
assertEquals(expected, path);
6156
}
6257

6358
@Test
6459
void testDirectPath() {
65-
List<AStarSearch.Node> path =
66-
AStarSearch.findPath(graph, A, B, ZERO_HEURISTIC);
60+
List<AStarSearch.Node> path = AStarSearch.findPath(graph, nodeA, nodeB, ZERO_HEURISTIC);
6761

68-
List<AStarSearch.Node> expected = Arrays.asList(A, B);
62+
List<AStarSearch.Node> expected = Arrays.asList(nodeA, nodeB);
6963

7064
assertEquals(expected, path);
7165
}
7266

7367
@Test
7468
void testStartEqualsGoal() {
75-
List<AStarSearch.Node> path =
76-
AStarSearch.findPath(graph, A, A, ZERO_HEURISTIC);
69+
List<AStarSearch.Node> path = AStarSearch.findPath(graph, nodeA, nodeA, ZERO_HEURISTIC);
7770

78-
List<AStarSearch.Node> expected = Collections.singletonList(A);
71+
List<AStarSearch.Node> expected = Collections.singletonList(nodeA);
7972

8073
assertEquals(expected, path);
8174
}
8275

8376
@Test
8477
void testNoPathExists() {
85-
AStarSearch.Node E = new AStarSearch.Node("E");
78+
AStarSearch.Node nodeE = new AStarSearch.Node("nodeE");
8679

87-
List<AStarSearch.Node> path =
88-
AStarSearch.findPath(graph, E, A, ZERO_HEURISTIC);
80+
List<AStarSearch.Node> path = AStarSearch.findPath(graph, nodeE, nodeA, ZERO_HEURISTIC);
8981

9082
assertTrue(path.isEmpty());
9183
}
9284

9385
@Test
9486
void testPathCostOptimality() {
95-
List<AStarSearch.Node> path =
96-
AStarSearch.findPath(graph, A, D, ZERO_HEURISTIC);
87+
List<AStarSearch.Node> path = AStarSearch.findPath(graph, nodeA, nodeD, ZERO_HEURISTIC);
9788

9889
// Calculate total cost
9990
double cost = calculatePathCost(path);

0 commit comments

Comments
 (0)