1- /*
2- Time Complexity = O(E), where E is equal to the number of edges
3- */
41package com .thealgorithms .datastructures .graphs ;
52
63import java .util .ArrayList ;
7- import java .util .Arrays ;
84import java .util .Comparator ;
95import java .util .List ;
106import java .util .PriorityQueue ;
117
8+ /**
9+ * AStar class implements the A* pathfinding algorithm to find the shortest path in a graph.
10+ * The graph is represented using an adjacency list, and the algorithm uses a heuristic to estimate
11+ * the cost to reach the destination node.
12+ * Time Complexity = O(E), where E is equal to the number of edges
13+ */
1214public final class AStar {
1315 private AStar () {
1416 }
1517
16- private static class Graph {
17-
18- // Graph's structure can be changed only applying changes to this class.
19-
18+ /**
19+ * Represents a graph using an adjacency list.
20+ */
21+ static class Graph {
2022 private ArrayList <ArrayList <Edge >> graph ;
2123
22- // Initialise ArrayLists in Constructor
2324 Graph (int size ) {
2425 this .graph = new ArrayList <>();
2526 for (int i = 0 ; i < size ; i ++) {
@@ -31,15 +32,17 @@ private ArrayList<Edge> getNeighbours(int from) {
3132 return this .graph .get (from );
3233 }
3334
34- // Graph is bidirectional, for just one direction remove second instruction of this method.
35+ // Add a bidirectional edge to the graph
3536 private void addEdge (Edge edge ) {
3637 this .graph .get (edge .getFrom ()).add (new Edge (edge .getFrom (), edge .getTo (), edge .getWeight ()));
3738 this .graph .get (edge .getTo ()).add (new Edge (edge .getTo (), edge .getFrom (), edge .getWeight ()));
3839 }
3940 }
4041
42+ /**
43+ * Represents an edge in the graph with a start node, end node, and weight.
44+ */
4145 private static class Edge {
42-
4346 private int from ;
4447 private int to ;
4548 private int weight ;
@@ -63,12 +66,13 @@ public int getWeight() {
6366 }
6467 }
6568
66- // class to iterate during the algorithm execution, and also used to return the solution.
67- private static class PathAndDistance {
68-
69- private int distance ; // distance advanced so far.
70- private ArrayList <Integer > path ; // list of visited nodes in this path.
71- private int estimated ; // heuristic value associated to the last node od the path (current node).
69+ /**
70+ * Contains information about the path and its total distance.
71+ */
72+ static class PathAndDistance {
73+ private int distance ; // total distance from the start node
74+ private ArrayList <Integer > path ; // list of nodes in the path
75+ private int estimated ; // heuristic estimate for reaching the destination
7276
7377 PathAndDistance (int distance , ArrayList <Integer > path , int estimated ) {
7478 this .distance = distance ;
@@ -87,112 +91,54 @@ public ArrayList<Integer> getPath() {
8791 public int getEstimated () {
8892 return estimated ;
8993 }
90-
91- private void printSolution () {
92- if (this .path != null ) {
93- System .out .println ("Optimal path: " + this .path + ", distance: " + this .distance );
94- } else {
95- System .out .println ("There is no path available to connect the points" );
96- }
97- }
9894 }
9995
100- private static void initializeGraph (Graph graph , ArrayList <Integer > data ) {
96+ // Initializes the graph with edges defined in the input data
97+ static void initializeGraph (Graph graph , ArrayList <Integer > data ) {
10198 for (int i = 0 ; i < data .size (); i += 4 ) {
10299 graph .addEdge (new Edge (data .get (i ), data .get (i + 1 ), data .get (i + 2 )));
103100 }
104- /*
105- .x. node
106- (y) cost
107- - or | or / bidirectional connection
108-
109- ( 98)- .7. -(86)- .4.
110- |
111- ( 85)- .17. -(142)- .18. -(92)- .8. -(87)- .11.
112- |
113- . 1. -------------------- (160)
114- | \ |
115- (211) \ .6.
116- | \ |
117- . 5. (101)-.13. -(138) (115)
118- | | | /
119- ( 99) ( 97) | /
120- | | | /
121- .12. -(151)- .15. -(80)- .14. | /
122- | | | | /
123- ( 71) (140) (146)- .2. -(120)
124- | | |
125- .19. -( 75)- . 0. .10. -(75)- .3.
126- | |
127- (118) ( 70)
128- | |
129- .16. -(111)- .9.
130- */
131- }
132-
133- public static void main (String [] args ) {
134- // heuristic function optimistic values
135- int [] heuristic = {
136- 366 ,
137- 0 ,
138- 160 ,
139- 242 ,
140- 161 ,
141- 178 ,
142- 77 ,
143- 151 ,
144- 226 ,
145- 244 ,
146- 241 ,
147- 234 ,
148- 380 ,
149- 98 ,
150- 193 ,
151- 253 ,
152- 329 ,
153- 80 ,
154- 199 ,
155- 374 ,
156- };
157-
158- Graph graph = new Graph (20 );
159- ArrayList <Integer > graphData = new ArrayList <>(Arrays .asList (0 , 19 , 75 , null , 0 , 15 , 140 , null , 0 , 16 , 118 , null , 19 , 12 , 71 , null , 12 , 15 , 151 , null , 16 , 9 , 111 , null , 9 , 10 , 70 , null , 10 , 3 , 75 , null , 3 , 2 , 120 , null , 2 , 14 , 146 , null , 2 , 13 , 138 , null , 2 , 6 , 115 , null , 15 , 14 , 80 , null ,
160- 15 , 5 , 99 , null , 14 , 13 , 97 , null , 5 , 1 , 211 , null , 13 , 1 , 101 , null , 6 , 1 , 160 , null , 1 , 17 , 85 , null , 17 , 7 , 98 , null , 7 , 4 , 86 , null , 17 , 18 , 142 , null , 18 , 8 , 92 , null , 8 , 11 , 87 ));
161- initializeGraph (graph , graphData );
162-
163- PathAndDistance solution = aStar (3 , 1 , graph , heuristic );
164- solution .printSolution ();
165101 }
166102
103+ /**
104+ * Implements the A* pathfinding algorithm to find the shortest path from a start node to a destination node.
105+ *
106+ * @param from the starting node
107+ * @param to the destination node
108+ * @param graph the graph representation of the problem
109+ * @param heuristic the heuristic estimates for each node
110+ * @return a PathAndDistance object containing the shortest path and its distance
111+ */
167112 public static PathAndDistance aStar (int from , int to , Graph graph , int [] heuristic ) {
168- // nodes are prioritised by the less value of the current distance of their paths, and the
169- // estimated value
170- // given by the heuristic function to reach the destination point from the current point.
113+ // PriorityQueue to explore nodes based on their distance and estimated cost to reach the destination
171114 PriorityQueue <PathAndDistance > queue = new PriorityQueue <>(Comparator .comparingInt (a -> (a .getDistance () + a .getEstimated ())));
172115
173- // dummy data to start the algorithm from the beginning point
174- queue .add (new PathAndDistance (0 , new ArrayList <>(List .of (from )), 0 ));
116+ // Start with the initial node
117+ queue .add (new PathAndDistance (0 , new ArrayList <>(List .of (from )), heuristic [ from ] ));
175118
176119 boolean solutionFound = false ;
177120 PathAndDistance currentData = new PathAndDistance (-1 , null , -1 );
121+
178122 while (!queue .isEmpty () && !solutionFound ) {
179- currentData = queue .poll (); // first in the queue, best node so keep exploring.
180- int currentPosition = currentData .getPath ().get (currentData .getPath ().size () - 1 ); // current node.
123+ currentData = queue .poll (); // get the best node from the queue
124+ int currentPosition = currentData .getPath ().get (currentData .getPath ().size () - 1 ); // current node
125+
126+ // Check if the destination has been reached
181127 if (currentPosition == to ) {
182128 solutionFound = true ;
183129 } else {
184130 for (Edge edge : graph .getNeighbours (currentPosition )) {
185- if (!currentData .getPath ().contains (edge .getTo ())) { // Avoid Cycles
131+ // Avoid cycles by checking if the next node is already in the path
132+ if (!currentData .getPath ().contains (edge .getTo ())) {
186133 ArrayList <Integer > updatedPath = new ArrayList <>(currentData .getPath ());
187- updatedPath .add (edge .getTo ()); // Add the new node to the path, update the distance,
188- // and the heuristic function value associated to that path.
134+ updatedPath .add (edge .getTo ());
135+
136+ // Update the distance and heuristic for the new path
189137 queue .add (new PathAndDistance (currentData .getDistance () + edge .getWeight (), updatedPath , heuristic [edge .getTo ()]));
190138 }
191139 }
192140 }
193141 }
194142 return (solutionFound ) ? currentData : new PathAndDistance (-1 , null , -1 );
195- // Out of while loop, if there is a solution, the current Data stores the optimal path, and
196- // its distance
197143 }
198144}
0 commit comments