Binary Tree Preorder Traversal
Easy · Graphs · Explanation and code example
Morris Traversal
How it works
Morris Traversal lets us do preorder traversal without recursion and without a stack, using O(1) extra space.
The key idea:
- For every node with a left child, find its inorder predecessor (rightmost node in the left subtree).
- Normally, after finishing the left subtree, we would return back to the root.
Since we have no stack, we temporarily create a thread:
predecessor.right = current - On the first time we reach a node, we record its value (because preorder = Node → Left → Right).
- When we come back through the created thread, we restore the tree by removing the thread and then continue to the right child.
This modifies the tree temporarily but restores it fully at the end.
Steps
- Initialize
cur = rootand an empty result listres. - While
curis notnull:- If
cur.leftdoes NOT exist:- Visit
cur(append value tores). - Move to
cur.right.
- Visit
- Else:
- Find the inorder predecessor
prev(rightmost node incur.left). - If
prev.rightisnull:- This is the first time visiting
cur. - Append
cur.valtores. - Create a thread:
prev.right = cur. - Move to
cur.left.
- This is the first time visiting
- Else:
- Thread exists → we are returning after finishing the left subtree.
- Remove the thread:
prev.right = None. - Move to
cur.right.
- Find the inorder predecessor
- If
- Return
res.
Complexity
- Time complexity:
O(n) - Space complexity:
O(1)extra space.O(n)space for the output array.
Things to watch for
Adding Node Value After Recursing on Children
Preorder requires visiting the current node before its children. Adding the value after recursive calls produces postorder traversal instead.
Pushing Left Child Before Right in Stack-Based Approach
In the iterative approach, the right child must be pushed onto the stack before the left child. Since stacks are LIFO, pushing left first causes right to be processed first.
Python code example
from typing import List, Optional
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
res = []
cur = root
while cur:
if not cur.left:
res.append(cur.val)
cur = cur.right
else:
prev = cur.left
while prev.right and prev.right != cur:
prev = prev.right
if not prev.right:
res.append(cur.val)
prev.right = cur
cur = cur.left
else:
prev.right = None
cur = cur.right
return res
C++ code example
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
TreeNode* cur = root;
while (cur) {
if (!cur->left) {
res.push_back(cur->val);
cur = cur->right;
} else {
TreeNode* prev = cur->left;
while (prev->right && prev->right != cur) {
prev = prev->right;
}
if (!prev->right) {
res.push_back(cur->val);
prev->right = cur;
cur = cur->left;
} else {
prev->right = nullptr;
cur = cur->right;
}
}
}
return res;
}
};
Source and license
Adapted from NeetCode’s source · MIT license. Node types are supplied by LeetCode where needed.