A* Search: Heuristics, Admissibility and When It Beats Dijkstra

Dijkstra explores outward evenly in every direction. When you know where the goal is, that's wasteful. A* adds a heuristic estimate of the remaining distance so the search leans toward the target.

The priority

Each node gets f(n) = g(n) + h(n): g is the known cost from the start, and h estimates the cost to the goal. A* always expands the node with the smallest f.

import heapq

def astar(start, goal, neighbors, h):
    g = {start: 0}
    pq = [(h(start), start)]
    while pq:
        f, u = heapq.heappop(pq)
        if u == goal:
            return g[u]
        if f > g[u] + h(u):
            continue                       # stale entry
        for v, w in neighbors(u):
            ng = g[u] + w
            if ng < g.get(v, float("inf")):
                g[v] = ng
                heapq.heappush(pq, (ng + h(v), v))
    return None

Admissible and consistent heuristics

With h = 0, A* is exactly Dijkstra. With a perfect h, it walks straight to the goal.

Grid heuristics

Using Euclidean distance on a 4-directional grid is still admissible but weaker, so it expands more nodes; using Manhattan on an 8-directional grid overestimates and breaks optimality.

Interview talking points

One-liner: "A* is Dijkstra ordered by g + h; with an admissible, consistent heuristic it stays optimal while exploring far fewer nodes."


Disclosure: from the team behind Linkjob AI interview copilot.