力扣:二叉树的遍历java
- 遍历二叉树分两类:广度优先遍历(按层遍历),深度优先遍历(先中后序遍历),此文章为深度优先遍历,下一章为广度优先遍历。
- 遍历方法有两种:递归,迭代。
递归法
- 最简单的方法,也是最容易理解的方法。
三个步骤就能写出迭代法遍历二叉树:
- 设置参数,结果
- 设置结束条件(当前节点为空)
- 确定单层递归逻辑(改变此处的代码顺序,即可写出先中后序遍历)
//先序遍历
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {//主函数返回值为List集合
List<Integer> result = new ArrayList<Integer>();//设置返回值
preorder(root, result);//调用先序遍历的函数
return result;
}
public void preorder(TreeNode root, List<Integer> result) {//设置函数的输入节点和结果集
if (root == null) {//设置递归结束条件
return;
}
result.add(root.val);//先序则先将树的节点存入结果集
preorder(root.left, result);//递归该节点的左右孩子节点
preorder(root.right, result);
}
}
//中序遍历
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {//主函数返回值为List集合
List<Integer> result = new ArrayList<Integer>();//设置返回值
preorder(root, result);//调用中序遍历的函数
return result;
}
public void preorder(TreeNode root, List<Integer> result) {//设置函数的输入节点和结果集
if (root == null) {//设置递归结束条件
return;
}
//只需改变这里的顺序
preorder(root.left, result);//递归该节点的左孩子节点
result.add(root.val);//将树的节点存入结果集
preorder(root.right, result);//递归该节点的右孩子节点
}
}
//后序遍历
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {//主函数返回值为List集合
List<Integer> result = new ArrayList<Integer>();//设置返回值
preorder(root, result);//调用后序遍历的函数
return result;
}
public void preorder(TreeNode root, List<Integer> result) {//设置函数的输入节点和结果集
if (root == null) {//设置递归结束条件
return;
}
//只需改变这里的顺序
preorder(root.left, result);//递归该节点的左孩子节点
preorder(root.right, result);//递归该节点的右孩子节点
result.add(root.val);//将树的节点存入结果集
}
}
迭代法
迭代法的先序和后序类似,思路如下:
先序:
1.设置一个栈
2.依次按照中右左的顺序压入栈中,并不断弹出
后序:
1.设置一个栈
2.依次按照中左右的顺序压入栈中,并不断弹出
3.将结果集翻转
代码:
//先序遍历
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();//设置结果集
if(root == null) return result;//判断二叉树为空则直接返回
Stack<TreeNode> st = new Stack<>();//设置一个栈
st.push(root);//将二叉树头结点进行入栈
while(!st.isEmpty()){//设置循环,则到栈为空
TreeNode node = st.peek();//提取当前栈的最后一节点
st.pop();//对栈最后一个元素出栈
if(node != null){//当前节点不是空的时候,将该节点的值输入结果集
result.add(node.val);
}else{//否则结束本次循环
continue;
}
//将当前节点的右左孩子输出栈中
st.push(node.right);
st.push(node.left);
}
return result;
}
}
//后序遍历
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if(root == null) return result;
Stack<TreeNode> st = new Stack<>();
st.push(root);
while(!st.isEmpty()){
TreeNode node = st.peek();
st.pop();
if(node != null){
result.add(node.val);
}else{
continue;
}
//将当前节点的左右孩子输出栈中
st.push(node.left);
st.push(node.right);
}
Collections.reverse(result);//翻转结果集
return result;
}
}
中序遍历
流程:
1.设置一个栈
2.设置一个二叉树指针
3.设置循环条件(当指针或栈不为空进入循环,也就是当指针和栈都为空时循环结束)
4.循环内,如果指针不为空,则将指针的节点入栈,并指针向左移动,否则出栈操作,并将出栈的节点,记录如结果集中,并将指针赋值为指针节点的右节点
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();//结果集
if(root == null) return result;//树为空则直接返回空结果集
Stack<TreeNode> stack = new Stack<>();//设置一个栈
TreeNode node = root;//设置一个树的移动指针
while(node != null || !stack.isEmpty()){//当栈和指针都为空时结束循环
if(node!=null){//判断指针节点是否不为空,则进行入栈操作,并移动指针向左运动
stack.push(node);
node = node.left;
}else{//指针为空,则指针回退回上一个节点也就是父节点,
//并对父节点的值输入结果集,在将指针指向节点的右节点
node = stack.pop();
result.add(node.val);
node = node.right;
}
}
return result;
}
}