二叉树的递归遍历比较简单,但是在遍历节点较多的二叉树时有可能会栈溢出,所以还是非递归更安全
递归的本质还是栈,用栈模仿递归的过程即可
前序遍历
对于每个节点来说,先遍历节点值,再遍历左子树,最后遍历右子树
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> ans = new ArrayList<>();
Deque<TreeNode> stack = new ArrayDeque<>();
TreeNode node = root;
while (!stack.isEmpty() || node != null) {
if (node != null) {
// 优先放入节点值
ans.add(node.val);
// 放入当前节点,类似存下递归的上层
stack.push(node);
// 优先遍历左子树
node = node.left;
}
// 左子树为空,返回上层递归
node = stack.pop();
// 遍历右子树
node = node.right;
}
return ans;
}
中序遍历
左子树 -> 本节点值 -> 右子树
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> ans = new ArrayList<>();
Deque<TreeNode> stack = new ArrayDeque<>();
TreeNode node = root;
while (!stack.isEmpty() || node != null) {
while (node != null) {
// 放入当前节点,类似存下递归的上层
stack.push(node);
// 优先遍历左子树
node = node.left;
}
// 左子树为空时,返回上层递归,放入上层节点值
node = stack.pop();
ans.add(node.val);
// 遍历右子树
node = node.right;
}
return ans;
}
后序遍历
左子树 -> 右子树 -> 本节点值
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> ans = new ArrayList<>();
Deque<TreeNode> stack = new ArrayDeque<>();
TreeNode node = root;
TreeNode prev = null; // 最近一次访问的节点
while (!stack.isEmpty() || node != null) {
while (node != null) {
// 放入当前节点,类似存下递归的上层
stack.push(node);
// 优先遍历左子树
node = node.left;
}
// 返回上层递归
node = stack.pop();
// 如果右子树不为空且不是上次访问过的位置
if (node.right != null && node.right != prev) {
// 放入当前节点,类似存下递归的上层
stack.push(node);
// 遍历右子树
node = node.right;
} else {
// 存下最近一次访问的节点
prev = node;
// 存下当前节点值
ans.add(node.val);
// 置空,防止重复进入左子树
node = null;
}
}
return ans;
}