二叉树的遍历(递归方式和非递归方式)

本文介绍了如何在Java中使用递归和非递归方式实现二叉树的前序、中序和后序遍历,包括TreeNode类的定义和TreeTraversal、TreeTraveral2类中的具体实现方法,以及在Test测试类中的应用实例。
摘要由CSDN通过智能技术生成

 创建TreeNode类:

package com.atguigu.binarytree;

public class TreeNode {
    public int val;         //值
    public TreeNode left;   //左孩子
    public TreeNode right;  //右孩子

   //构造器
    //1.叶子节点的构造
    public TreeNode(int val){
        this.val = val;
    }
    //2.非叶子节点的构造
    public TreeNode( TreeNode left, int val,TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }

    @Override
    public String toString(){return String.valueOf(this.val);}
}

创建 TreeTravel类:递归方法

package com.atguigu.binarytree;

public class TreeTraversal {

    //递归方法遍历
    //1.前序遍历:先访问该节点的值,然后前序遍历左子树,最后前序遍历右子树
    static void preorder(TreeNode node) {
        //传递到最里面并返回到上一级的条件
        //每一级又都遵循这个规则:打印值,左子树,右子树
        if (node == null) {
            return;
        }
        System.out.print(node.val + "\t");//值
        //访问左子树(左子树用左孩子表示)
        preorder(node.left);//左
        preorder(node.right);//右
    }

    //2.中序遍历:先中序遍历左子树,然后是访问该节点的值,最后中序遍历右子树
    static void Inorder(TreeNode node) {
        if (node == null) {
            return;
        }
        Inorder(node.left);//左
        System.out.print(node.val + "\t");//值
        Inorder(node.right);//右
    }

    //3.后序遍历:先后序遍历左子树,然后是后序遍历右子树,最后访问该节点的值
    static void postorder(TreeNode node) {
        if (node == null) {
            return;
        }
        postorder(node.left);//左
        postorder(node.right);//右
        System.out.print(node.val + "\t");//值

    }
}

创建TreeTravel2类:非递归方法

package com.atguigu.binarytree;

import java.util.LinkedList;

public class TreeTraveral2 {
    /*
    非递归方法:利用一路往左走到底——再回头——往右走的路径不变的规律,
    变的是取路口的值的时机:
    前序遍历是取 来时 经过路口的值,
    中序遍历是取 回时 经过的路口的值。
    用栈来模拟回去时的路径,利用栈的先进后出原理

    后序遍历:区别于前中序遍历的地方是:
    弹栈要处理完右子树才能弹,不是回来时就立刻弹栈,
    即弹栈的条件为:1.栈顶元素的右子树为null(叶子结点)2.临时变量记住最近一次弹栈的元素,
    若最近一次弹栈的元素与栈顶元素的右孩子相同即当前栈顶元素的右子树已经处理完成(非叶子节点)。
     */

    //前序遍历:进栈打印(来时的路取值)
    static void Pretraveral(TreeNode node){
        LinkedList <TreeNode> stack = new LinkedList<>();//创建栈
        TreeNode curr = node;   //代表当前节点

        while(curr!=null || !stack.isEmpty()){
            if(curr!=null){
                System.out.print(curr.val+ "\t");
                stack.push(curr);       //进栈,为了记住回来的路
                curr = curr.left;       //取左孩子
            }else{
                TreeNode pop  = stack.pop();      //出栈
                curr = pop.right;      //取右孩子
            }
        }
    }
    //中序遍历:出栈打印(来时的路取值)
    static void Intraveral(TreeNode node){
        LinkedList <TreeNode> stack = new LinkedList<>();//创建栈
        TreeNode curr = node;   //代表当前节点

        while(curr!=null || !stack.isEmpty()){
            if(curr!=null){
                stack.push(curr);       //进栈
                curr = curr.left;       //取左孩子
            }else{
                TreeNode pop = stack.pop();     //出栈
                System.out.print(pop.val+ "\t");
                curr = pop.right;      //取右孩子
            }
        }
    }
    //后序遍历:
    static void posttraveral(TreeNode node){
        LinkedList <TreeNode> stack = new LinkedList<>();//创建栈
        TreeNode curr = node;   //代表当前节点
        TreeNode pop = null; //最近一次弹栈的元素

        while(curr!=null || !stack.isEmpty()){
            if(curr!=null){
                stack.push(curr);       //进栈
                curr = curr.left;       //取左孩子
            }else{
                TreeNode peek = stack.peek();//栈顶元素
                if(peek.right == null || peek.right == pop){ //右子树处理完成
                    pop  = stack.pop();      //出栈
                    System.out.print(pop.val+ "\t");
                }else{
                    curr = peek.right; //处理右孩子
                }
            }
        }
    }

    /*
    合并:基于后序遍历改动
     */
    static void traveral(TreeNode node){
        LinkedList <TreeNode> stack = new LinkedList<>();//创建栈
        TreeNode curr = node;   //代表当前节点
        TreeNode pop = null; //临时变量:最近一次弹栈的元素

        while(curr!=null || !stack.isEmpty()){
            if(curr!=null){
                stack.push(curr);       //进栈
                //待处理左子树
                System.out.println("前: " + curr.val); //前序遍历  打印值
                curr = curr.left;
            }else{
                TreeNode peek = stack.peek();//栈顶元素
                //没有右子树
                if(peek.right == null ){
                    System.out.println("中: " +peek.val);//中序遍历  打印值
                    pop  = stack.pop();      //出栈
                    System.out.println("后: " +pop.val);//后序遍历  打印值
                //右子树处理完成
                }else if(peek.right == pop){
                    pop  = stack.pop();      //出栈
                    System.out.println("后: " +pop.val);//后序遍历  打印值
                //待处理右子树
                }else{
                    System.out.println("中: " +peek.val);//中序遍历  打印值
                    curr = peek.right;
                }
            }
        }
    }
}

创建Test测试类 

package com.atguigu.binarytree;

import static com.atguigu.binarytree.TreeTraveral2.*;
import static com.atguigu.binarytree.TreeTraversal.*;

public class TreeTest {
    public static void main(String[] args) {

        TreeNode root = new TreeNode(new TreeNode(new TreeNode(4),2,new TreeNode(7)),
                1,new TreeNode(new TreeNode(5),3,new TreeNode(6)));

        preorder(root);//1 2  4  7  3  5  6
        Inorder(root);//4  2  7  1  5  3  6
        postorder(root);//4  7 2  5  6  3  1

        Pretraveral(root);//1  2  4  7  3  5  6
        Intraveral(root); //4  2  7  1  5  3  6
        posttraveral(root); //4  7 2  5  6  3  1

        traveral(root);
        /*前: 1 前: 2 前: 4 中: 4 后: 4 中: 2 前: 7
        中: 7 后: 7 后: 2 中: 1 前: 3 前: 5 中: 5
        后: 5 中: 3 前: 6 中: 6 后: 6 后: 3 后: 1*/
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值