数据结构——二叉树前序、中序、后序及层次四种遍历(java语言版)

本文详细介绍了二叉树的前序、中序、后序及层次遍历方法,包括递归与非递归实现,并提供了完整的代码示例。

前言

前序、中序、后序方式可以使用递归和非递归方式,这里将都一一举例,层次遍历时有两种方法,第一种方法只是简单的遍历出来,第二种方法是用一个集合将他每层内容包含,作用是让它分了组,可以知道是第几层。
值得注意的是:我是先将每一个方法先单独写出来,最后附上完整的代码(所有方式都有哦)想先知道结果的可以直接复制先测试。
我们测试的树图片:
在这里插入图片描述

前序遍历

首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树,如果二叉树为空则返回。
前序遍历:ABDEGCF

递归方式

	 //递归前序遍历  根左右
    private static void preOrder(TreeNode root){
        System.out.print(root.val);
        if (root.left!=null) preOrder(root.left);
        if (root.right!=null) preOrder(root.right);
    }

非递归方式

通过栈来实现。

//非递归前序遍历   根左右
    private static void preOrder1(TreeNode root){
       if (root==null)return;
        Stack<TreeNode>stack=new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()){
            TreeNode node =stack.pop();
            System.out.print(node.val);
            //因为是一个栈,先进后出,所以右子结点先进入栈,在左子结点进入
            if (node.right!=null) stack.push(node.right);
            if (node.left!=null) stack.push(node.left);
        }
    }

中序遍历

中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。若二叉树为空则结束返回,否则: 1.中序遍历左子树
2.访问根结点 3.中序遍历右子树
中序遍历:DBGEACF

递归方式

//递归中序遍历   左根右
    private static void midOrder(TreeNode root){
        //直到找到最左边的结点才输出,即:D结点
        if (root.left!=null) midOrder(root.left);
        System.out.print(root.val);
        if (root.right!=null) midOrder(root.right);
    }

非递归方式

通过栈来实现。

 //非递归中序遍历
    private static void midOrder1(TreeNode root){
        if (root==null)return;
        Stack<TreeNode>stack=new Stack<>();
        //创建一个中间节点,保存树中节点值
        TreeNode node1=root;
        //两个条件栈不为空,和中间结点不为空,二者满足其一即可
        while (!stack.isEmpty()||node1!=null){
           while(node1!=null){
               stack.push(node1);
               //一直往左边找,有就把它压入栈中,当没有时node1=null
               node1=node1.left;
           }
           //当没有node1=null时,打印出当前栈顶元素
            TreeNode node2=stack.pop();
            System.out.print(node2.val);
            //查看node2是否右子结点有值
            if (node2.right!=null)node1=node2.right;
        }
    }

后序遍历

首先遍历左子树,然后遍历右子树,最后访问根结点,在遍历左、右子树时,仍然先遍历左子树,然后遍历右子树,最后遍历根结点。
后序遍历:DGEBFCA

递归方式

//递归后序遍历    左右根
    private static void postOrder(TreeNode root){
        if (root.left!=null) postOrder(root.left);
        if (root.right!=null) postOrder(root.right);
        System.out.print(root.val);
    }

非递归方式

前序遍历是: 根左右 调换左右子结点进栈位置为: 根右左
在通过输入一个新栈中,在输出来就是:左右根(栈先进后出)

    //非递归后序遍历    左右根
    private static void postOrder1(TreeNode root){
        if (root==null)return;
        Stack<TreeNode>stack=new Stack<>();
        //新栈:答案的逆序
        Stack<TreeNode>stack2=new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()){
            TreeNode node =stack.pop();
            //将值压入新栈
            stack2.push(node);
            //调换了左右子结点进栈的位置
            if (node.left!=null) stack.push(node.left);
            if (node.right!=null) stack.push(node.right);
        }
        //输出新栈的内容
        while (!stack2.isEmpty()){
            System.out.print(stack2.pop().val);
        }
    }

层序遍历

二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推
遍历方法:层序遍历是通过一个队列来实现的,先让根节点入队,当根节点出队的时候,看是否有左右子结点,有就让其入队,之后就是判断当前要出队的结点是否有左右子结点,有就入队,没有就继续输出队首元素。
在这里插入图片描述

层序遍历方式一

层序遍历方式一:ABCDEFG

//层序遍历方式一
        private static void dfs(TreeNode root){
            if (root==null)return;
            //队列
            Queue<TreeNode>queue=new LinkedList<>();
            //当前结点入队
            queue.add(root);
            while(!queue.isEmpty()){
                //队列首元素出队
                TreeNode node1=queue.poll();
                System.out.print(node1.val);
                //判断是否有左右子结点,有就入队
                if (node1.left!=null)queue.add(node1.left);
                if (node1.right!=null)queue.add(node1.right);
            }
        }

层序遍历方式 二

层序遍历方式二(分组输出):[A][B, C][D, E, F][G]

//层序遍历方式二
    private static List<List<String>> dfs2(TreeNode root){
        //保存temp的内容,输出是三个集合List <String>,起到分组的作用
        List<List<String>>res=new ArrayList<>();
        //队列
        Queue<TreeNode>queue=new LinkedList<>();
        queue.add(root);
        //用List <String>temp保存每一层的结果
        List <String>temp;
        while(!queue.isEmpty()){
            int size=queue.size();
            temp=new ArrayList<>();
            while (size-->0){
                TreeNode node1=queue.poll();
                temp.add(node1.val);
                if (node1.left!=null)queue.add(node1.left);
                if (node1.right!=null)queue.add(node1.right);
            }
            res.add(temp);
        }
        return res;
    }

完整代码

package tree;

