BFS
Dijkstra's Algorithm
Shortest Path
Graph Theory
Algorithm Comparison

What is difference between BFS and Dijkstra's algorithms when looking for shortest path?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

BFS and Dijkstra are both shortest-path algorithms, but they solve different versions of the problem. BFS is correct when every edge has the same cost, while Dijkstra is needed when edges have non-negative but different weights.

What BFS Actually Optimizes

Breadth-first search explores a graph level by level. In an unweighted graph, each edge counts as one step, so the first time BFS reaches a node, it has found a path with the minimum number of edges.

That is why BFS works perfectly for:

  • mazes where every move costs the same
  • social-network “degrees of separation” problems
  • shortest path in a graph where each edge weight is effectively 1

Its data structure is just a queue, and its time complexity is O(V + E).

What Dijkstra Adds

Dijkstra solves the harder problem where edges have different non-negative costs. Instead of exploring strictly by edge count, it always expands the node with the smallest currently known distance.

That requires a priority queue rather than a plain FIFO queue.

If one road costs 1 and another costs 100, BFS treats them as equally good because both are one hop. Dijkstra does not. It chooses paths based on total weight.

With a binary heap, Dijkstra usually runs in O((V + E) log V).

A Small Example

Consider this graph:

  • 'A -> B with cost 1'
  • 'A -> C with cost 5'
  • 'B -> C with cost 1'

BFS sees A -> C as a one-edge path and may treat it as shortest by hop count. Dijkstra correctly prefers A -> B -> C because its total cost is 2, which is less than 5.

That example is the entire distinction in practice: BFS minimizes hops, Dijkstra minimizes summed weight.

Runnable Python Examples

Here is a compact BFS implementation for an unweighted graph:

python
1from collections import deque
2
3
4def bfs_shortest_path(graph, start, goal):
5    queue = deque([(start, [start])])
6    visited = {start}
7
8    while queue:
9        node, path = queue.popleft()
10        if node == goal:
11            return path
12        for neighbor in graph[node]:
13            if neighbor not in visited:
14                visited.add(neighbor)
15                queue.append((neighbor, path + [neighbor]))
16
17    return None
18
19
20graph = {
21    "A": ["B", "C"],
22    "B": ["D"],
23    "C": ["D"],
24    "D": [],
25}
26
27print(bfs_shortest_path(graph, "A", "D"))

And here is Dijkstra for weighted graphs:

python
1import heapq
2
3
4def dijkstra(graph, start, goal):
5    heap = [(0, start, [start])]
6    best = {start: 0}
7
8    while heap:
9        distance, node, path = heapq.heappop(heap)
10        if node == goal:
11            return distance, path
12        if distance > best.get(node, float("inf")):
13            continue
14        for neighbor, weight in graph[node]:
15            new_distance = distance + weight
16            if new_distance < best.get(neighbor, float("inf")):
17                best[neighbor] = new_distance
18                heapq.heappush(heap, (new_distance, neighbor, path + [neighbor]))
19
20    return None
21
22
23weighted_graph = {
24    "A": [("B", 1), ("C", 5)],
25    "B": [("C", 1)],
26    "C": [],
27}
28
29print(dijkstra(weighted_graph, "A", "C"))

A Useful Mental Model

You can think of BFS as a special case of Dijkstra where every edge weight is identical. In that case, the priority queue is unnecessary because all frontier nodes at the same depth have equal cost, so a normal queue is enough.

That mental model helps you choose correctly:

  • all edges equal, use BFS
  • non-negative varying weights, use Dijkstra
  • negative weights, use neither; use Bellman-Ford or another algorithm designed for them

Common Pitfalls

The most common mistake is using BFS on a weighted graph because it “looks simpler.” If edge weights differ, BFS can return the wrong answer.

Another mistake is using Dijkstra on graphs with negative edge weights. The algorithm assumes once a shortest tentative distance is finalized, it stays final. Negative edges break that assumption.

A third mistake is thinking Dijkstra is always too expensive. On many practical sparse graphs it is fast enough, and correctness matters more than avoiding a priority queue.

Summary

  • BFS finds shortest paths by number of edges, not by total weight.
  • Dijkstra finds minimum-weight paths when all edge weights are non-negative.
  • BFS is effectively Dijkstra specialized to unit-cost edges.
  • If weights differ, BFS can be wrong even when it finds a path quickly.
  • If negative weights exist, switch to an algorithm built for that case.

Course illustration
Course illustration

All Rights Reserved.