Discrete Mathsfor Engineers

Structures, proofs, and intuition

EN | PT

Depth-First Search (DFS)

Part 3 — The Algorithm (CLRS Pseudocode)

Series: Depth-First Search (DFS) Part 3 of 8

3. The Algorithm


Roadmap (what you will learn in this part):
  1. The state maintained by DFS
  2. The role of colors and parent pointers
  3. The global DFS procedure
  4. The recursive DFS-VISIT procedure
  5. Discovery and finish times
  6. Why DFS may produce a forest

In this part, we formalize Depth-First Search using the classical presentation from Introduction to Algorithms (CLRS).

DFS is not just an intuition about “going deep”. It is a precise graph traversal procedure with well-defined state, recursion structure, and timestamps.

3.1 State Maintained by DFS

For each vertex u ∈ V, DFS stores:

  • color[u] — exploration state
  • π[u] — predecessor (parent) in the DFS tree
  • d[u] — discovery time
  • f[u] — finish time

These values allow DFS to do much more than just traverse the graph. They encode structural information that will be essential later for edge classification, cycle detection, and topological sorting.

3.2 The Meaning of Colors

Color Meaning
WHITE The vertex has not been discovered yet.
GRAY The vertex has been discovered but is still being explored.
BLACK The vertex and all its reachable descendants have been fully explored.
Interpretation: GRAY means “currently active in the recursion stack”.

3.3 Main Procedure — DFS

The global DFS procedure initializes all vertices and then scans the graph. If it finds a WHITE vertex, it starts a new DFS tree rooted at that vertex.

DFS(G):

    for each vertex u in V[G]:
        color[u] = WHITE
        π[u] = NIL

    time = 0

    for each vertex u in V[G]:
        if color[u] == WHITE:
            DFS-VISIT(G, u)
Important: If the graph is disconnected, DFS will produce a DFS forest, not just a single tree.

3.4 Recursive Procedure — DFS-VISIT

The real exploration happens inside the recursive subroutine:

DFS-VISIT(G, u):

    time = time + 1
    d[u] = time
    color[u] = GRAY

    for each v in Adj[u]:
        if color[v] == WHITE:
            π[v] = u
            DFS-VISIT(G, v)

    color[u] = BLACK
    time = time + 1
    f[u] = time

This procedure captures the full deep-exploration logic: discover a vertex, recursively visit unvisited neighbors, and only then finish the current vertex.

3.5 Discovery and Finish Times

DFS assigns two timestamps to every vertex:

  • d[u] — when u is first discovered
  • f[u] — when the exploration of u is complete

These timestamps are one of the most important features of DFS. They turn a traversal into a structural analysis tool.

Later, the interval [d[u], f[u]] will let us reason about ancestry, nesting, and edge types.

3.6 Parent Pointers and DFS Trees

Whenever DFS discovers a WHITE vertex v from a vertex u, it sets:

π[v] = u

These parent pointers define the DFS tree rooted at the vertex that started the exploration.

If the graph has multiple disconnected regions, DFS builds a collection of trees, called a DFS forest.

3.7 Why DFS May Produce a Forest

DFS starts a new recursive exploration every time it encounters a vertex that is still WHITE in the outer loop.

Therefore:

  • If the graph is fully reachable from a single source, DFS produces one tree.
  • If the graph has multiple disconnected components, DFS produces multiple trees.
Conclusion: the complete DFS output is, in general, a forest.

Next: Part 4 — Structural Properties & Discovery Times

Now that the algorithm is fully defined, the next step is to understand the structural meaning of its timestamps and recursion.

In Part 4, we study discovery times, finish times, nesting intervals, and the parenthesis-style structure generated by DFS.