1
- /*
2
- Time Complexity = O(E), where E is equal to the number of edges
3
- */
4
1
package com .thealgorithms .datastructures .graphs ;
5
2
6
3
import java .util .ArrayList ;
9
6
import java .util .List ;
10
7
import java .util .PriorityQueue ;
11
8
9
+ /**
10
+ * AStar class implements the A* pathfinding algorithm to find the shortest path in a graph.
11
+ * The graph is represented using an adjacency list, and the algorithm uses a heuristic to estimate
12
+ * the cost to reach the destination node.
13
+ * Time Complexity = O(E), where E is equal to the number of edges
14
+ */
12
15
public final class AStar {
13
16
private AStar () {
14
17
}
15
18
16
- private static class Graph {
17
-
18
- // Graph's structure can be changed only applying changes to this class.
19
-
19
+ /**
20
+ * Represents a graph using an adjacency list.
21
+ */
22
+ static class Graph {
20
23
private ArrayList <ArrayList <Edge >> graph ;
21
24
22
- // Initialise ArrayLists in Constructor
23
25
Graph (int size ) {
24
26
this .graph = new ArrayList <>();
25
27
for (int i = 0 ; i < size ; i ++) {
@@ -31,15 +33,17 @@ private ArrayList<Edge> getNeighbours(int from) {
31
33
return this .graph .get (from );
32
34
}
33
35
34
- // Graph is bidirectional, for just one direction remove second instruction of this method.
36
+ // Add a bidirectional edge to the graph
35
37
private void addEdge (Edge edge ) {
36
38
this .graph .get (edge .getFrom ()).add (new Edge (edge .getFrom (), edge .getTo (), edge .getWeight ()));
37
39
this .graph .get (edge .getTo ()).add (new Edge (edge .getTo (), edge .getFrom (), edge .getWeight ()));
38
40
}
39
41
}
40
42
43
+ /**
44
+ * Represents an edge in the graph with a start node, end node, and weight.
45
+ */
41
46
private static class Edge {
42
-
43
47
private int from ;
44
48
private int to ;
45
49
private int weight ;
@@ -63,12 +67,13 @@ public int getWeight() {
63
67
}
64
68
}
65
69
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).
70
+ /**
71
+ * Contains information about the path and its total distance.
72
+ */
73
+ static class PathAndDistance {
74
+ private int distance ; // total distance from the start node
75
+ private ArrayList <Integer > path ; // list of nodes in the path
76
+ private int estimated ; // heuristic estimate for reaching the destination
72
77
73
78
PathAndDistance (int distance , ArrayList <Integer > path , int estimated ) {
74
79
this .distance = distance ;
@@ -97,102 +102,54 @@ private void printSolution() {
97
102
}
98
103
}
99
104
100
- private static void initializeGraph (Graph graph , ArrayList <Integer > data ) {
105
+ // Initializes the graph with edges defined in the input data
106
+ static void initializeGraph (Graph graph , ArrayList <Integer > data ) {
101
107
for (int i = 0 ; i < data .size (); i += 4 ) {
102
108
graph .addEdge (new Edge (data .get (i ), data .get (i + 1 ), data .get (i + 2 )));
103
109
}
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 ();
165
110
}
166
111
112
+ /**
113
+ * Implements the A* pathfinding algorithm to find the shortest path from a start node to a destination node.
114
+ *
115
+ * @param from the starting node
116
+ * @param to the destination node
117
+ * @param graph the graph representation of the problem
118
+ * @param heuristic the heuristic estimates for each node
119
+ * @return a PathAndDistance object containing the shortest path and its distance
120
+ */
167
121
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.
171
- PriorityQueue < PathAndDistance > queue = new PriorityQueue <>( Comparator . comparingInt ( a -> ( a . getDistance () + a . getEstimated ())) );
122
+ // PriorityQueue to explore nodes based on their distance and estimated cost to reach the destination
123
+ PriorityQueue < PathAndDistance > queue = new PriorityQueue <>(
124
+ Comparator . comparingInt ( a -> ( a . getDistance () + a . getEstimated ()))
125
+ );
172
126
173
- // dummy data to start the algorithm from the beginning point
174
- queue .add (new PathAndDistance (0 , new ArrayList <>(List .of (from )), 0 ));
127
+ // Start with the initial node
128
+ queue .add (new PathAndDistance (0 , new ArrayList <>(List .of (from )), heuristic [ from ] ));
175
129
176
130
boolean solutionFound = false ;
177
131
PathAndDistance currentData = new PathAndDistance (-1 , null , -1 );
132
+
178
133
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.
134
+ currentData = queue .poll (); // get the best node from the queue
135
+ int currentPosition = currentData .getPath ().get (currentData .getPath ().size () - 1 ); // current node
136
+
137
+ // Check if the destination has been reached
181
138
if (currentPosition == to ) {
182
139
solutionFound = true ;
183
140
} else {
184
141
for (Edge edge : graph .getNeighbours (currentPosition )) {
185
- if (!currentData .getPath ().contains (edge .getTo ())) { // Avoid Cycles
142
+ // Avoid cycles by checking if the next node is already in the path
143
+ if (!currentData .getPath ().contains (edge .getTo ())) {
186
144
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.
145
+ updatedPath .add (edge .getTo ());
146
+
147
+ // Update the distance and heuristic for the new path
189
148
queue .add (new PathAndDistance (currentData .getDistance () + edge .getWeight (), updatedPath , heuristic [edge .getTo ()]));
190
149
}
191
150
}
192
151
}
193
152
}
194
153
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
197
154
}
198
155
}
0 commit comments