Binary Trees

A binary tree is a tree data structure where each node has at most two children, referred to as the left child and the right child. The fixed limit of two children makes binary trees straightforward to implement — each node only needs two pointers — and enables algorithms that can efficiently narrow down a problem by going left or right at each step.

A useful intuition: think of a tournament bracket (each match has exactly one winner and one loser), a yes/no decision flowchart, or any process that repeatedly splits into exactly two possibilities. These real-world structures map naturally onto binary trees.

Rendering diagram...

Binary Tree Node Structure#

Every node in a binary tree stores three pieces of information:

Rendering diagram...

When a pointer is None (Python) or null (JavaScript), it means that child does not exist. A node with both pointers set to null is called a leaf node — it sits at the bottom of the tree with no descendants.

Binary Tree Node

The fundamental building block of a binary tree

A simple TreeNode class with value, left, and right pointers

Types of Binary Trees#

Binary trees come in several variants, each with distinct structural guarantees and trade-offs. Recognizing which type you are working with tells you what operations are efficient and what assumptions you can safely make:

Full Binary Tree
Rendering diagram...
Complete Binary Tree
Rendering diagram...
Perfect Binary Tree
Rendering diagram...
Balanced Binary Tree
Rendering diagram...
Degenerate Tree
Rendering diagram...
TypeDefinitionProperties
Full (Strict)Every node has 0 or 2 childrenNo nodes with only 1 child
CompleteAll levels filled except possibly the last, which is filled left to rightUsed in heaps; can be stored in array
PerfectAll internal nodes have 2 children AND all leaves at same levelHas 2^(h+1) - 1 nodes where h is height
BalancedHeight of left and right subtrees differ by at most 1 at every nodeEnsures O(log n) operations
Degenerate (Skewed)Each node has at most 1 childEssentially a linked list; O(n) operations

Identifying Binary Tree Types

Check if a binary tree is full, complete, or balanced

Functions to check if a tree is full or balanced

Tree Traversals#

Traversal means visiting every node in the tree exactly once, performing some action at each node (such as printing the value or accumulating a result). The order in which nodes are visited changes the meaning of the result, so choosing the right traversal is just as important as writing the traversal correctly. For binary trees, there are four primary strategies:

Inorder Traversal (Left, Root, Right)#

Inorder traversal follows the pattern Left → Root → Right: descend into the left subtree, process the current node, then descend into the right subtree. Its most important property is that when applied to a Binary Search Tree (BST), it visits every node in ascending sorted order. BSTs are covered in the next chapter — for now, just remember that inorder is the traversal to reach for when you need sorted output from a BST.

Inorder: 4, 2, 5, 1, 6, 3, 7
Rendering diagram...
Rendering diagram...

Inorder Traversal

Visit nodes in Left-Root-Right order

Time:O(n)Space:O(h)Best:O(n)Worst:O(n)

Preorder Traversal (Root, Left, Right)#

Preorder traversal follows the pattern Root → Left → Right: process the current node first, then descend into the left subtree, then the right subtree. Because each node is recorded before its children, preorder captures the parent-before-child relationship of the tree. This makes it well-suited for serializing a tree (encoding it as a flat sequence that can be fully reconstructed later) and for copying a tree (you must create the root before you can attach children to it).

Preorder: 1, 2, 4, 5, 3, 6, 7
Rendering diagram...
Rendering diagram...

Preorder Traversal

Visit nodes in Root-Left-Right order

Time:O(n)Space:O(h)Best:O(n)Worst:O(n)

Postorder Traversal (Left, Right, Root)#

Postorder traversal follows the pattern Left → Right → Root: fully process both subtrees before handling the current node. Because a node is only visited after all of its descendants have been processed, postorder is the correct choice when a parent depends on the results of its children. The two classic examples are deleting a tree (you must free the children before freeing the parent, otherwise you lose access to them) and evaluating an expression tree (you must evaluate the sub-expressions before you can apply the operator at the parent node).

Postorder: 4, 5, 2, 6, 7, 3, 1
Rendering diagram...
Rendering diagram...

Postorder Traversal

Visit nodes in Left-Right-Root order

Time:O(n)Space:O(h)Best:O(n)Worst:O(n)

Level-Order Traversal (BFS)#

Level-order traversal visits nodes level by level — all nodes at depth 0 first, then all at depth 1, and so on — processing nodes left to right within each level. This is also called Breadth-First Search (BFS) on the tree. It uses a queue (first-in, first-out) rather than a stack, because we want to process nodes in the same order they were discovered. A stack would reverse that order, which is exactly what we do not want here.

Level Order: 1, 2, 3, 4, 5, 6, 7
Rendering diagram...
Rendering diagram...

Level-Order Traversal (BFS)

Visit nodes level by level using a queue (w = maximum width of tree)

Time:O(n)Space:O(w)Best:O(n)Worst:O(n)

Traversal Comparison#

