Why is DFS slower in one tree and faster in the other?
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
Depth-first search has the same big-O time complexity on trees of the same size, but real running time can still vary a lot between different tree shapes. The reason is that complexity tells you the total amount of work asymptotically, while actual performance is also influenced by recursion depth, memory access patterns, branching structure, and where the target node is found.
The Big-O Result Does Not Tell the Whole Story
For a tree traversal that visits every node exactly once, DFS is still O(n) on both trees. That means the algorithm scales linearly with the number of nodes.
What big-O does not tell you is:
- how deep the recursion goes,
- how much backtracking happens before success,
- whether the target is found early or late,
- and how friendly the memory layout is to the CPU.
So two trees can have the same node count and the same asymptotic complexity while still behaving differently in practice.
Tree Shape Changes the Traversal Experience
Consider a very deep unbalanced tree versus a more balanced tree.
If the tree is deep and skewed, the recursion chain becomes long. That can increase function-call overhead and even risk recursion-depth problems in some languages.
If the tree is balanced, the maximum depth is lower, which changes stack behavior and often improves practical performance.
Early Exit Matters
DFS performance can differ dramatically depending on where the target appears.
If the target is near the root or near the first branch DFS explores, the traversal can finish quickly. If the target is buried deep in the last branch visited, DFS may traverse almost the whole tree first.
That means "slower in one tree and faster in the other" may have less to do with the algorithm itself and more to do with where success happens relative to the traversal order.
Memory Access and Cache Effects
Even when node counts are equal, the physical memory layout of the tree can affect speed. Pointer-heavy, scattered structures often lead to poorer cache locality than compact or more predictably allocated structures.
This matters because the CPU can process nearby memory more efficiently than constantly jumping to unrelated addresses. In a real program, that can make one tree layout noticeably slower even though the algorithmic complexity is the same.
Recursive Overhead Versus Iterative DFS
If recursion depth is large, recursive DFS can pay more stack overhead than an iterative DFS with an explicit stack.
This does not change the asymptotic complexity, but it can change practical performance and robustness on deep trees.
The Right Mental Model
A useful way to think about it is:
- complexity explains growth with input size,
- structure explains constant factors and traversal order effects,
- and search goals explain when the traversal can stop early.
So when one DFS run is slower than another, ask:
- are both traversals visiting all nodes,
- are the trees equally deep,
- is the target found at different times,
- and is recursion or memory layout contributing extra cost?
Those questions are usually more informative than repeating the complexity class alone.
Common Pitfalls
- Assuming equal big-O complexity means equal real-world running time.
- Ignoring early-exit behavior when the search target appears in different parts of different trees.
- Forgetting that deep recursion adds overhead and can hit recursion limits.
- Comparing two DFS runs without considering memory layout or allocation patterns.
- Treating "balanced" and "unbalanced" trees as purely theoretical differences when they can materially affect runtime behavior.
Summary
- DFS can still run at different speeds on different trees even when the big-O complexity is the same.
- Tree depth, branching shape, and target location all affect practical performance.
- Early exit can make one search finish much sooner than another.
- Memory layout and recursion overhead also influence runtime.
- Big-O explains scaling, but actual traversal speed depends on structure and execution details.
Related reading
- Why is dictionary so much faster than list?
- Why is Insertion sort better than Quick sort for small list of elements?
- Why is insertion sort Θn2 in the average case?
- Why is it impossible to find a specified value in a sorted array faster than Olog n?
- Why is Dictionary preferred over Hashtable in C#?
- Why is Dictionary preferred over Hashtable in C?
- Why is Dictionary.First so slow?
- Why is docker build taking so long to run?

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.