zoukankan      html  css  js  c++  java
  • 【LeetCode】二叉树的深度优先遍历(前、中、后)

    (一)二叉树的前序遍历

    题目: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;
        }
    }
    

    总结:

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

  • 相关阅读:
    selenuim
    selenium
    selenium
    selenium
    【OSG】 报错:丢失osg100-osgDB.dll
    无法启动此程序,因为计算机中丢失 zlibd.dll【OSG】
    无法打开mfc120.lib
    jquery中的$("#id")与document.getElementById("id")的区别
    arcgis api for javascript 各个版本的SDK下载
    ajax与servlet交互(通过JSON),JAVA的arraylist传到前端的方法
  • 原文地址:https://www.cnblogs.com/gzshan/p/12634231.html
Copyright © 2011-2022 走看看