GeeksforGeeks Hard

Morris Inorder Traversal

Inorder traversal in O(1) space — no recursion, no stack.

treemorristhreading
Open on GeeksforGeeks ↗
02

Intuition

The stack's only job is remembering how to get back up. Morris threading stores that return path in the tree itself: link the left subtree's rightmost node (the inorder predecessor) back to the current node. Coming back later, the thread's existence tells you the left side is done — remove it and visit.

How to spot this pattern

O(1) space by borrowing the tree's own null pointers. Each node's inorder predecessor has a free right pointer; temporarily aiming it at the current node creates a thread back up, removing the need for a stack. Arriving via that thread is the signal that the left subtree is finished.

03

Approach

1

Find the predecessor

cur has a left child → walk left subtree's right spine to its end (stopping if the thread back to cur already exists).

2

Thread or visit

No thread yet → create it (pred.right = cur), descend left. Thread exists → left subtree finished: cut the thread, visit cur, go right.

3

Tree restored

Every thread is removed on second arrival — the tree ends unchanged, and each edge is walked ≤ 3 times → O(n).

04

Solution & live demo

1def morris_inorder(root):
2 res, cur = [], root
3 while cur:
4 if not cur.left:
5 res.append(cur.val)
6 cur = cur.right
7 else:
8 pred = cur.left
9 while pred.right and pred.right is not cur:
10 pred = pred.right
11 if not pred.right:
12 pred.right = cur # lay the thread
13 cur = cur.left
14 else:
15 pred.right = None # cut it, left side done
16 res.append(cur.val)
17 cur = cur.right
18 return res
05

Common pitfalls

Not cutting the thread

✗ Wrong
else:
    res.append(cur.val)
    cur = cur.right
✓ Right
else:
    pred.right = None
    res.append(cur.val)
    cur = cur.right

The thread is scaffolding, not structure. Leaving it in place permanently corrupts the tree into a cyclic graph, so any later traversal loops forever.

Omitting the pred.right is not cur check

✗ Wrong
while pred.right:
    pred = pred.right
✓ Right
while pred.right and pred.right is not cur:
    pred = pred.right

On the second visit the predecessor's right pointer is the thread, pointing back at cur. Without the identity check the walk follows it and spins in an infinite loop.

Emitting the value on first arrival

✗ Wrong
if not pred.right:
    res.append(cur.val)
    pred.right = cur
✓ Right
if not pred.right:
    pred.right = cur
    cur = cur.left

That produces Morris preorder. Inorder requires the node to be emitted only when returning via the thread, after its entire left subtree has been output.

06

Edge cases

No left child

Visit immediately and go right — the trivial case.

Interrupting mid-traversal

Threads would be left dangling — Morris must run to completion to restore the tree.

07

Complexity

Time
O(n)
Space
O(1)
Threads replace the stack; tree restored at the end.