function bidirectionalBfs(grid: Grid, start: Cell, goal: Cell) { const front = { ring: [start], parent: new Map([[start, null]]) }, back = { ring: [goal], parent: new Map([[goal, null]]) }; while (front.ring.length > 0 && back.ring.length > 0) {const meeting = expand(grid, front, back); // one ring from the start side
if (meeting) return join(front.parent, back.parent, meeting);
const met = expand(grid, back, front); // one ring from the goal side
if (met) return join(front.parent, back.parent, met);
}
return null;
}
function expand(grid: Grid, side: Side, other: Side) { for (const current of side.ring.splice(0)) { for (const neighbor of neighbors(grid, current)) {if (side.parent.has(neighbor)) continue;
side.parent.set(neighbor, current); side.ring.push(neighbor);
if (other.parent.has(neighbor)) return neighbor;
}
}
return null;
}
Two searches: one from the start (12, 1), one from the goal (5, 42). They take turns growing one ring each.
Understanding Bidirectional BFS
The idea
Bidirectional search runs two breadth-first searches at once, one from the start and one from the goal, growing one ring each in turn. The moment a cell is reached by both, the two parent chains join through it and form a shortest path.
The saving comes from geometry. A single BFS to distance d fills a disc of about d² cells; two searches to distance d/2 fill two discs of (d/2)² each, half the area in total. On graphs with high branching the saving is exponential: b^(d/2) instead of b^d.
The four stages
Complexity
Versus its siblings
Pseudocode
BIDIRECTIONALBFS(start, goal)
front ← BFS state from start; back ← BFS state from goal
repeat
grow front by one ring; if it touches a cell back has reached: join the two parent chains there
grow back by one ring; same check
until either side has no ring left: no path
When to use
Pitfalls
History
Ira Pohl analysed bidirectional search in his 1969 thesis and 1971 paper, and it has been standard in route planning ever since: contraction hierarchies and hub labels, the engines behind today's map services, run a bidirectional Dijkstra at their core.