gzshan

(一)二叉树的前序遍历

题目:144. 二叉树的前序遍历

题目描述:给定一个二叉树,返回它的 前序 遍历(根左右)。

示例:

输入: [1,null,2,3]  
   1
    \
     2
    /
   3 

输出: [1,2,3]

解题思路:

  从二叉树根结点开始,沿左子树一直走到末端(左孩子为空)为止,在走的过程中,访问所遇结点,并依次把所遇结点进栈,当左子树为空时,从栈顶退出某结点,并将指针指向该结点的右孩子。如此重复,直到栈为空或指针为空为止。

代码实现:

//方法一:递归,根左右
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        preorderTraversal(root,res);
        return res;
    }
    public void preorderTraversal(TreeNode root,List<Integer> res){
        if(root==null)
            return ;
        res.add(root.val);
        preorderTraversal(root.left,res);
        preorderTraversal(root.right,res);
    }
}
//方法二:非递归方法
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        if(root==null)
            return res;
        
        Stack<TreeNode> stack=new Stack<>();
        TreeNode p=root;

        while(p!=null || !stack.isEmpty()){
            while(p!=null){
                res.add(p.val);
                stack.push(p);  //进栈
                p=p.left;   //进入左子树
            }
            p=stack.pop();  //退栈
            p=p.right;
        }

        return res;
    }
}

(二)二叉树的中序遍历

题目:94. 二叉树的中序遍历

题目描述:给定一个二叉树,返回它的中序 遍历。

示例:

输入: [1,null,2,3]
   1
    \
     2
    /
   3

输出: [1,3,2]

解题思路:

  从二叉树根结点开始,沿左子树一直走到末端(左孩子为空)为止,在走的过程中,把依次遇到的结点进栈,待左子树为空时,从栈中退出结点并访问,并将指针指向该结点的右孩子。如此重复,直到栈为空或指针为空为止。

代码实现:

//方法一:递归,左根右
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        inorderTraversal(root,res);
        return res;
    }
    public void inorderTraversal(TreeNode root,List<Integer> res){
        if(root==null)
            return ;
        inorderTraversal(root.left,res);
        res.add(root.val);
        inorderTraversal(root.right,res);
    }
}
//方法二:非递归,迭代
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        if(root==null)
            return res;
        
        Stack<TreeNode> stack=new Stack<>();
        TreeNode p=root;

        while(p!=null ||  !stack.isEmpty()){
            while(p!=null){
                stack.push(p);  //进栈
                p=p.left;   //向左
            }
            p=stack.pop();  //弹栈
            res.add(p.val);  //访问
            p=p.right;   //向右
        }

        return res;
    }
}

(三)二叉树的后序遍历

题目:145. 二叉树的后序遍历

题目描述:给定一个二叉树,返回它的 后序 遍历。

示例:

输入: [1,null,2,3]  
   1
    \
     2
    /
   3 

输出: [3,2,1]

解题思路:

  在后序遍历中,当搜索指针指向某一个结点时,不能马上进行访问,而先要遍历左子树,所以此结点应先进栈保存,当遍历完它的左子树后,再次回到该结点,还不能访问它,还需先遍历其右子树,所以该结点还必须再次进栈,只有等它的右子树遍历完后,再次退栈时,才能访问该结点。为了区分同一结点的两次进栈,引入一个栈次数的标志,一个元素第一次进栈标志为0,第二次进栈标志为1,并将标志存入另一个栈中,当从标志栈中退出的元素为1时,访问结点。

代码实现:

//方法一:递归,左右根
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        if(root==null)
            return res;
        postorderTraversal(root,res);
        return res;
    }
    public void postorderTraversal(TreeNode root,List<Integer> res){
        if(root==null)
            return;
        postorderTraversal(root.left,res);
        postorderTraversal(root.right,res);
        res.add(root.val);
    }
}

//方法二:非递归
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        if(root==null)
            return res;
        
        Stack<TreeNode> stack1=new Stack<>(); //栈1存放结点
        Stack<Integer> stack2=new Stack<>(); //栈2存放进栈次数的标志
        TreeNode p=root;

        do{
            while(p!=null){
                stack1.push(p);
                stack2.push(0);
                p=p.left;
            }

            if(!stack1.isEmpty()){
                int num=stack2.pop();
                p=stack1.pop();
                if(num==0){
                    stack1.push(p);
                    stack2.push(1);
                    p=p.right;
                }
                else{
                    res.add(p.val);
                    p=null;
                }
            }
        }while(!stack1.isEmpty());

        return res;
    }
}

总结:

  二叉树的深度优先遍历是二叉树题目中最基本的算法,很多算法都基于深度优先遍历进行变形,其中递归解法相对很简单,特别是对非递归的迭代方法,基于栈是基础,要着重理解。

分类:

技术点:

相关文章: