What is Depth-First Search?
Depth-First Search explores a graph by plunging as deep as possible down one path before ever backing up: from the current vertex, move to an unvisited neighbor, then from there to one of its unvisited neighbors, and so on — only backtracking to try a different branch once a path runs out of new vertices to reach. Unlike BFS's expanding rings, DFS traces out one long tendril at a time.
How Does It Work?
That behavior comes from using a stack (last-in, first-out) instead of a queue. Whichever vertex was discovered most recently is the one explored next, which is exactly what "keep going deeper" means — the newest neighbor found always jumps ahead of anything discovered earlier and still waiting. A stack can be explicit (an array used as a stack) or implicit, via the call stack of a recursive function — both produce the same traversal order.
A subtlety worth noting: with an explicit stack, a vertex can end up pushed more than once before it's actually processed, if two different vertices both discover it as a neighbor before it's popped. That's fine — a visited check happens when a vertex is popped, not when it's pushed, so any duplicate is simply skipped once it's already been handled. This is a real difference from BFS, which marks a vertex visited the moment it's enqueued specifically to prevent that kind of duplication.
Algorithm Steps
- Push the start vertex onto the stack
- While the stack isn't empty, repeat:
- Pop a vertex; if it's already visited, skip it and continue
- Otherwise, mark it visited and process it (this is the visit order)
- Push each of its unvisited neighbors onto the stack
- Stop when the stack is empty — every vertex reachable from the start has been visited
Time Complexity
- Time Complexity: O(V + E) — every vertex is popped and processed once, and every edge is examined once across the whole run.
- Space Complexity: O(V) — for the stack (explicit or via recursion) and the visited set in the worst case.
Time Complexity Analysis
DFS is the natural tool whenever "is there a path at all" matters more than "what's the shortest path" — detecting cycles, finding connected components, topological sorting of a dependency graph, and solving maze- or puzzle-like search spaces where backtracking through one failed branch to try another is exactly the desired behavior.