A* Algorithm
The best of both worlds
Combining Distance and Direction
Dijkstra's algorithm finds the shortest path, but it explores blindly—expanding outward in all directions like ripples in a pond. What if we could give it a sense of direction? What if we could tell it: "The goal is over there"?
This is exactly what A* (pronounced "A-star") does. It combines the proven optimality of Dijkstra with the efficiency of goal-directed search.
The magic formula is deceptively simple:
Let's unpack each term:
- is the actual cost from the start to node . This is what Dijkstra uses—the distance we've measured by actually traversing the graph.
- is the estimated cost from to the goal. This is the heuristic—our best guess at how far we still need to go.
- is the total estimated cost of the cheapest path through . We prioritize exploring nodes with the lowest .
Think of it this way: tells us what we know (how far we've come), and tells us what we believe (how far we have to go). Together, they guide us toward the goal while still ensuring we find the optimal path.
A* is Dijkstra with a sense of direction.
Why This Works
Consider how Dijkstra expands its search. Starting from the origin, it explores all nodes at distance 1, then all nodes at distance 2, and so on. The frontier forms concentric circles around the start—expanding uniformly in every direction, even directions that lead away from the goal.
A* changes this by biasing the search toward the goal. Instead of expanding in perfect circles, A* stretches its frontier into an ellipse oriented toward the destination. Nodes that are both close to the start and close to the goal get explored first.
Interactive: How Search Frontiers Differ
(circular frontier)
(elliptical frontier)
With no obstacles, Dijkstra expands in perfect circles. A* stretches toward the goal, creating an elliptical frontier that reaches the target faster.
Watch how Dijkstra's frontier expands as a circle while A*'s frontier stretches toward the goal. This focused exploration is why A* often visits far fewer nodes.
The key insight is that the heuristic pulls the search toward the goal without sacrificing correctness. As long as the heuristic never overestimates the true cost (we call this admissible), A* will always find the optimal path.
A* in Action
Let's watch A* navigate through a grid with obstacles. Notice how it explores nodes preferentially in the direction of the goal, while still considering the actual distances traveled.
Interactive: A* Step-by-Step
Click explored cells to see their f, g, h values. Click empty cells to toggle walls. Drag start (S) and end (E) to reposition them.
Click on any cell to see its , , and values. The priority queue orders cells by their value—lower means the cell gets explored sooner.
Pay attention to the frontier shape. Unlike BFS or Dijkstra, A*'s frontier isn't symmetric. It bulges toward the goal, exploring the most promising paths first.
Understanding F, G, and H
Each cell in an A* search carries three values. Understanding what each one means is crucial for intuition.
Interactive: Click Cells to See F, G, H Values
Click any explored cell to see its detailed f, g, h breakdown. Notice how cells on the optimal path have the lowest f values.
- g (green): The shortest known distance from the start. This is measured, not estimated.
- h (blue): The heuristic estimate to the goal. With Manhattan distance, this is .
- f (purple): The sum . Cells with lower are explored first.
Notice how cells near the start have low but high , while cells near the goal have high but low . The cells along the optimal path tend to have the lowest values.
A* vs Dijkstra: The Showdown
How much difference does that heuristic make? Let's find out by running both algorithms side-by-side on terrain with varying costs.
Interactive: A* vs Dijkstra Side-by-Side
Click cells to toggle walls. Both algorithms start and end at the same positions. Watch how A* focuses its search toward the goal while Dijkstra expands uniformly.
Both algorithms find the same optimal path—that's guaranteed when the heuristic is admissible. But look at the node counts. A* typically explores far fewer cells because it doesn't waste time searching in the wrong direction.
This is the power of informed search. By incorporating knowledge about where we want to go, we can dramatically reduce the work needed to get there.
The Algorithm
Here is A* in pseudocode:
A*(graph, start, goal, heuristic):
open_set ← priority queue ordered by f(n)
closed_set ← empty set
g_score ← map with default value ∞
parent ← empty map
g_score[start] ← 0
f_score[start] ← heuristic(start, goal)
add start to open_set with priority f_score[start]
parent[start] ← null
while open_set is not empty:
current ← extract node with lowest f from open_set
if current = goal:
return reconstruct_path(parent, goal)
add current to closed_set
for each neighbor of current:
if neighbor in closed_set:
continue
tentative_g ← g_score[current] + cost(current, neighbor)
if tentative_g < g_score[neighbor]:
parent[neighbor] ← current
g_score[neighbor] ← tentative_g
f_score[neighbor] ← tentative_g + heuristic(neighbor, goal)
if neighbor not in open_set:
add neighbor to open_set with priority f_score[neighbor]
return "no path found"The structure is nearly identical to Dijkstra's algorithm. The only difference is how we prioritize nodes: Dijkstra uses alone, while A* uses .
When to use A* vs Dijkstra:
- Use A* when you have a single target and a good heuristic. It will find the optimal path faster.
- Use Dijkstra when you need shortest paths to all nodes, or when no good heuristic exists.
Visualizing in 3D
Pathfinding isn't limited to flat grids. On terrain with hills and valleys, the cost of traversal varies with elevation. Watch A* navigate a 3D landscape, finding the optimal path that balances distance and elevation change.
Interactive: A* on 3D Terrain
Drag to rotate the view. Taller columns represent higher terrain cost. A* finds the optimal path balancing distance and elevation.
Drag to rotate the view. Notice how the search naturally avoids steep climbs when a gentler path exists nearby.
Key Takeaways
- A* combines actual distance () with heuristic estimate () into a total score
- The priority queue orders nodes by —lowest total estimated cost first
- A* explores fewer nodes than Dijkstra while still finding the optimal path
- An admissible heuristic (one that never overestimates) guarantees optimality
- A* is the most widely used pathfinding algorithm in games, robotics, and navigation systems
- The algorithm stretches its frontier toward the goal, creating an elliptical rather than circular search pattern