A* Search
A* finds the shortest path by being smart about which way to look.
The idea
A* Search is an informed search that finds the cheapest path from start to goal. For each node it computes f(n) = g(n) + h(n): g is the real cost paid so far, and h is a heuristic guess of the cost still remaining. It always expands the waiting node with the smallest f, so it balances "how far I've come" with "how far I probably have to go" β giving the exactness of cost-based search with the speed of a good guess.
How it works
- Put the start node in OPEN (the frontier of nodes waiting to be expanded), with g=0 and f = g + h(start).
- CLOSED (already-expanded nodes) starts empty.
- Pick from OPEN the node with the smallest f(n) = g(n) + h(n). This is the node we expand next.
- If that node is the goal, stop β trace back the parent pointers to read off the shortest path.
- Otherwise move it from OPEN to CLOSED (it is now expanded and won't be revisited normally).
- Look at each neighbor: compute a tentative g = (g of current) + (edge cost to neighbor).
- If this path to the neighbor is cheaper than any we've seen, record it β set the neighbor's g, f = g + h, and parent β and place/update it in OPEN.
- Repeat from step 3 until the goal is expanded, or OPEN empties (meaning no path exists).
See it step by step
Watch A* Search search a real problem β flying from Sydney (SYD) to London (LHR). Click Next to advance one expansion and watch OPEN, the traversal, the path and the cost update live.

OPEN, CLOSED & the data structures
OPEN is a priority queue (min-heap) ordered by f(n) = g(n) + h(n), so the most promising node β lowest estimated total cost β always comes out first. CLOSED is a set of nodes already expanded; checking it prevents re-expanding the same node and wasting work. We also keep, per node, its best-known g cost and a parent pointer so we can rebuild the final path once the goal is reached.
Pseudocode
function A_STAR(start, goal, h):
g[start] = 0
f[start] = h(start)
OPEN = priority queue ordered by f # frontier
push start into OPEN
CLOSED = empty set # expanded nodes
while OPEN not empty:
current = node in OPEN with smallest f
if current == goal:
return reconstruct_path(current)
move current from OPEN to CLOSED
for each neighbor of current:
if neighbor in CLOSED: continue
tentative_g = g[current] + cost(current, neighbor)
if tentative_g < g[neighbor]: # a cheaper route found
parent[neighbor] = current
g[neighbor] = tentative_g
f[neighbor] = tentative_g + h(neighbor)
if neighbor not in OPEN: push neighbor into OPEN
return failure # OPEN empty, no path
At a glance
π When to use it
- You need the cheapest/shortest path and have a reasonable heuristic (e.g. straight-line distance).
- You want the guarantees of cost-based search but faster, by steering toward the goal.
- Graphs like maps, grids, and game pathfinding where distances estimate well.
- Memory is available β A* trades memory for speed and optimality.
β οΈ Watch out for
- If h overestimates (is not admissible), A* can miss the optimal path β it may return a good-but-not-shortest route.
- It is memory-heavy: OPEN and CLOSED can grow huge, so it can run out of memory on very large graphs.
- A neighbor already in OPEN may need updating (relaxation) when a cheaper route is found β don't just skip it.
- With h(n)=0 everywhere, A* degrades into Uniform-Cost Search (slower but still optimal); a poor heuristic loses A*'s speed advantage.
Now see it for yourself
Open A* Search in the visualizer β step through it, pause, and watch OPEN & CLOSED change.