算法系列二之树:二叉树的前中后序遍历
大家好呀,我是饲养员,今天给大家分享一个简单的算法题,树问题:二叉树的深度遍历
144. 二叉树的前序遍历
难度:简单
给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
示例 1:
输入:root = [1,null,2,3]
输出:[1,2,3]
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [1]
输出:[1]
示例 4:
输入:root = [1,2]
输出:[1,2]
示例 5:
输入:root = [1,null,2]
输出:[1,2]
解:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
if(root == null){
return Collections.EMPTY_LIST;
}
List<Integer> list = new ArrayList<>();
// 前序遍历:根左右
list.add(root.val);
list.addAll(preorderTraversal(root.left));
list.addAll(preorderTraversal(root.right));
return list;
}
}
用递归写非常简单,那么中序遍历也是第23行和24行对换即可,后序也是如此,由于这是一道简单题,我们需要尝试非递归的写法,可是思路应该怎样呢?我遍历到的节点不一定就是要的结果顺序呀,如果能够控制先进的能够后出就好了,那么这种数据结构是什么呢?栈(Stack)
来,我们试一下用非递归写一下,代码如下:
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new LinkedList<>();
// 初始化一个栈,用来存放临时数据
Stack<TreeNode> stack = new Stack<>();
TreeNode tree = root;
// 如果当前节点已经空或者栈为null,则跳出循环
while(tree != null || !stack.empty()){
// 正常场景下,当前树不为null,能够继续循环的情况
while (tree != null) {
list.add(tree.val);
stack.add(tree);
tree = tree.left;
}
// 接下来分tree == null, stack还没有完全弹出的情况,只要直接弹出即可
tree = stack.pop();
// 根节点和左节点分别完成,剩下右节点
tree = tree.right;
}
return list;
}
}
那么中序遍历呢?
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new LinkedList<>();
Stack<TreeNode> stack = new Stack<>();
TreeNode tree = root;
while(tree != null || !stack.empty()){
if (tree != null) {
stack.add(tree);
tree = tree.left;
} else {
tree = stack.pop();
list.add(tree.val);
tree = tree.right;
}
}
return list;
}
}
总结
其实非递归方式无非就是用一个栈去临时存放树,从而达到控制存放树存放顺序这么一个作用,其实栈的用法也很简单,pop是弹出元素,add是放入元素,栈是先进后出的,前序遍历是根左右,中序是左根右,知道这些基本的概念后,解题就很容易。
好了,本期的饲养员投喂完毕,下次见!