Trees
Tree: a hierarchy with one root where each node has a value and children. Recursive traversal is elegant but unsafe on deep user data; use iterative DFS with an explicit stack.
A tree is a hierarchy: each node has a value and zero or more children, and there is exactly one root. There are no cycles and no second path to the same node. The DOM, a file system, and a JSON document are all trees.
The simplest representation is a plain object with a value field and a children array. A recursive walk function visits the root, then calls itself on each child. Tracking depth lets you add indentation so the printed output mirrors the hierarchy visually.
const fileSystem = {
value: "root",
children: [
{
value: "src",
children: [
{ value: "index.js", children: [] },
{ value: "utils.js", children: [] },
],
},
{
value: "public",
children: [
{ value: "index.html", children: [] },
{ value: "logo.svg", children: [] },
],
},
{ value: "package.json", children: [] },
],
};
function walk(node, depth = 0) {
console.log(" ".repeat(depth * 2) + node.value);
for (const child of node.children) {
walk(child, depth + 1); // recurse into each child
}
}
walk(fileSystem);
// root
// src
// index.js
// utils.js
// public
// index.html
// logo.svg
// package.jsonRecursive traversal has an implicit stack living in the call stack. When the tree comes from user input it can be arbitrarily deep, and deep recursion throws a RangeError: Maximum call stack size exceeded. An iterative DFS replaces the call stack with an explicit array used as a stack: push the root, then loop - pop a node, process it, push its children.
function walkIterative(root) {
const stack = [{ node: root, depth: 0 }];
while (stack.length > 0) {
const { node, depth } = stack.pop(); // take from the top
console.log(" ".repeat(depth * 2) + node.value);
// push children in reverse order so the first child is processed first
for (let i = node.children.length - 1; i >= 0; i--) {
stack.push({ node: node.children[i], depth: depth + 1 });
}
}
}
// same output as the recursive version, but safe on deep trees
walkIterative(fileSystem);
// root
// src
// index.js
// utils.js
// public
// index.html
// logo.svg
// package.json
// the recursive version would throw on deeply nested user data:
// RangeError: Maximum call stack size exceededIn production
Recursive traversal blows the call stack on deep user-supplied trees - HTML pasted from a document editor or badly nested JSON can easily exceed the default stack depth in V8 (~10,000 frames). Iterative DFS with an explicit stack is the safe default whenever depth is unbounded. For the DOM specifically, TreeWalker (document.createTreeWalker) is purpose-built, iterative, and faster than any hand-rolled traversal.
Enjoyed this? Get more essays on software craft delivered to your inbox.
Subscribe free