A tree is a node with subtrees, so recursion is the natural way to visit it. Pre-order, in-order, and post-order are the same walk with the visit moved.
What you will see
6
About 3 min of reading
Quick check
Before this new lesson, one small question about the lesson you just finished. Recall it, do not look it up.
Try It
Walk a tree with recursion.
1
Size of a tree.
def size(node):
if node is None:
return 0
return 1 + size(node.get("left")) + size(node.get("right"))
tree = {"v": 1, "left": {"v": 2}, "right": {"v": 3}}
print(size(tree))
Before you run it, say out loud what it will print. Then open the answer.
What it prints
3
2
In-order list.
def inorder(node):
if node is None:
return []
return inorder(node.get("left")) + [node["v"]] + inorder(node.get("right"))
tree = {"v": 2, "left": {"v": 1}, "right": {"v": 3}}
print(inorder(tree))
Before you run it, say out loud what it will print. Then open the answer.
What it prints
[1, 2, 3]
3
Height of a tree.
def height(node):
if node is None:
return 0
return 1 + max(height(node.get("left")), height(node.get("right")))
tree = {"v": 1, "left": {"v": 2, "left": {"v": 3}}}
print(height(tree))
Before you run it, say out loud what it will print. Then open the answer.
What it prints
3
4
Sum tree values.
def total(node):
if node is None:
return 0
return node["v"] + total(node.get("left")) + total(node.get("right"))
tree = {"v": 1, "left": {"v": 2}, "right": {"v": 3}}
print(total(tree))
Before you run it, say out loud what it will print. Then open the answer.
What it prints
6
Put it in order
Before you write anything, put these lines back in the right order. Click a line to move it up one step. This support step is easier than writing code from scratch, and it is here to make the last example stick.
Data Flow
A tree is a node with subtrees, so recursion visits it naturally. Pre, in, and post order are the same walk with the visit moved.
1visit node
↓
2recurse left child
↓
3recurse right child
↓
4None is base
Line by line
Read the first example one line at a time. A line that prints shows what appears on screen; the rest set things up quietly.
def size(node):sets nothing on screen
if node is None:sets nothing on screen
return 0sets nothing on screen
return 1 + size(node.get("left")) + size(node.get("right"))sets nothing on screen
tree = {"v": 1, "left": {"v": 2}, "right": {"v": 3}}sets nothing on screen
print(size(tree))3
Why this worksOrder is where you visit
The three orders are one recursion with the node visit placed before, between, or after the child calls. Pick the one the task needs.
None is the base
A missing child is None and returns the empty answer. Every branch of a tree walk ends there.
Examples
Node with children
defsize(node):
if node is None:
return0return1 + size(node.get("left")) + size(node.get("right"))
tree = {"v": 1, "left": {"v": 2}, "right": {"v": 3}}
print(size(tree))
A node is counted, then each child subtree. None is the base case for a missing child.
In-order gives sorted
definorder(node):
if node is None:
return []
returninorder(node.get("left")) + [node["v"]] + inorder(node.get("right"))
tree = {"v": 2, "left": {"v": 1}, "right": {"v": 3}}
print(inorder(tree))
Left, then node, then right. On a search tree that order is sorted.
Pre-order visits first
defpreorder(node):
if node is None:
return []
return [node["v"]] + preorder(node.get("left")) + preorder(node.get("right"))
tree = {"v": 2, "left": {"v": 1}, "right": {"v": 3}}
print(preorder(tree))
Node before children. That order copies the shape top down.
Post-order visits last
defpostorder(node):
if node is None:
return []
returnpostorder(node.get("left")) + postorder(node.get("right")) + [node["v"]]
tree = {"v": 2, "left": {"v": 1}, "right": {"v": 3}}
print(postorder(tree))
Children before node. Useful when a parent needs its children solved first.
Depth of a tree
defheight(node):
if node is None:
return0return1 + max(height(node.get("left")), height(node.get("right")))
tree = {"v": 1, "left": {"v": 2, "left": {"v": 3}}}
print(height(tree))
The taller branch plus one. None has height zero, the base.
Sum the values
deftotal(node):
if node is None:
return0return node["v"] + total(node.get("left")) + total(node.get("right"))
tree = {"v": 1, "left": {"v": 2}, "right": {"v": 3}}
print(total(tree))
Node value plus both subtrees. The same recursion shape as size.
A leaf is the base
defsize(node):
if node is None:
return0return1 + size(node.get("left")) + size(node.get("right"))
tree = {"v": 9}
print(size(tree))
A leaf has two None children, each returning zero. The leaf itself counts one.
Search tree in-order
definorder(node):
if node is None:
return []
returninorder(node.get("left")) + [node["v"]] + inorder(node.get("right"))
tree = {"v": 3, "left": {"v": 1, "left": {"v": 2}}, "right": {"v": 4}}
print(inorder(tree))
In-order on a search tree lists values in order. The walk respects the ordering.
Words this lesson uses
Each one is defined here on this site. Open the entry for the full definition and the other words it points at.