1. 程式人生 > 其它 >二叉樹之前序遍歷、中序遍歷、後續遍歷

二叉樹之前序遍歷、中序遍歷、後續遍歷

技術標籤:leetcode演算法leetcode樹遍歷

刷leetcode的時候,看到三道題:145. 二叉樹的後序遍歷、94. 二叉樹的中序遍歷、144. 二叉樹的前序遍歷。正好趁著這三道題,回顧一下二叉樹的遍歷演算法。

  • 二叉樹的前序遍歷:先遍歷根,再遍歷左子樹,再遍歷右子樹;
  • 二叉樹的中序遍歷:先遍歷左子樹,再遍歷根,再遍歷右子樹;
  • 二叉樹的後序遍歷:先遍歷左子樹,再遍歷右子樹,再遍歷根;

前中後遍歷是以根的順序區分的。
下面按照leetcode題目要求給出每個遍歷演算法的遞迴和非遞迴程式。
在這三個題目裡面,樹節點都是使用TreeNode表示的,程式碼如下:

public class
TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } }

下面的程式碼假設輸入的為下圖的樹:
在這裡插入圖片描述

144. 二叉樹的前序遍歷


前序遍歷的遞迴程式。

public class PreorderTraversal {
    public static void main(String[] args)throws Exception {
        PreorderTraversal code=new PreorderTraversal();
        TreeNode right=new TreeNode(2,new TreeNode(3),null);
        TreeNode root=new TreeNode(1,null,right);
        System.out.println(
code.preorderTraversal(root)); } public List<Integer> preorderTraversal(TreeNode root) { List<Integer> res=new ArrayList<>(); traverByRecursion(root,res); return res; } //遞迴遍歷 private void traverByRecursion(TreeNode root,List<Integer> list) { if(root==null){ return ; } list.add(root.val);//先遍歷根 this.traverByRecursion(root.left,list);//遍歷左子樹 this.traverByRecursion(root.right,list);//遍歷右子樹 } }

前序遍歷的非遞迴程式。

public class PreorderTraversal {
    public static void main(String[] args)throws Exception {
        PreorderTraversal code=new PreorderTraversal();
        TreeNode right=new TreeNode(2,new TreeNode(3),null);
        TreeNode root=new TreeNode(1,null,right);
        System.out.println(code.preorderTraversal(root));
    }
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        traverByNotRecursion(root,res);
        return res;
    }
    //非遞迴遍歷
    private void traverByNotRecursion(TreeNode root,List<Integer> list) {
        if(root==null){
            return ;
        }
        //使用stack模擬計算機棧
        List<TreeNode> stack=new ArrayList<>();
        stack.add(root);
        do{
            TreeNode node=stack.remove(stack.size()-1);
            list.add(node.val);//遍歷根
            if(node.right!=null){
                stack.add(node.right);//新增右子樹
            }
            if(node.left!=null){
                stack.add(node.left);//新增左子樹
            }
        }while(stack.size()!=0);
    }
}

94. 二叉樹的中序遍歷
中序遍歷的遞迴程式。

public class InorderTraversal {
    public static void main(String[] args)throws Exception {
        InorderTraversal code=new InorderTraversal();
        TreeNode right=new TreeNode(2,new TreeNode(3),null);
        TreeNode root=new TreeNode(1,null,right);
        System.out.println(code.inorderTraversal(root));
    }
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        traverByRecursion(root,res);
        return res;
    }
    //遞迴遍歷
    private void traverByRecursion(TreeNode root, List<Integer> list) {
        if(root==null) {
            return;
        }
        this.traverByRecursion(root.left,list);//遍歷左子樹
        list.add(root.val);//遍歷根
        this.traverByRecursion(root.right,list);//遍歷右子樹
    }
}

中序遍歷的非遞迴程式。

public class InorderTraversal {
    public static void main(String[] args)throws Exception {
        InorderTraversal code=new InorderTraversal();
        TreeNode right=new TreeNode(2,new TreeNode(3),null);
        TreeNode root=new TreeNode(1,null,right);
        System.out.println(code.inorderTraversal(root));
    }
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        traverByNotRecursion(root,res);
        return res;
    }
    //非遞迴遍歷
    private void traverByNotRecursion(TreeNode root, List<Integer> list) {
        if(root==null){
            return ;
        }
        //使用stack模擬計算機棧
        List<TreeNode> stack=new ArrayList<>();
        while(!stack.isEmpty()||root!=null){
            if(root!=null){
                stack.add(root);
                root=root.left;
            }else{
                root=stack.remove(stack.size()-1);
                list.add(root.val);
                root=root.right;
            }
        }
    }
}

145. 二叉樹的後序遍歷
後序遍歷的遞迴程式。

public class PostorderTraversal {
    public static void main(String[] args)throws Exception {
        PostorderTraversal code=new PostorderTraversal();
        TreeNode right=new TreeNode(2,new TreeNode(3),null);
        TreeNode root=new TreeNode(1,null,right);
        System.out.println(code.postorderTraversal(root));
    }
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        traverByRecursion(root,res);
        return res;
    }
    //遞迴遍歷
    private void traverByRecursion(TreeNode root, List<Integer> list) {
        if(root==null) {
            return;
        }
        this.traverByRecursion(root.left,list);//遍歷左子樹
        this.traverByRecursion(root.right,list);//遍歷右子樹
        list.add(root.val);//遍歷根
    }
}

後序遍歷的非遞迴程式。

public class PostorderTraversal {
    public static void main(String[] args)throws Exception {
        PostorderTraversal code=new PostorderTraversal();
        TreeNode right=new TreeNode(2,new TreeNode(3),null);
        TreeNode root=new TreeNode(1,null,right);
        System.out.println(code.postorderTraversal(root));
    }
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        traverByNotRecursion(root,res);
        return res;
    }
    //非遞迴遍歷
    private void traverByNotRecursion(TreeNode root, List<Integer> list) {
        if(root==null){
            return ;
        }
        //使用stack模擬計算機棧
        List<TreeNode> stack=new ArrayList<>();
        TreeNode lastNode=null;//記錄最後一次訪問的節點
        while(!stack.isEmpty()||root!=null){
            while(root!=null){
                stack.add(root);
                root=root.left;
            }
            root=stack.get(stack.size()-1);//取棧頂元素
            if(root.right==null||root.right==lastNode){
                stack.remove(stack.size()-1);
                list.add(root.val);
                lastNode=root;
                root=null;
            }else{
                root=root.right;
            }
        }
    }
}