function route(map: RoadMap, start: Node, goal: Node) {const open = new MinHeap([start]), distance = new Map([[start, 0]]), parent = new Map();
while (open.size > 0) {// lowest distance so far
const current = open.pop();
if (current === goal) return rebuild(parent, goal);
for (const street of map.streetsFrom(current)) {const next = street.otherEnd(current);
const candidate = distance.get(current)! + street.metres;
if (candidate >= (distance.get(next) ?? Infinity)) continue;
distance.set(next, candidate); parent.set(next, current);
open.push(next, candidate);
}
}
}
Loading the street map…
Understanding Dijkstra on the real map
The idea
Dijkstra always closes the open intersection with the shortest driven distance from the start, whatever direction it lies in. Each closed intersection has its final distance; its streets are relaxed so that neighbours reached more cheaply get a new distance and a new parent.
With no idea where the goal is, the search fills a disc of the map that grows until the goal falls inside it. On a city grid that means closing several times more intersections than A*, yet the route is identical: both are exact, only the effort differs.
The four stages
Complexity
Versus its siblings
Pseudocode
ROUTE(map, start, goal)
open ← {start}; distance[start] ← 0while open not empty
current ← the open intersection with the lowest distance
if current = goal: return the route via parent
for each street leaving current, to neighbour
if distance[current] + street.metres < distance[neighbour]: update it, parent[neighbour] ← current, add neighbour to open
When to use
Pitfalls
History
The map is the centre of Cascavel, Paraná: 4 180 intersections and 5 438 street segments from OpenStreetMap, one-way streets respected, about 10 by 7 km. Every real routing engine runs this same loop on a graph a million times larger, with contraction hierarchies or landmarks precomputed so that a query touches only a sliver of it.