Routing Algorithms
Shortest Path
Graph Theory
Path Optimization
Navigation

Calculating the shortest route between two points

Master System Design with Codemia

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

Introduction

Calculating the shortest route between two points is a standard graph optimization problem used in navigation, logistics, and networking. The algorithm you should use depends on graph properties such as weight sign, density, and whether a good heuristic exists. Getting the data model right is usually more important than clever algorithm code.

Model the Route as a Weighted Graph

Represent each location as a node and each possible movement as an edge with numeric cost. Cost might mean distance, travel time, toll-adjusted score, or energy use.

The algorithm can only optimize the cost you provide. If costs mix incompatible units, shortest output may be operationally wrong.

Key modeling decisions:

  • directed graph for one-way roads
  • undirected graph for bidirectional movement
  • static versus frequently changing edge weights
  • one-off query versus many repeated queries

These decisions influence algorithm selection and caching strategy.

Dijkstra for Non-Negative Edge Weights

Dijkstra is the default choice when all edge weights are non-negative. It uses a priority queue and always expands the currently cheapest known frontier.

python
1import heapq
2
3
4def dijkstra(graph, start, target):
5    pq = [(0, start)]
6    dist = {start: 0}
7    prev = {}
8
9    while pq:
10        cost, node = heapq.heappop(pq)
11
12        if node == target:
13            break
14
15        if cost > dist[node]:
16            continue
17
18        for nxt, w in graph.get(node, []):
19            new_cost = cost + w
20            if new_cost < dist.get(nxt, float("inf")):
21                dist[nxt] = new_cost
22                prev[nxt] = node
23                heapq.heappush(pq, (new_cost, nxt))
24
25    return dist, prev
26
27
28def path_from_prev(prev, start, target):
29    if target != start and target not in prev:
30        return []
31    path = [target]
32    while path[-1] != start:
33        path.append(prev[path[-1]])
34    path.reverse()
35    return path
36
37
38graph = {
39    "A": [("B", 2), ("C", 5)],
40    "B": [("C", 1), ("D", 4)],
41    "C": [("D", 1)],
42    "D": []
43}
44
45dist, prev = dijkstra(graph, "A", "D")
46print("cost", dist.get("D"))
47print("path", path_from_prev(prev, "A", "D"))

This gives both shortest cost and actual route sequence.

A-Star When You Have a Good Heuristic

If nodes have coordinates or spatial structure, A-star can be faster by guiding search toward the target. It extends Dijkstra with heuristic score.

The heuristic must not overestimate true remaining cost if you need guaranteed optimal paths.

python
1import heapq
2import math
3
4
5def astar(graph, coords, start, goal):
6    def h(node):
7        x1, y1 = coords[node]
8        x2, y2 = coords[goal]
9        return math.hypot(x2 - x1, y2 - y1)
10
11    pq = [(h(start), 0, start)]
12    dist = {start: 0}
13    prev = {}
14
15    while pq:
16        _, g, node = heapq.heappop(pq)
17        if node == goal:
18            break
19
20        for nxt, w in graph.get(node, []):
21            ng = g + w
22            if ng < dist.get(nxt, float("inf")):
23                dist[nxt] = ng
24                prev[nxt] = node
25                heapq.heappush(pq, (ng + h(nxt), ng, nxt))
26
27    return dist, prev

A-star usually explores fewer nodes than Dijkstra when heuristic quality is good.

Route Computation in Real Systems

Real route engines need more than one shortest-path call. Practical requirements often include:

  • dynamic traffic updates changing edge weights
  • turn restrictions and forbidden segments
  • multiple alternative routes
  • latency budgets under heavy concurrency

For repeated queries on mostly static maps, preprocessing techniques can reduce per-query cost. For rapidly changing networks, fast recomputation with incremental updates is often simpler.

Always keep route result deterministic under equal costs if downstream systems depend on stable output.

Validation and Operational Safeguards

Shortest-path code often fails due to graph data quality issues.

Add checks for:

  • start and target existence
  • unreachable target handling with clear output
  • non-negative edge assumptions for Dijkstra
  • route reconstruction consistency

Log metadata such as visited node count and elapsed computation time. These signals help diagnose both performance regressions and malformed inputs.

Common Pitfalls

Running Dijkstra with negative edges can produce invalid results.

Using inconsistent cost units across edges creates routes that optimize the wrong objective.

Returning only route cost without path sequence makes results less useful for clients.

Ignoring unreachable-node cases leads to ambiguous failures in production flows.

Summary

  • Model routing as a weighted graph with one consistent cost definition.
  • Use Dijkstra for non-negative weights and A-star when a good heuristic exists.
  • Return both shortest cost and reconstructed path.
  • Validate graph assumptions explicitly to avoid silent errors.
  • Monitor runtime metrics so route quality and performance stay predictable.

Course illustration
Course illustration

All Rights Reserved.