题目
前序思路
- 首先思考二叉树的前序遍历,其核心思想为:
- 过程1:每拿到一个节点就把它保存在栈中
- 对这个节点的左子树重复过程1,直到左子树为空。
- 因为保存在栈中的节点都遍历了左子树但没有遍历右子树,所以对栈中节点出栈并对它的右子树重复过程1
- 直到遍历完所有节点
- 详细代码如下
代码
public List<Integer> preorderTraversal(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
ArrayList<Integer> ans = new ArrayList<>();
TreeNode temp = root;
while (temp!=null || !stack.empty()){
while (temp!=null){
ans.add(temp.val);
stack.push(temp);
temp = temp.left;
}
temp = stack.pop();
temp = temp.right;
}
return ans;
}
后序思路
- 根据上面学到的前序遍历知识,思考后序遍历,前序遍历为根左右,后序遍历为左右根。
- 前序遍历时,是往list尾部插的,出来的顺序是根左右,如果相反往头部插,那么出来的顺序则为右左根。
- 那么只需先遍历到最右,再弹出并找最左,即可完成左右根的遍历。
代码
public List<Integer> postorderTraversal(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
ArrayList<Integer> ans = new ArrayList<>();
TreeNode temp = root;
while (!stack.empty() || temp!=null){
while (temp!=null){
ans.add(0,temp.val);
stack.push(temp);
temp = temp.right;
}
temp = stack.pop();
temp = temp.left;
}
return ans;
}
中序思路
- 中序思路不能完全按照前后序,因为中序为左根右,根节点并不首先或者最后打印。
- 故修改上述代码,添加入栈的时候就不要打印了,直接入栈,其次对每个以temp为root的节点,都需要找到其最左端,所以每次循环时都要找到其最左端的节点。
- 在找到最左端时对栈进行pop并保存结果,此时再令temp为其右节点,因为此时左中均已入栈,需要找到右节点的最左端。
代码
public List<Integer> inorderTraversal(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
ArrayList<Integer> ans = new ArrayList<>();
TreeNode temp = root;
while (!stack.empty() || temp!=null){
while (temp!=null){
stack.push(temp);
temp = temp.left;
}
temp = stack.pop();
ans.add(temp.val);
temp = temp.right;
}
return ans;
}