import java.util.*;
@SuppressWarnings("all")//抑制警告(主要是自己不想看到哈哈)
public class My_tree {
    public static void main(String[] args) {
        //这一部分是创建结点并且设置好他们的左右结点
        TreeNode nodeA=new TreeNode("A");
        TreeNode nodeB=new TreeNode("B");
        TreeNode nodeC=new TreeNode("C");
        TreeNode nodeD=new TreeNode("D");
        TreeNode nodeE=new TreeNode("E");
        TreeNode nodeF=new TreeNode("F");
        TreeNode nodeG=new TreeNode("G");

        nodeA.left=nodeB;
        nodeA.right=nodeC;
        nodeB.left=nodeD;
        nodeB.right=nodeE;
        nodeE.left=nodeG;
        nodeC.right=nodeF;

        System.out.print("递归前序遍历:");
        preOrder(nodeA);
        System.out.println();
        System.out.print("递归中序遍历:");
        midOrder(nodeA);
        System.out.println();
        System.out.print("递归后序遍历:");
        postOrder(nodeA);
        System.out.println();
        System.out.print("非递归前序遍历:");
        preOrder1(nodeA);
        System.out.println();
        System.out.print("非递归中序遍历:");
        midOrder1(nodeA);
        System.out.println();
        System.out.print("非递归后序遍历:");
        postOrder1(nodeA);
        System.out.println();
        System.out.print("层序遍历方式一:");
        dfs(nodeA);
        System.out.println();
        System.out.print("层序遍历方式二(分组输出):");
        //打印返回集合里面的东西
        List<List<String>> list= dfs2(nodeA);
        for (int i = 0; i <4; i++) {
            System.out.print(list.get(i));
        }
    }
    //递归前序遍历  根左右
    private static void preOrder(TreeNode root){
        System.out.print(root.val);
        if (root.left!=null) preOrder(root.left);
        if (root.right!=null) preOrder(root.right);
    }
    //非递归前序遍历   根左右
    private static void preOrder1(TreeNode root){
       if (root==null)return;
        Stack<TreeNode>stack=new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()){
            TreeNode node =stack.pop();
            System.out.print(node.val);
            //因为是一个栈,先进后出,所以右子结点先进入栈,在左子结点进入
            if (node.right!=null) stack.push(node.right);
            if (node.left!=null) stack.push(node.left);
        }
    }
     //递归中序遍历   左根右
    private static void midOrder(TreeNode root){
        //直到找到最左边的结点才输出,即:D结点
        if (root.left!=null) midOrder(root.left);
        System.out.print(root.val);
        if (root.right!=null) midOrder(root.right);
    }
    //非递归中序遍历
    private static void midOrder1(TreeNode root){
        if (root==null)return;
        Stack<TreeNode>stack=new Stack<>();
        //创建一个中间节点,保存树中节点值
        TreeNode node1=root;
        //两个条件栈不为空,和中间结点不为空,二者满足其一即可
        while (!stack.isEmpty()||node1!=null){
           while(node1!=null){
               stack.push(node1);
               //一直往左边找,有就把它压入栈中,当没有时node1=null
               node1=node1.left;
           }
           //当没有node1=null时,打印出当前栈顶元素
            TreeNode node2=stack.pop();
            System.out.print(node2.val);
            //查看node2是否右子结点有值
            if (node2.right!=null)node1=node2.right;
        }
    }

     //递归后序遍历    左右根
    private static void postOrder(TreeNode root){
        if (root.left!=null) postOrder(root.left);
        if (root.right!=null) postOrder(root.right);
        System.out.print(root.val);
    }
    //非递归后序遍历    左右根
    //前序遍历是: 根左右  调换左右子结点进栈位置为: 根右左
    //在通过输入一个新栈中,在输出来就是:左右根(栈先进后出)
    private static void postOrder1(TreeNode root){
        if (root==null)return;
        Stack<TreeNode>stack=new Stack<>();
        //新栈:答案的逆序
        Stack<TreeNode>stack2=new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()){
            TreeNode node =stack.pop();
            //将值压入新栈
            stack2.push(node);
            //调换了左右子结点进栈的位置
            if (node.left!=null) stack.push(node.left);
            if (node.right!=null) stack.push(node.right);
        }
        //输出新栈的内容
        while (!stack2.isEmpty()){
            System.out.print(stack2.pop().val);
        }
    }
        //层序遍历方式一
        private static void dfs(TreeNode root){
            if (root==null)return;
            //队列
            Queue<TreeNode>queue=new LinkedList<>();
            queue.add(root);
            while(!queue.isEmpty()){
                TreeNode node1=queue.poll();
                System.out.print(node1.val);
                if (node1.left!=null)queue.add(node1.left);
                if (node1.right!=null)queue.add(node1.right);
            }
        }
    //层序遍历方式二
    private static List<List<String>> dfs2(TreeNode root){
        List<List<String>>res=new ArrayList<>();
        //队列
        Queue<TreeNode>queue=new LinkedList<>();
        queue.add(root);
        List <String>temp;
        while(!queue.isEmpty()){
            int size=queue.size();
            temp=new ArrayList<>();
            while (size-->0){
                TreeNode node1=queue.poll();
                temp.add(node1.val);
                if (node1.left!=null)queue.add(node1.left);
                if (node1.right!=null)queue.add(node1.right);
            }
            res.add(temp);
        }
        return res;
    }





}
//定义一个类,包含它的值和左右结点
class TreeNode {
 String val;
 public TreeNode left;
 public TreeNode right;
    //空参构造方法,赋予当前结点值
    public TreeNode(String val) {
        this.val = val;
    }

}

完整代码运结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yjg_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值