Skip to content

Commit 9a05c56

Browse files
committed
Update A* Search: dynamic input, TheAlgorithms style
1 parent af7f33f commit 9a05c56

File tree

1 file changed

+130
-112
lines changed

1 file changed

+130
-112
lines changed
Lines changed: 130 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,122 +1,140 @@
1-
package Astar;
1+
package com.thealgorithms.graph;
22

33
import java.util.*;
44

55
/**
66
* A* Search Algorithm for shortest pathfinding.
77
*
8-
* <p>Commonly used in games, navigation, and robotics. Combines Dijkstra’s Algorithm and heuristic estimation.</p>
8+
* <p>Commonly used in games, navigation, and robotics.
9+
* Combines Dijkstra’s Algorithm and heuristic estimation.</p>
910
*
10-
*
11+
* <p>Reference: https://en.wikipedia.org/wiki/A*_search_algorithm</p>
1112
*/
1213
public class AStarSearch {
1314

14-
static class Node implements Comparable<Node> {
15-
int id;
16-
double g; // Cost from start
17-
double h; // Heuristic to goal
18-
double f; // Total cost = g + h
19-
Node parent;
20-
21-
Node(int id, double g, double h, Node parent) {
22-
this.id = id;
23-
this.g = g;
24-
this.h = h;
25-
this.f = g + h;
26-
this.parent = parent;
27-
}
28-
29-
@Override
30-
public int compareTo(Node o) {
31-
return Double.compare(this.f, o.f);
32-
}
33-
}
34-
35-
private final Map<Integer, List<int[]>> graph;
36-
37-
public AStarSearch() {
38-
graph = new HashMap<>();
39-
}
40-
41-
public void addEdge(int u, int v, int weight) {
42-
graph.computeIfAbsent(u, k -> new ArrayList<>()).add(new int[]{v, weight});
43-
graph.computeIfAbsent(v, k -> new ArrayList<>()).add(new int[]{u, weight}); // if undirected
44-
}
45-
46-
private double heuristic(int node, int goal) {
47-
return Math.abs(goal - node); // Simplified heuristic
48-
}
49-
50-
public List<Integer> findPath(int start, int goal) {
51-
PriorityQueue<Node> openSet = new PriorityQueue<>();
52-
Map<Integer, Double> gScore = new HashMap<>();
53-
Set<Integer> closedSet = new HashSet<>();
54-
55-
openSet.add(new Node(start, 0, heuristic(start, goal), null));
56-
gScore.put(start, 0.0);
57-
58-
while (!openSet.isEmpty()) {
59-
Node current = openSet.poll();
60-
61-
if (current.id == goal) {
62-
return reconstructPath(current);
63-
}
64-
65-
closedSet.add(current.id);
66-
67-
for (int[] edge : graph.getOrDefault(current.id, new ArrayList<>())) {
68-
int neighbor = edge[0];
69-
double tentativeG = current.g + edge[1];
70-
71-
if (closedSet.contains(neighbor)) continue;
72-
73-
if (tentativeG < gScore.getOrDefault(neighbor, Double.MAX_VALUE)) {
74-
gScore.put(neighbor, tentativeG);
75-
Node next = new Node(neighbor, tentativeG, heuristic(neighbor, goal), current);
76-
openSet.add(next);
77-
}
78-
}
79-
}
80-
return Collections.emptyList();
81-
}
82-
83-
private List<Integer> reconstructPath(Node node) {
84-
List<Integer> path = new ArrayList<>();
85-
while (node != null) {
86-
path.add(node.id);
87-
node = node.parent;
88-
}
89-
Collections.reverse(path);
90-
return path;
91-
}
92-
93-
public static void main(String[] args) {
94-
Scanner sc = new Scanner(System.in);
95-
AStarSearch aStar = new AStarSearch();
96-
97-
System.out.print("Enter number of edges: ");
98-
int edges = sc.nextInt();
99-
100-
System.out.println("Enter edges in format: u v weight");
101-
for (int i = 0; i < edges; i++) {
102-
int u = sc.nextInt();
103-
int v = sc.nextInt();
104-
int w = sc.nextInt();
105-
aStar.addEdge(u, v, w);
106-
}
107-
108-
System.out.print("Enter start node: ");
109-
int start = sc.nextInt();
110-
111-
System.out.print("Enter goal node: ");
112-
int goal = sc.nextInt();
113-
114-
List<Integer> path = aStar.findPath(start, goal);
115-
if (path.isEmpty()) {
116-
System.out.println("No path found from " + start + " → " + goal);
117-
} else {
118-
System.out.println("Shortest path from " + start + " → " + goal + ": " + path);
119-
}
120-
sc.close();
121-
}
122-
}
15+
static class Node implements Comparable<Node> {
16+
int id;
17+
double g; // Cost from start
18+
double h; // Heuristic to goal
19+
double f; // Total cost = g + h
20+
Node parent;
21+
22+
Node(int id, double g, double h, Node parent) {
23+
this.id = id;
24+
this.g = g;
25+
this.h = h;
26+
this.f = g + h;
27+
this.parent = parent;
28+
}
29+
30+
@Override
31+
public int compareTo(Node o) {
32+
return Double.compare(this.f, o.f);
33+
}
34+
}
35+
36+
private final Map<Integer, List<int[]>> graph;
37+
38+
public AStarSearch() {
39+
graph = new HashMap<>();
40+
}
41+
42+
/**
43+
* Adds an undirected edge between nodes u and v with the given weight.
44+
*/
45+
public void addEdge(int u, int v, int weight) {
46+
graph.computeIfAbsent(u, k -> new ArrayList<>()).add(new int[]{v, weight});
47+
graph.computeIfAbsent(v, k -> new ArrayList<>()).add(new int[]{u, weight});
48+
}
49+
50+
/**
51+
* Heuristic function (simplified for numeric nodes).
52+
*/
53+
private double heuristic(int node, int goal) {
54+
return Math.abs(goal - node);
55+
}
56+
57+
/**
58+
* Finds the shortest path from start to goal using A* algorithm.
59+
*
60+
* @param start starting node
61+
* @param goal goal node
62+
* @return list of nodes representing the shortest path
63+
*/
64+
public List<Integer> findPath(int start, int goal) {
65+
PriorityQueue<Node> openSet = new PriorityQueue<>();
66+
Map<Integer, Double> gScore = new HashMap<>();
67+
Set<Integer> closedSet = new HashSet<>();
68+
69+
openSet.add(new Node(start, 0, heuristic(start, goal), null));
70+
gScore.put(start, 0.0);
71+
72+
while (!openSet.isEmpty()) {
73+
Node current = openSet.poll();
74+
75+
if (current.id == goal) {
76+
return reconstructPath(current);
77+
}
78+
79+
closedSet.add(current.id);
80+
81+
for (int[] edge : graph.getOrDefault(current.id, new ArrayList<>())) {
82+
int neighbor = edge[0];
83+
double tentativeG = current.g + edge[1];
84+
85+
if (closedSet.contains(neighbor)) continue;
86+
87+
if (tentativeG < gScore.getOrDefault(neighbor, Double.MAX_VALUE)) {
88+
gScore.put(neighbor, tentativeG);
89+
Node next = new Node(neighbor, tentativeG, heuristic(neighbor, goal), current);
90+
openSet.add(next);
91+
}
92+
}
93+
}
94+
return Collections.emptyList();
95+
}
96+
97+
/**
98+
* Reconstructs path by following parent nodes.
99+
*/
100+
private List<Integer> reconstructPath(Node node) {
101+
List<Integer> path = new ArrayList<>();
102+
while (node != null) {
103+
path.add(node.id);
104+
node = node.parent;
105+
}
106+
Collections.reverse(path);
107+
return path;
108+
}
109+
110+
/** Dynamic usage: reads graph and start/goal from input */
111+
public static void main(String[] args) {
112+
Scanner sc = new Scanner(System.in);
113+
AStarSearch aStar = new AStarSearch();
114+
115+
System.out.print("Enter number of edges: ");
116+
int edges = sc.nextInt();
117+
118+
System.out.println("Enter edges in format: u v weight");
119+
for (int i = 0; i < edges; i++) {
120+
int u = sc.nextInt();
121+
int v = sc.nextInt();
122+
int w = sc.nextInt();
123+
aStar.addEdge(u, v, w);
124+
}
125+
126+
System.out.print("Enter start node: ");
127+
int start = sc.nextInt();
128+
129+
System.out.print("Enter goal node: ");
130+
int goal = sc.nextInt();
131+
132+
List<Integer> path = aStar.findPath(start, goal);
133+
if (path.isEmpty()) {
134+
System.out.println("No path found from " + start + " → " + goal);
135+
} else {
136+
System.out.println("Shortest path from " + start + " → " + goal + ": " + path);
137+
}
138+
sc.close();
139+
}
140+
}

0 commit comments

Comments
 (0)