二叉树的三种遍历如果用递归写都很简单,代码几乎都没有变化
前序遍历
非递归的前序遍历思路如下:
前序遍历:root -> left -> right
用栈保存左右节点
每次先取出栈顶元素(root),加入结果
再把栈顶元素的左右节点加入栈
要想用栈实现先遍历左子树再遍历右子树,那么添加到栈的时候就要反过来添加,先添加右子树再添加左子树
返回结果
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public List<Integer> preorder(TreeNode root) {
List<Integer> result = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
if (node == null) continue;
result.add(node.val);
stack.push(node.right); // 先右后左,保证左子树先遍历
stack.push(node.left);
}
return result;
}
后序遍历
left -> right -> root
先来回顾一下前序遍历 root -> left -> right
这样看两条式子有点像,root都是一头一尾,但中间有点不太一样,如果把前序变成root -> right -> left的话那就和后序遍历完全逆序了
所以一种巧妙的思路就是把前序遍历稍微改一改,然后把结果集逆序
代码:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public List<Integer> postorder(TreeNode root) {
List<Integer> result= new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
if (node == null) continue;
result.add(node.val);
stack.push(node.left);
stack.push(node.right);
}
Collections.reverse(result);
return result;
}
中序遍历
left -> root-> right
也就是说要一直找到树的最左节点,再访问其父节点最后访问父节点右子树
代码:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public List<Integer> inorder(TreeNode root) {
List<Integer> result= new ArrayList<>();
if (root == null){
return result;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode current = root;
while (current != null || !stack.isEmpty()) {
while (current != null) {
stack.push(current);
//一直找到最左,先不管右边
current = current.left;
}
TreeNode node = stack.pop();
result.add(node.val);
//中序遍历,最后访问右边
current = node.right;
}
return result;
}