1- package Astar ;
1+ package com . thealgorithms . graph ;
22
33import 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 */
1213public 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