二叉树的遍历
前序遍历:根节点–》根节点的左子树–》根节点的右子树
中序遍历:根节点的左子树–》根节点–》根节点的右子树
后序遍历:根节点的左子树–》根节点的右子树–》根节点
共同点:先坐子树后右子树
不同点:根节点的遍历次序不同
二叉树的递归遍历非常简单,就拿前序遍历做个说明(来源–》力扣144. 二叉树的前序遍历):
创建一个数组,保存遍历结果,只要节点不为空,就保存结点,向左遍历完后向右遍历
二叉树中序和后序的递归遍历只需要改变递归的顺序
class Solution {
List<Integer> arr=new ArrayList<>();
public List<Integer> preorderTraversal(TreeNode root) {
if(root!=null){
arr.add(root.val);
preorderTraversal(root.left);
preorderTraversal(root.right);
}
return arr;
}
}
以下是二叉树的非递归遍历👇👇👇
二叉树的前序遍历
二叉树前序遍历的非递归遍历是借助栈(Stack)来实现的:先把根结点入栈,栈非空时元素出栈放到数组中,然后让右孩子和左孩子分别入栈(因为是先序遍历跟–》左–》右,所以先把右孩子入栈,再把左孩子入栈),代码(力扣144. 二叉树的前序遍历)和入栈出栈顺序如下:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> ret=new ArrayList<>();
if(root==null){
return ret;
}
Stack<TreeNode> s=new Stack<>();
s.push(root);
while(!s.isEmpty()){
TreeNode cur=s.pop();
ret.add(cur.val);
if(cur.right!=null){
s.push(cur.right);
}
if(cur.left!=null){
s.push(cur.left);
}
}
return ret;
}
}
二叉树的中序遍历
二叉树的中序遍历,代码如下(力扣94. 二叉树的中序遍历):
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> ret=new ArrayList<>();
if(root==null){
return ret;
}
Stack<TreeNode> s=new Stack<>();
TreeNode cur=root;
while(cur!=null||!s.isEmpty()){
while(cur!=null){
s.push(cur);
cur=cur.left;
}
TreeNode p=s.pop();
ret.add(p.val);
if(p.right!=null){
cur=p.right;
}
}
return ret;
}
}
二叉树的后序遍历
二叉树的后序遍历,代码如下(力扣145. 二叉树的后序遍历):
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> ret=new ArrayList<>();
if(root==null){
return ret;
}
TreeNode cur=root;
TreeNode flag=null;
Stack<TreeNode> s=new Stack<>();
while(cur!=null||!s.isEmpty()){
while(cur!=null){
s.push(cur);
cur=cur.left;
}
TreeNode p=s.peek();
if(p.right==null||flag==p.right){
flag=s.peek();
ret.add(s.pop().val);
}
else{
cur=p.right;
}
}
return ret;
}
}
后序遍历是在中序遍历的基础上添加一个标志位,确保结点的右孩子已经操作过,如果没有设置标志位,可能会导致结点不停的入栈出栈
总结
二叉树的前中后序遍历都可以借助栈(Stack)来实现,前序遍历相对简单(但要注意在前序遍历中是右孩子先入栈,然后左孩子入栈),后序遍历比较难理解,需要在中序遍历的基础上还要考虑结点是否遍历过。