Converting a 2D grid graph data structure to a tree
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
A 2D grid graph is not a tree by default because every interior cell usually has several neighbors, which creates cycles. Converting it to a tree really means choosing one acyclic set of parent-child links that still reaches every reachable cell.
A tree is a spanning view of the grid
The key idea is that you usually do not "transform" the grid into a different mathematical object with the same edges. Instead, you build a spanning tree of the grid.
That means:
- every reachable node appears exactly once in the result
- the result has no cycles
- each non-root node gets exactly one parent
- some original grid edges are intentionally discarded
If your grid is connected and has V reachable cells, the tree will contain V - 1 edges. Any extra edge from the original grid would reintroduce a cycle.
This distinction matters because a tree cannot preserve all adjacency information from a dense grid. It preserves connectivity, not every neighbor relationship.
Building a tree with breadth-first search
Breadth-first search is often the cleanest conversion method when you want a shallow tree rooted at a chosen start cell. It visits cells level by level and records the first cell that discovered each neighbor as the parent.
Here is a runnable Python example that turns a rectangular grid into a BFS tree while skipping blocked cells:
The parent dictionary is the tree. Every key is a node, and its value is the parent node. The root maps to None.
When depth-first search is a better fit
Depth-first search is equally valid if you just need any tree and do not care about minimizing depth from the root. DFS often feels natural for recursive algorithms or maze-style exploration.
BFS and DFS both run in linear time with respect to vertices and edges. The choice is about the shape of the tree:
- BFS usually gives shorter root-to-node paths
- DFS often gives longer branches and a less balanced tree
Choosing a root and storing the result
The root changes the hierarchy but not the fact that the output is a tree. In pathfinding or visibility systems, the root is often the player position or a source cell. In generic utilities, the top-left reachable cell is a simple default.
You also need to decide how to store the tree:
- '
parent[node] = parent_nodeis compact and easy for backtracking' - '
children[node] = [...]is convenient for top-down traversal' - both can be generated from each other
If the original graph has multiple disconnected components, one tree is not enough. You either choose a single component or build a forest, which is just a set of trees.
Common Pitfalls
The most common mistake is expecting the tree to preserve every original neighbor link. It cannot, because keeping all grid edges would keep the cycles too.
Another issue is forgetting about blocked or unreachable cells. If your input grid has walls, holes, or disconnected regions, your conversion code should either return only the reachable component from the root or explicitly build multiple trees.
It is also easy to call the result a tree while still storing cross-links from the original graph. Once those extra links remain part of the structure, the result is no longer a tree for traversal purposes.
Finally, do not assume BFS and DFS are interchangeable for downstream logic. If later code depends on shallow depth, shortest unweighted paths, or predictable levels, BFS is the safer choice.
Summary
- Converting a grid graph to a tree usually means building a spanning tree.
- A tree preserves connectivity, not every adjacency edge from the original grid.
- BFS is a good default when you want short root-to-node paths.
- DFS is fine when any acyclic hierarchy is acceptable.
- Disconnected grids produce a forest unless you intentionally restrict the input to one component.

