二叉树遍历:前序、中序、后序
递归与迭代两种方式实现二叉树的三种遍历
问题
实现二叉树的前序、中序、后序遍历,分别用递归和迭代两种方式。
解答
二叉树节点定义
function TreeNode(val, left = null, right = null) {
this.val = val;
this.left = left;
this.right = right;
}
前序遍历(根 → 左 → 右)
// 递归
function preorderRecursive(root) {
const result = [];
function traverse(node) {
if (!node) return;
result.push(node.val); // 先访问根
traverse(node.left); // 再遍历左子树
traverse(node.right); // 最后遍历右子树
}
traverse(root);
return result;
}
// 迭代
function preorderIterative(root) {
if (!root) return [];
const result = [];
const stack = [root];
while (stack.length) {
const node = stack.pop();
result.push(node.val);
// 先压右子节点,再压左子节点(出栈时左先出)
if (node.right) stack.push(node.right);
if (node.left) stack.push(node.left);
}
return result;
}
中序遍历(左 → 根 → 右)
// 递归
function inorderRecursive(root) {
const result = [];
function traverse(node) {
if (!node) return;
traverse(node.left); // 先遍历左子树
result.push(node.val); // 再访问根
traverse(node.right); // 最后遍历右子树
}
traverse(root);
return result;
}
// 迭代
function inorderIterative(root) {
const result = [];
const stack = [];
let current = root;
while (current || stack.length) {
// 一直向左走,把沿途节点压入栈
while (current) {
stack.push(current);
current = current.left;
}
// 弹出节点,访问它,然后转向右子树
current = stack.pop();
result.push(current.val);
current = current.right;
}
return result;
}
后序遍历(左 → 右 → 根)
// 递归
function postorderRecursive(root) {
const result = [];
function traverse(node) {
if (!node) return;
traverse(node.left); // 先遍历左子树
traverse(node.right); // 再遍历右子树
result.push(node.val); // 最后访问根
}
traverse(root);
return result;
}
// 迭代(反转法:根右左 → 反转得到 左右根)
function postorderIterative(root) {
if (!root) return [];
const result = [];
const stack = [root];
while (stack.length) {
const node = stack.pop();
result.push(node.val);
// 先压左,再压右(出栈顺序:根 → 右 → 左)
if (node.left) stack.push(node.left);
if (node.right) stack.push(node.right);
}
return result.reverse(); // 反转得到:左 → 右 → 根
}
测试
// 1
// / \
// 2 3
// / \
// 4 5
const root = new TreeNode(1,
new TreeNode(2, new TreeNode(4), new TreeNode(5)),
new TreeNode(3)
);
console.log(preorderRecursive(root)); // [1, 2, 4, 5, 3]
console.log(inorderRecursive(root)); // [4, 2, 5, 1, 3]
console.log(postorderRecursive(root)); // [4, 5, 2, 3, 1]
关键点
- 前序:根左右;中序:左根右;后序:左右根
- 递归写法简单,改变
push位置即可切换遍历方式 - 前序迭代:栈中先压右再压左,保证左先出
- 中序迭代:不断向左走并压栈,弹出后转向右子树
- 后序迭代:可用「根右左 + 反转」的技巧简化实现
目录