You are viewing a free preview of this lesson.
Subscribe to unlock all 10 lessons in this course and every other course on LearningBro.
A* (pronounced "A-star") is an informed search algorithm: it finds the shortest path between a start and a goal vertex, but unlike Dijkstra's algorithm it uses extra knowledge about where the goal is to steer the search towards it rather than groping outwards in every direction. That extra knowledge is supplied by a heuristic function h(n), an estimate of how far each vertex is from the goal. By combining the known cost of getting to a vertex with the estimated cost of getting from it to the goal, A* concentrates its effort along promising routes and so typically examines far fewer vertices than Dijkstra's while still — given a sensible heuristic — returning the genuinely shortest path. It is the workhorse of game-AI pathfinding, robotics and route planning. At A-Level you must understand the formula f(n)=g(n)+h(n), the meaning and importance of an admissible heuristic, why A* expands fewer nodes than Dijkstra's, and how to trace a small example.
This lesson addresses AQA A-Level Computer Science (7517), Section 4.3 Fundamentals of algorithms, specifically 4.3.6 Optimisation algorithms (A* search). The specification requires you to understand how A* finds the shortest path, the role of the cost function f(n)=g(n)+h(n), and the contrast with Dijkstra's algorithm. It builds directly on Dijkstra's algorithm (4.3.6) — A* is Dijkstra's with a heuristic added — on priority queues (4.2.4) for the open set, on graphs (4.2.6) for the search space, and on the idea of a heuristic from the optimisation/intractability strand (4.4.4 / 4.3.6). The admissibility analysis uses the complexity and optimality reasoning of 4.4.4.
Dijkstra's algorithm finalises vertices strictly in order of their distance from the source. With no notion of which direction the goal lies in, it expands outwards uniformly — like a circular ripple — and so finalises many vertices that lie away from the goal before it ever reaches it. On a large map that is a great deal of wasted exploration.
A* fixes this by ranking each candidate vertex n not by how far it is from the start, but by an estimate of the total cost of the whole journey that passes through it:
f(n)=g(n)+h(n).
| Component | Meaning | Known or estimated? |
|---|---|---|
| g(n) | The actual cost of the best path found so far from the start to n | Known (computed by relaxation, exactly as in Dijkstra's) |
| h(n) | The heuristic estimate of the cost from n onward to the goal | Estimated (a problem-specific guess) |
| f(n) | The estimated total cost of the cheapest path from start to goal through n | Derived: g(n)+h(n) |
At each step A* expands the open-set vertex with the lowest f(n). The g term keeps it honest about cost already incurred; the h term pulls it towards the goal. The interplay of the two is the whole algorithm.
The heuristic is an estimate of the remaining distance from a vertex to the goal — cheap to compute, never actually traversing the graph. Its quality determines how well A* performs, and one property of it determines whether A* is even correct: admissibility.
A heuristic is admissible if it never overestimates the true remaining cost: for every vertex n, h(n)≤h∗(n), where h∗(n) is the real shortest distance from n to the goal. If the heuristic is admissible, A* is guaranteed to return the optimal (shortest) path. Intuitively, an admissible heuristic is optimistic — it may say "the goal looks close" when it is actually far, but it never wrongly says "the goal is far" about a vertex that is in fact close, and it is that one-sided honesty that stops A* from discarding the true best route.
| Heuristic | Formula | When to use |
|---|---|---|
| Manhattan distance | h=∣x1−x2∣+∣y1−y2∣ | Movement restricted to 4 directions (up, down, left, right) |
| Euclidean distance | h=(x1−x2)2+(y1−y2)2 | Movement allowed in any direction (including diagonals) |
| Zero heuristic | h(n)=0 | Makes A* behave identically to Dijkstra's algorithm |
The Manhattan distance is admissible for 4-directional movement because, when you can only step along grid lines, the true shortest distance can never be less than the sum of the horizontal and vertical gaps — so the estimate never exceeds the truth. The zero heuristic is trivially admissible (it never overestimates anything), which is exactly why setting h(n)=0 recovers Dijkstra's algorithm: with no goal-direction information, A* ranks purely by g(n), the distance from the source.
Key Insight: h(n)=0 for all n turns A* into Dijkstra's algorithm. The heuristic is the only thing that makes A* "smarter": it is what focuses the search towards the goal. The closer h is to the true remaining cost (without ever exceeding it), the more sharply focused — and faster — A* becomes.
PROCEDURE AStar(graph, start, goal, h)
openSet = priority queue ordered by f value // frontier to explore
closedSet = empty set // already finalised
g[start] = 0
f[start] = h(start, goal)
ADD start TO openSet
WHILE openSet IS NOT EMPTY
current = vertex in openSet with the LOWEST f value // extract-min
IF current = goal THEN
RECONSTRUCT path via previous[] from start to goal
RETURN path
END IF
REMOVE current FROM openSet
ADD current TO closedSet
FOR EACH neighbour OF current
IF neighbour IN closedSet THEN
CONTINUE
END IF
tentativeG = g[current] + weight(current, neighbour)
IF neighbour NOT IN openSet THEN
ADD neighbour TO openSet
ELSE IF tentativeG >= g[neighbour] THEN
CONTINUE // existing route is no worse
END IF
previous[neighbour] = current
g[neighbour] = tentativeG
f[neighbour] = g[neighbour] + h(neighbour, goal)
END FOR
END WHILE
RETURN "No path found"
END PROCEDURE
Compare this with the Dijkstra pseudocode of the previous lesson: the structure is identical (an open priority queue, relaxation of neighbours, a closed set of finalised vertices). The only difference is the key used to order the open set — f=g+h here versus g alone in Dijkstra's. That one change is the entire content of "A* = Dijkstra + heuristic".
Consider a 3×4 grid. S is the start, G the goal, and # a wall that cannot be entered. Movement is 4-directional and each step costs 1. We use the Manhattan distance to the goal as the heuristic.
| row \ col | 0 | 1 | 2 | 3 |
|---|---|---|---|---|
| 0 | S | . | . | . |
| 1 | . | # | # | . |
| 2 | . | . | . | G |
Coordinates are (row,col), so S=(0,0) and G=(2,3). The Manhattan heuristic from a cell (r,c) is h=∣r−2∣+∣c−3∣.
We show the open set (as cell: g, h, f) and the closed set at each step. The cell extracted each round is the open-set cell with the smallest f (ties broken by larger g, then arbitrarily — a common tie-break that favours cells nearer the goal).
S=(0,0): g=0, h=∣0−2∣+∣0−3∣=2+3=5, so f=5.
| Open set | Closed set |
|---|---|
| (0,0): g0 h5 f5 | { } |
Neighbours of (0,0) that are not walls: (0,1) and (1,0).
| Open set | Closed set |
|---|---|
| (0,1): g1 h4 f5, (1,0): g1 h4 f5 | {(0,0)} |
Both open cells have f=5; the tie-break (prefer larger g, then towards the goal) selects (0,1). Its non-wall, non-closed neighbours: (0,2). ((1,1) is a wall.)
| Open set | Closed set |
|---|---|
| (1,0): g1 h4 f5, (0,2): g2 h3 f5 | {(0,0), (0,1)} |
Neighbours: (0,3). ((1,2) is a wall.)
| Open set | Closed set |
|---|---|
| (1,0): g1 h4 f5, (0,3): g3 h2 f5 | {(0,0), (0,1), (0,2)} |
Neighbours: (1,3).
| Open set | Closed set |
|---|---|
| (1,0): g1 h4 f5, (1,3): g4 h1 f5 | {(0,0), (0,1), (0,2), (0,3)} |
Neighbours: (2,3)=G.
| Open set | Closed set |
|---|---|
| (1,0): g1 h4 f5, (2,3): g5 h0 f5 | {(0,0), (0,1), (0,2), (0,3), (1,3)} |
The goal is extracted. A* terminates and reconstructs the path through the previous pointers:
S(0,0)→(0,1)→(0,2)→(0,3)→(1,3)→G(2,3),total cost =5.
Look at the closed set: A* finalised only the cells along the top edge and down the right side — the cells the heuristic identified as lying on the way to the goal. Crucially, cell (1,0) entered the open set in step 2 but was never expanded: its f=5 tied, but the tie-break consistently preferred cells with larger g (further along a committed route towards the goal), so the bottom-left region was left unexplored. Dijkstra's algorithm, ranking purely by g, would have had no reason to prefer the goal-ward cells and would have expanded (1,0) and the whole left/bottom region too. That difference — leaving provably-irrelevant regions unexplored — is the precise sense in which A* expands fewer nodes than Dijkstra's.
Note also that every cell on the discovered path had f=5, equal to the true optimal cost. This is no accident: along an optimal path computed with an admissible (here, consistent) heuristic, f stays constant and equal to the optimum, because each unit of g gained is matched by a unit of h lost as you step closer to the goal.
| Feature | Dijkstra's | A* |
|---|---|---|
| Uses a heuristic? | No | Yes — h(n) |
| Ranks open vertices by | g(n) (distance from source) | f(n)=g(n)+h(n) (estimated total) |
| Direction of exploration | Outwards in all directions equally | Preferentially towards the goal |
| Optimal path? | Yes (non-negative weights) | Yes (iff h is admissible) |
| Vertices expanded | More (no goal awareness) | Fewer (guided by h) |
| When h(n)=0 | — | Degenerates exactly to Dijkstra's |
| Worst-case time | O(V2) or O((V+E)logV) | Same worst case; far fewer expansions in practice |
The key examiner point is that A*'s advantage is practical, not asymptotic: in the worst case (e.g. a useless heuristic, or a maze that thwarts every guess) A* explores as much as Dijkstra's, so the Big-O is the same. The win is that a good heuristic prunes huge swathes of the graph that Dijkstra's would needlessly examine.
Two related-but-distinct properties govern A*'s behaviour, and confusing them is a common slip.
| Property | Definition | Effect on A* |
|---|---|---|
| Admissible | h(n) never overestimates the true remaining cost: h(n)≤h∗(n) | Guarantees A* returns the optimal path |
| Consistent (monotone) | For every edge (n,m): h(n)≤cost(n,m)+h(m) | A* never needs to re-open a closed vertex, so it is more efficient |
Every consistent heuristic is automatically admissible, but not every admissible heuristic is consistent. Consistency is a "triangle-inequality" condition: the estimate from n must not exceed the cost of stepping to a neighbour m plus the estimate from m. When it holds, the f values encountered along any path never decrease, which is what lets A* finalise a vertex on first extraction and never revisit it (just like Dijkstra's). The Manhattan distance is both admissible and consistent for uniform-cost 4-directional grids, which is why the trace above never had to re-open a closed cell.
| Application | Detail |
|---|---|
| Video-game pathfinding | NPCs navigate around obstacles on a game map; A* is the de-facto standard because it is fast and gives natural-looking routes |
| Robotics | Mobile robots plan collision-free paths through a mapped physical environment |
| Route planning | Sat-navs use A* variants (with straight-line distance as the heuristic) for journey planning |
| Puzzle solving | Sliding puzzles such as the 8-/15-puzzle, using "number of misplaced tiles" or "sum of tile distances" as an admissible heuristic |
Exam Tip: A frequent question asks you to explain the difference between Dijkstra and A*, or why A* is more efficient. The full-mark answer is: A* adds a heuristic h(n) that estimates the remaining cost to the goal, so it ranks vertices by f(n)=g(n)+h(n) and explores towards the goal, expanding fewer vertices; and provided h is admissible (never overestimates) the path it returns is still optimal. State both halves — the efficiency gain and the admissibility condition for optimality — to secure all the marks.
Subscribe to continue reading
Get full access to this lesson and all 10 lessons in this course.