All four traversal strategies visit every node in O(n) time. What differs is the order — which determines what the resulting sequence means and which problems each traversal is naturally suited for:

Traversal orders for tree: 1(2(4,5), 3(6,7))

TraversalOrderUse CasesResult for Example Tree
InorderLeft, Root, RightSorted output (BST), infix expression[4, 2, 5, 1, 6, 3, 7]
PreorderRoot, Left, RightCopy tree, prefix expression, serialize[1, 2, 4, 5, 3, 6, 7]
PostorderLeft, Right, RootDelete tree, postfix expression[4, 5, 2, 6, 7, 3, 1]
Level-orderLevel by levelShortest path, level operations[1, 2, 3, 4, 5, 6, 7]

Calculate Tree Height#

There are two common conventions for measuring tree height:

  • Edge-based: count the number of edges on the longest root-to-leaf path. An empty tree has height -1; a single-node tree has height 0.
  • Node-based: count the number of nodes on the longest root-to-leaf path. An empty tree has height 0; a single-node tree has height 1.

Both conventions are correct — they are off by one from each other. The implementations below show both. Be consistent within your own code, and check which convention a coding problem or interview expects.

Calculate Tree Height

Find the height of a binary tree (longest path from root to leaf)

Time:O(n)Space:O(h)Best:O(n)Worst:O(n)

Common Operations#

OperationTime ComplexitySpace Complexity
Traversal (any)O(n)O(h) recursive; O(h) for iterative DFS, O(w) for iterative BFS
Calculate HeightO(n)O(h)
Count NodesO(n)O(h)
Search (unsorted)O(n)O(h)
Insert at PositionO(n)O(h)
Find Max/MinO(n)O(h)
Check if BalancedO(n)O(h)

h = height of tree; w = maximum width (nodes on the widest level). For a balanced tree h = O(log n); for a skewed tree h = O(n). w can be O(n) for a perfect binary tree's last level.

Count Nodes in Binary Tree

Count total nodes, leaf nodes, or internal nodes

Three ways to count nodes in a binary tree

Applications of Binary Trees#

ApplicationDescriptionWhy Binary Tree?
Expression TreesRepresent mathematical expressionsOperators as internal nodes, operands as leaves
Huffman CodingData compression algorithmBuild optimal prefix codes using binary tree
Binary HeapsPriority queue implementationComplete binary tree stored in array
Syntax Trees (AST)Compiler designParse and represent code structure
Decision TreesMachine learning classificationBinary decisions at each node
Game TreesAI for games (minimax)Represent possible game states
Expression Tree for: 3 + 4 * 2
Rendering diagram...

Reviewing AI-Generated Code#

Binary tree traversals are deceptively easy to get wrong — a single misplaced line silently produces incorrect output without raising an error. When reviewing AI-generated tree code, focus on two recurring failure points: the order in which nodes are visited, and how the underlying stack or queue is managed in iterative versions.

IssueWhat to CheckCommon AI Mistake
Visit orderVerify when node is processedWrong order in inorder/preorder/postorder
Null handlingCheck before accessing left/rightDereferencing null pointers
Stack vs QueueDFS uses stack, BFS uses queueUsing wrong data structure
Iterative conversionPush order matters for stackWrong push order in iterative traversal
Space complexityRecursion uses call stackClaiming O(1) space for recursive solution

Spotting AI Traversal Bugs

Common errors in AI-generated traversal code

Correct iterative inorder with proper stack management

Questions to Ask When Reviewing Binary Tree Code#

  1. "When exactly is the node visited?" — Confirm that the value is appended (or processed) at precisely the right point relative to the recursive calls, matching the intended traversal order.
  2. "Show me the output for this small example tree" — Trace through a 3–7 node example by hand and compare it to the code's output. Discrepancies reveal order bugs instantly.
  3. "In the iterative version, what is pushed to the stack first?" — Remember that a stack is LIFO: whatever is pushed last is processed first. Verify that the push order produces the intended visit order.
  4. "What is the actual space complexity?" — Recursive solutions consume O(h) call-stack space, not O(1). For a skewed tree, that becomes O(n).

Summary#

ConceptKey Point
Binary TreeTree where each node has at most two children (left and right)
TypesFull, Complete, Perfect, Balanced, Degenerate
Inorder (L-Root-R)Gives sorted output for BST; used for expressions
Preorder (Root-L-R)Root first; used for copying and serializing trees
Postorder (L-R-Root)Root last; used for deletion and evaluation
Level-order (BFS)Uses queue; visits level by level
HeightLongest path from root to leaf; O(log n) for balanced, O(n) for skewed
ApplicationsExpression trees, heaps, ASTs, decision trees, game AI

Now that you understand binary trees and their traversals, continue to Binary Search Trees to see how adding a simple ordering rule — all left values smaller, all right values larger — transforms an ordinary binary tree into a structure that supports efficient searching, insertion, and deletion.