前言:
二叉树的遍历指的是按照某种固定的方向来遍历整个二叉树,然后返回一个数组/链表,即线性的数据结构,常用的遍历方式有三种,前序,中序和后序遍历,还有一种是按照每一层来访问二叉树的,叫做层序遍历,下面以返回一个List为例,总结每种遍历方式
//定义一个树节点
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
前序遍历
前序遍历的顺序是根节点,左儿子,右儿子,然后逐个对左儿子和右儿子实施这种遍历方式,二叉树相关的算法大都都能使用递归解决,遍历当然也可以,前序遍历代码如下:
//首先是递归算法:前序遍历,顺序是根节点,左儿子,右儿子
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
digui(root, res);
return res;
}
public void digui(TreeNode root, List<Integer> res){
if(root == null) return;
res.add(root.val);
digui(root.left, res);
digui(root.right, res);
return;
}
}
//迭代算法:就是非递归了,结果返回的是个list,需要逐个的求树的根左右的值,也就是需要另外一个数据结构存储节点,这里使用栈,弹出栈顶元素,然后把其右儿子和左儿子入栈,逐步进行这个操作直至栈空*/
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if(root == null) return res;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);//初始化栈
while(!stack.isEmpty()){//栈不空则执行弹出栈顶元素,然后入栈其右儿子,左儿子
root = stack.pop();//获取栈顶元素并出栈
res.add(root.val);
if(root.right != null) stack.push(root.right);
if(root.left != null) stack.push(root.left);
}
return res;
}
}
中序遍历
中序遍历的顺序是左儿子,根节点,右儿子
/中序遍历顺序 左儿子,根节点,右儿子
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
digui(root, res);
return res;
}
public void digui(TreeNode root, List<Integer> res){
if(root == null) return;
if(root.left != null){//res.add(root.left.val);这一行是错误的,注意每一层只需要add根节点,不用add其左右节点,因为下一层子节点就变根节点了,这里再add就会重复
digui(root.left, res);
}
res.add(root.val);
if(root.right != null) digui(root.right, res);
}
}
//递归的方式:和前序遍历一样,使用栈作为辅助存储,和前序遍历的区别是前者可以以根节点为基准进行操作,中序遍历的话需要先放左儿子,也就是list的第一个元素是最左边的那个节点,这样的话栈的初始化就需要遍历到树的最左侧节点,然后开始每层循环:弹出栈顶元素(左儿子),然后把栈顶元素的右儿子入栈
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if(root == null) return res;
Stack<TreeNode> stack = new Stack<>();
while(root != null || !stack.isEmpty()){//这里的初始化方式就是先遍历到树的最左侧节点
while(root != null){
stack.push(root);
root = root.left;
}
root = stack.pop();//获取栈顶元素并出栈
res.add(root.val);
root = root.right;//如果右儿子不为空,则下面需要求其最左侧左儿子,然后入栈,为空则继续弹出
}
return res;
}
}