skip to content

Why does releasing a binary decision tree node by node require postorder, when every traversal is O(n)?

level: middleimportance: must knowfreq 72%

answer

  1. Cost is equal, correctness is not
  2. Who needs whom to finish first
  3. A node holds the only links down
  4. Dependency runs children to parent
  5. That direction has a name: postorder

basics

~20 s

Releasing a node destroys the only links to its subtrees, so both children must go first — exactly postorder. All four traversals cost O(n); what differs is the direction of the dependency, which here runs from children up to the parent.

solid answer

~50 s

Equal asymptotic cost is not interchangeability. A node is the only handle you have on its two subtrees, so tearing it down before them strands everything below — the walk must finish both children first, which is the definition of postorder. The general rule is to read the direction of the data dependency: work that has to **roll up** from children to parent (releasing, summing a subtree's rule count, computing a branch's worst-case depth) is postorder; work that has to **push context down** from parent to children (stamping each rule with the path taken to reach it, emitting a serialized form a rebuilder can consume top-down) is preorder; work defined by tier (rendering a routing rule set one level at a time for an ops dashboard) is level-order. "They're all O(n), so it doesn't matter" answers a cost question that nobody asked, and gets the correctness question wrong.

go deeper

for a junior

Know that a node holds the only links to its subtrees, so anything that destroys a node must handle both children first. Be able to name that order as postorder.

for a middle

Explain the choice as a data-dependency direction — upward means postorder, downward means preorder, tier-defined means level-order — and say why identical O(n) cost is irrelevant to it.

for a senior

Diagnose an existing walk from its dependency: given a pass over a rule tree, say which order it must run in and what symptom appears if someone reorders it during a refactor.

for a principal

Own the design call: decide whether repeated passes in different orders over one structure should be collapsed into a single walk carrying both a descend hook and an ascend hook, and what that costs the next reader.

## The trap in the question Every traversal of an n-node tree is O(n). That is true, and it is the reason the mistake is so common: a candidate hears "which traversal" as a performance question, answers "they're the same cost," and misses that the orders are not *interchangeable*. Cost tells you what the walk will price; the **direction of the data dependency** tells you which walk is correct. Only one of them usually is. ## Why teardown is child-first Consider a fraud-triage decision tree: internal nodes hold rule records (a feature, a threshold, some counters) and each has up to two children. You want to release every node's storage explicitly. A node is the *only* reference to its two subtrees. Release it first and the addresses of its children are gone with it — the subtrees are still allocated, still occupying memory, and now unreachable. So the correct order is: release the left subtree, release the right subtree, then release the node. That is postorder, precisely. The same shape appears any time "finish the children before the parent can be finished" holds: - computing how many rules a subtree contains, or the worst-case evaluation depth of a branch — the parent's number is a function of its children's numbers, - collapsing a subtree into a summary record for a report, - checking a structural invariant bottom-up, where a parent's verdict depends on both children's verdicts, - any "unwind and clean up" pass at all. ## Why some work is parent-first Invert the dependency and you get preorder. If each node must be handed something the parent computed — the path taken from the root to reach it, an accumulated set of conditions, a depth stamp, an inherited routing prefix — the parent has to be processed before the descent, so the value is in hand when the children are visited. Preorder is also the natural serialization order: emit the node, then its left subtree, then its right, using an explicit sentinel token where a child is missing, and a rebuilder can consume that stream front to back, creating each node before its children. A nuance worth stating honestly, because interviewers probe it: **copying** a tree is not rigidly preorder. The familiar top-down copy (create the copied node, then recurse and attach each copied child) is preorder, but a bottom-up copy that builds both child copies first and then constructs the parent from them is postorder and equally correct. Copying works either way because the copy has no ordering constraint of its own. Releasing does not have that freedom, which is exactly why teardown is the sharper example. ## Why some work is tier-defined And sometimes the task's shape is neither up nor down but *across*. Rendering the routing rule set to an operations dashboard one tier at a time — every depth-1 rule, then every depth-2 rule — cannot be produced by any placement of the visit inside a recursive left/right descent, because a depth-first walk finishes one whole branch before touching the sibling branch's second level. That job needs the queue-driven level-order walk. ## Reconstruction: another place order carries information The orders also differ in how much information their *output* preserves. With distinct values, a preorder sequence plus an inorder sequence reconstructs the original binary tree uniquely: preorder names the root, inorder splits the remaining values into the left and right groups, and you recurse. Preorder plus postorder does **not** determine the tree in general — for a node with exactly one child, nothing in either sequence says which side it was on; the pair is only sufficient when every node has zero or two children. A single preorder sequence with explicit empty-child markers is enough on its own, because the markers restore the shape the plain sequence loses. ## How to answer it out loud Name the dependency direction first, then the order it forces, then the cost as an aside: > "Freeing a node destroys the links to its children, so children first — that's postorder. The choice isn't about speed; all four are linear. It's that the dependency runs upward, and postorder is the order that respects it. If the dependency ran downward — stamping each node with its path from the root — I'd want preorder instead." ## What people get wrong - "All O(n), so pick any." Conflates cost with correctness. - "Preorder frees the parent first, which detaches the children so they get cleaned up." Detaching is what makes them unreachable, not what reclaims them. - "Use level-order, it touches each node once too." It does, but it releases parents before their children — the same bug with an extra queue. - "Postorder is only for arithmetic on trees." Aggregation is one instance of the child-first dependency, not the whole category.

  • Give me a task on the same tree where preorder is the only correct order.
    Stamping each rule with the path taken from the root to reach it. The parent must compute and hand down the prefix before either child is visited, so the node's work strictly precedes both descents. Serializing the tree is the same shape: emit the node, then its subtrees, with an explicit marker for a missing child, and a rebuilder can consume the stream front to back.
  • Does a preorder sequence plus a postorder sequence reconstruct a binary tree?
    Not in general. For a node with exactly one child, neither sequence records whether the child was on the left or the right, so distinct trees share both sequences. The pair is sufficient only when every node has zero or two children. Preorder plus inorder does determine the tree with distinct values, and preorder alone suffices if empty children are emitted as explicit markers.
  • Is copying a tree preorder, by the same argument?
    Less rigidly. The usual top-down copy — create the node, then recurse and attach each copied child — is preorder, but building both child copies first and constructing the parent from them is postorder and just as correct. Copying imposes no ordering constraint of its own, which is why teardown, where the constraint is real, is the better illustration.

Dismantling scaffolding: you take down the upper platforms before the poles holding them. Remove a pole first and everything it supported is still up there, now unreachable.

saying these in an interview costs you the question

  • Says all traversals are O(n), so the choice does not matter
  • Frees the parent first and assumes children are collected
  • Picks level-order because it also visits every node once
  • Treats postorder as only for arithmetic expression trees
  • Claims preorder plus postorder always rebuilds the tree

context