Homeβ€Ί DSAβ€Ί Eulerian Path and Circuit β€” Hierholzer's Algorithm

Eulerian Path and Circuit β€” Hierholzer's Algorithm

Where developers are forged. Β· Structured learning Β· Free forever.
πŸ“ Part of: Graphs β†’ Topic 16 of 17
Learn Eulerian paths and circuits.
βš™οΈ Intermediate β€” basic DSA knowledge assumed
In this tutorial, you'll learn:
  • Eulerian circuit exists iff: undirected β€” connected + all even degrees. Directed β€” strongly connected + in-degree = out-degree for all vertices. Check this before running Hierholzer.
  • Eulerian path (not circuit): exactly 2 odd-degree vertices in undirected (path goes between them), or exactly one source (+1 out) and one sink (+1 in) in directed.
  • Hierholzer O(E): start from any vertex, walk randomly until stuck. If stuck at start and all edges used β€” done. Otherwise find vertex on current path with unused edges, extend there.
✦ Plain-English analogy ✦ Real code with output ✦ Interview questions
⚑ Quick Answer
An Eulerian circuit visits every edge exactly once and returns to the start β€” like drawing a figure without lifting your pen and ending where you started. Euler proved in 1736 (the first graph theory result) that this is possible if and only if every vertex has even degree. Hierholzer's algorithm finds the circuit in O(E) time.

Euler's solution to the Seven Bridges of KΓΆnigsberg in 1736 is considered the founding paper of graph theory and one of the earliest proofs in discrete mathematics. The question was whether a walker could cross all seven bridges of KΓΆnigsberg exactly once and return to the start. Euler proved it was impossible β€” and in doing so invented the mathematical framework we now call graph theory.

The algorithm itself (Hierholzer's, 1873) is elegant: find a cycle, find a node on the cycle with unused edges, extend. The linear time O(E) complexity is achievable because each edge is traversed exactly once. In bioinformatics, Eulerian paths in de Bruijn graphs are how genome assemblers reconstruct DNA sequences from millions of short reads β€” perhaps the most important modern application of 230-year-old graph theory.

Existence Conditions

Undirected graph: - Eulerian circuit exists ↔ graph is connected AND every vertex has even degree - Eulerian path exists ↔ graph is connected AND exactly 0 or 2 vertices have odd degree (path goes from one odd-degree vertex to the other)

Directed graph: - Eulerian circuit exists ↔ strongly connected AND every vertex: in-degree = out-degree - Eulerian path exists ↔ weakly connected AND at most one vertex has out-degree - in-degree = 1 (start) AND at most one vertex has in-degree - out-degree = 1 (end)

euler_check.py Β· PYTHON
1234567891011121314
from collections import defaultdict

def has_eulerian_circuit(adj: dict) -> bool:
    # All vertices must have even degree
    return all(len(neighbours) % 2 == 0 for neighbours in adj.values())

def has_eulerian_path(adj: dict) -> bool:
    odd_degree = sum(1 for v in adj if len(adj[v]) % 2 != 0)
    return odd_degree == 0 or odd_degree == 2

# KΓΆnigsberg bridges β€” all 4 vertices have odd degree
konigsberg = {'A':['B','B','D'], 'B':['A','A','C','C'], 'C':['B','B','D'], 'D':['A','C']}
print(has_eulerian_circuit(konigsberg))  # False
print(has_eulerian_path(konigsberg))     # False β€” no Eulerian path!
β–Ά Output
False
False

Hierholzer's Algorithm β€” O(E)

  1. Start at any vertex (or an odd-degree vertex for Eulerian path)
  2. Walk randomly, never reusing edges, until stuck
  3. If stuck at start: done if all edges used; otherwise, find a vertex on the current circuit with unused edges
  4. Insert a new circuit from that vertex into the main circuit
  5. Repeat until all edges are used
hierholzer.py Β· PYTHON
1234567891011121314151617181920212223242526272829303132
from collections import defaultdict

def eulerian_circuit(adj_input: dict) -> list:
    """
    Find Eulerian circuit using Hierholzer's algorithm.
    adj_input: {vertex: [neighbours]} β€” will be modified
    """
    adj = defaultdict(list)
    for u, neighbours in adj_input.items():
        adj[u].extend(neighbours)

    # Check all vertices have even degree
    if not all(len(adj[v]) % 2 == 0 for v in adj):
        return []  # No Eulerian circuit

    start = next(iter(adj))
    stack = [start]
    circuit = []

    while stack:
        v = stack[-1]
        if adj[v]:
            u = adj[v].pop()
            adj[u].remove(v)  # remove reverse edge for undirected
            stack.append(u)
        else:
            circuit.append(stack.pop())

    return circuit[::-1]

adj = {0:[1,2], 1:[0,2], 2:[0,1]}
print(eulerian_circuit(adj))  # [0, 1, 2, 0] (triangle)
β–Ά Output
[0, 1, 2, 0]

The Seven Bridges of KΓΆnigsberg

Euler proved in 1736 that the city of KΓΆnigsberg (now Kaliningrad) has no Eulerian path. The city has 4 landmasses connected by 7 bridges. Each landmass has an odd number of bridges (3, 5, 3, 3). For an Eulerian path, at most 2 vertices can have odd degree. With 4 odd-degree vertices, neither an Eulerian path nor circuit exists.

This is the founding problem of graph theory.

Applications

  • DNA fragment assembly: Eulerian path in de Bruijn graphs reassembles genome sequences
  • Route planning: Postman problem β€” minimum edges to add to make graph Eulerian
  • Circuit design: Drawing PCB traces without lifting the pen
  • Puzzle solving: Draw-without-lifting-pen puzzles

🎯 Key Takeaways

  • Eulerian circuit exists iff: undirected β€” connected + all even degrees. Directed β€” strongly connected + in-degree = out-degree for all vertices. Check this before running Hierholzer.
  • Eulerian path (not circuit): exactly 2 odd-degree vertices in undirected (path goes between them), or exactly one source (+1 out) and one sink (+1 in) in directed.
  • Hierholzer O(E): start from any vertex, walk randomly until stuck. If stuck at start and all edges used β€” done. Otherwise find vertex on current path with unused edges, extend there.
  • The stack-based implementation avoids the recursion depth issues of the naive recursive approach. Use it in practice.
  • Bioinformatics: genome assembly treats DNA reads as edges in a de Bruijn graph. Assembling the genome = finding an Eulerian path. This is why Euler path algorithms are in production bioinformatics pipelines.

Interview Questions on This Topic

  • QState the necessary and sufficient conditions for an Eulerian circuit to exist.
  • QWhy did the KΓΆnigsberg bridge problem have no solution?
  • QExplain Hierholzer's algorithm and its time complexity.
  • QHow does an Eulerian path problem differ from a Hamiltonian path problem?

Frequently Asked Questions

What is the difference between Eulerian and Hamiltonian paths?

Eulerian path: visit every EDGE exactly once. Hamiltonian path: visit every VERTEX exactly once. Eulerian path has efficient O(E) solution. Hamiltonian path is NP-complete β€” no known polynomial algorithm.

πŸ”₯
Naren Founder & Author

Developer and founder of TheCodeForge. I built this site because I was tired of tutorials that explain what to type without explaining why it works. Every article here is written to make concepts actually click.

← PreviousMaximum Flow β€” Ford-Fulkerson and Edmonds-Karp AlgorithmNext β†’Articulation Points and Bridges in Graphs
Forged with πŸ”₯ at TheCodeForge.io β€” Where Developers Are Forged