Depth-First Search (DFS) and Depth-First Traversal

In short: Depth-first search (DFS) is an algorithm for traversing a tree or graph that goes as deep as possible down one path before backtracking to try another. It uses a stack (or recursion), runs in O(V + E) time, and powers cycle detection, topological sorting, and backtracking.

Depth-first search (DFS) is an algorithm for exploring a tree or graph. It goes as deep as possible down one path before backing up and trying a different one, using a stack (often just the call stack, via recursion) to remember where to back up to. Since it visits every node and edge once, it takes O(V + E) time.

On a graph On a tree
time O(V + E) O(n)
space O(V) O(h)

V is the number of nodes (vertices) and E is the number of edges in the graph. n is the number of nodes in the tree, and h is its height.

Depth-first search is like walking through a corn maze. You explore one path, hit a dead end, and go back and try a different one.

Here's how a DFS would traverse this tree, starting with the root:

A 4-row binary tree represented by circles connected with lines. Our depth-first search has us start at the root node at the top of the tree.

We'd go down the first path we find until we hit a dead end:

The same binary tree with all nodes in the leftmost branch bolded after being visited.

Then we'd do the same thing again—go down a path until we hit a dead end:

Then we do the same thing again: head down the next leftmost path until we reach a dead end.

And again:

And again.

And again:

Until we've visited every node in the tree.

Until we reach the end.

How DFS Works

  1. Start at a node and mark it as visited.
  2. Pick a neighbor you haven't visited yet, and run a DFS from there.
  3. When a node has no unvisited neighbors left, back up to the node you came from and keep going.

Here's a recursive implementation that returns the nodes in the order the search visits them:

import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; public static List<String> depthFirstSearch(Map<String, String[]> graph, String startNode) { // graph is a map: // key: a node // value: an array of the node's neighbors Set<String> visited = new HashSet<>(); List<String> visitOrder = new ArrayList<>(); visit(startNode, graph, visited, visitOrder); return visitOrder; } private static void visit(String node, Map<String, String[]> graph, Set<String> visited, List<String> visitOrder) { visited.add(node); visitOrder.add(node); // go as deep as we can down each unvisited neighbor for (String neighbor : graph.get(node)) { if (!visited.contains(neighbor)) { visit(neighbor, graph, visited, visitOrder); } } }

The visited hash set is what keeps a DFS from going around in circles forever when a graph has a cycle. (In a tree, there's only one path to each node, so you can skip it.) You can also write a DFS without recursion, by pushing nodes onto your own stack. That's handy when the graph is so deep that recursion would overflow the call stack.

DFS vs. BFS

Depth-first search is often compared with breadth-first search (BFS), which explores the graph level by level instead:

DFS BFS
Explores As deep as possible down one path, then backs up All nodes one step away, then two steps away, and so on
Uses a Stack (or recursion) Queue
Time O(V + E) O(V + E)
Extra space on a tree O(h), for the height of the tree O(w), for the width of the widest level
Finds shortest paths? No Yes, in unweighted graphs
Great for Detecting cycles, topological sorting, exploring every path (backtracking), and solving mazes Shortest paths, finding the closest matches first, and level-by-level tree traversal

A DFS on a binary tree generally uses less memory than a BFS, since a balanced tree's height is a lot smaller than the width of its bottom level. And DFS is easy to write with recursion. But if you need the shortest path to a node, use BFS.

What DFS Is Used For

  • Detecting cycles in a graph.
  • Topological sort, which orders tasks so each one comes after everything it depends on.
  • Finding connected components, like counting the islands in a grid.
  • Backtracking problems, like generating every permutation of a string or solving a maze.
  • Tree traversals. Pre-order, in-order, and post-order traversals are all depth-first.

Frequently Asked Questions

What is depth-first search?

Depth-first search (DFS) is a way to traverse a tree or graph that explores as deep as possible along each branch before backtracking. It's usually written with recursion or an explicit stack.

What's the difference between DFS and BFS?

DFS dives deep down one path before backtracking, using a stack or recursion; BFS explores level by level using a queue. Both take O(V + E) time, but only BFS finds shortest paths in unweighted graphs.

What is the time complexity of DFS?

O(V + E) on a graph with V nodes and E edges, since it visits each node and follows each edge once (O(n) on a tree with n nodes). It uses O(V) space for the visited set and the stack, or O(h) on a tree of height h.

Does DFS use a stack or a queue?

A stack. Recursive DFS uses the call stack, and iterative DFS pushes nodes onto an explicit stack. BFS is the one that uses a queue.

What is DFS used for?

Detecting cycles, topological sorting, finding connected components, solving mazes, backtracking problems like generating permutations, and pre-order, in-order, and post-order tree traversals.

Last updated: October 21, 2026

. . .