树、二叉树的前中后层序遍历(递归、非递归Java实现)

二叉树的非递归遍历:Java语言实现 1 前言       上一篇写了《二叉树的递归遍历:Java语言实现》,现在用java实现下二叉树的非递归遍历。2 二叉树的非递归遍历2.1 先序遍历       根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对于任一结点,其可看做是根结点,因此可以直接访问。访问完之后,若其左孩子不为空,按相同规则访问它的左子树;当访问其左子树时,再访问它的右子树。因此其处理过程如下:对... 阅读详情

1. 二叉树的前中后序遍历(递归,非递归)以及层序遍历

1.1 二叉树前中后遍历的递归解法

树的前中后序的遍历这个是很常见的问题,其递归做法相对简单,这里直接贴代码:

    // 前序遍历
    public static void preorder(TreeNode treeNode) {
        if (treeNode == null) return;
        System.out.print(treeNode.val + " ");
        preorder(treeNode.left);
        preorder(treeNode.right);
    }
    
    // 中序遍历
    public static void inorder(TreeNode treeNode) {
        if (treeNode == null) return;
        inorder(treeNode.left);
        System.out.print(treeNode.val + " ");
        inorder(treeNode.right);
    }

    // 后序遍历
    public static void postorder(TreeNode treeNode) {
        if (treeNode == null) return;
        postorder(treeNode.left);
        postorder(treeNode.right);
        System.out.print(treeNode.val + " ");
    }

从上面的代码中可以看到,树的前中后序遍历代码结构基本相同,差距只要在何时输出根值,前序遍历一遍历到节点时,先输出根植,中序是遍历完左子节点,后序是最后才输出,理解起来很容易。

1.2 二叉树前中后遍历的非递归解法

接下来我们来看看如何用非递归的方式,实现前中后序遍历:

1.2.1 非递归的前序遍历:(LeetCode 144)

在这里插入图片描述
前序遍历:34、35、29、25、33、42、40、39
根据树前序遍历的特点,我们很容易将其与栈的特点相结合,这里简单附上代码:

    // 前序遍历的非递归解法
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> lists = new ArrayList<>();
        if (root == null) return lists;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        TreeNode temp = null;
        while (!stack.isEmpty()) {
            temp = stack.pop();
            lists.add(temp.val);
            // 这里注意,要先压入右子节点,再压入左节点
            if (temp.right != null) {
                stack.push(temp.right);
            }
            if (temp.left != null) {
                stack.push(temp.left);
            }
        }
        return lists;
    }

1.2.2 非递归的中序遍历:(LeetCode 94)

在这里插入图片描述
中序遍历:25、29、35、33、34、40、42、39
这个实现的思路,是按照中序遍历的过程:先找到最左的子树,然后返回其父节点,然后遍历右子树,这个返回的动作可以让我们联想到使用栈这个数据结构,实现代码:

    // 二叉树非递归的中序遍历
    public List<Integer> inorderTraversal(TreeNode root) {
    	if (root == null) {
    		return new ArrayList<>();
    	}
        Stack<TreeNode> stack = new Stack<>();
        TreeNode node = root, temp = null;
        List<Integer> lists = new ArrayList<>();
        
        // 判断条件:所有栈为空,且节点指向为空,即所有节点已经完成遍历
        while (!stack.isEmpty() || node != null) {
            // 向左搜索,寻找最左的节点,即中序遍历的第一个节点
            while (node != null) {
                stack.add(node);
                node = node.left;
            }
            // 对每一个节点进行判断
            if (!stack.empty()) {
                // 获取当前节点
                temp = stack.pop();
                // 遍历该节点
                lists.add(temp.val);
                // 如果该节点为内部节点,则按中序遍历的顺序,遍历其右子节点
                node = temp.right;
            }
        }
        return lists;
    }

1.2.3 非递归的后序遍历:(LeetCode 145)

非递归的后序遍历比较麻烦,但如果我们发现以下规律,就会变得简单:
例如:
在这里插入图片描述
对于后序遍历,结果:25、29、33、35、40、39、42、34
后序遍历的方法,就是先左子树,后右子树,再最后根节点,如果反过来,顺序就变成了:先根节点,后右子树,再左子树,是不是跟先序遍历有点像呢?就是先序遍历根节点遍历之后,下一个是遍历左子树,而下一个再遍历右子树。我们按这种反过来的顺序进行遍历,结果:34、42、39、40、35、33、29、25。很容易发现跟上面后序遍历的结果刚好相反。
因此,后序遍历可以变为:先遍历根节点,后遍历右子树,再遍历左子树,的结果的逆序,我们修改先序遍历的代码,可以得到:

    public List<Integer> postorderTraversal_(TreeNode root) {
        LinkedList<Integer> lists = new LinkedList<>();
        if (root == null) return lists;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        TreeNode temp = null;
        while (!stack.isEmpty()) {
            temp = stack.pop();
            lists.addFirst(temp.val);
            if (temp.left != null) {
                stack.push(temp.left);
            }
            if (temp.right != null) {
                stack.push(temp.right);
            }
        }
        return lists;
    }

这里使用了LinkedList,目的是为了让我们每一次插入结果,都可以插入到当前结果的最前面,相当于实现逆序的过程。

1.3 层序遍历:(LeetCode 102、103、107)

层序遍历,就是按照每一层的顺序,一层一层的访问,例如:
在这里插入图片描述
层序遍历的结果为:[[34], [35, 42], [29, 33, 40, 39], [25]]

    // 根据层序遍历的特点,我们很容易想到使用队列,利用广度优先遍历的方式,进行遍历
    public List<List<Integer>> levelOrder(TreeNode root) {
        if (root == null) {
            return new ArrayList<>();
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        List<List<Integer>> lists = new ArrayList<>();
        List<Integer> arrays = new ArrayList<>();
        TreeNode temp = null;
        while (!queue.isEmpty()) {
            int n = queue.size();
            // 这里通过读取队列的元素,获取这一层有多少个元素
            for (int i = 0; i < n; i++) {
                temp = queue.poll();
                arrays.add(temp.val);
                if (temp.left != null) {
                    queue.add(temp.left);
                }
                if (temp.right != null) {
                    queue.add(temp.right);
                }
            }
            // 将每一层的数据放入到链表中
            lists.add(new ArrayList<>(arrays));
            arrays.clear();
        }
        return lists;
    }

2 树的前中后层序遍历

上面讲的都是二叉树,那对于一棵普通的树,其前中后序遍历,是如何呢:

2.1 前序遍历:(LeetCode 589)

	// 递归实现
	public List<Integer> preorder(Node root) {
        List<Integer> result = new ArrayList<>();
        if (root == null) {
            return result;
        }
        helper(result, root);
        return result;
    }

    private void helper(List<Integer> list, Node root) {
        list.add(root.val);
        for (Node node: root.children
             ) {
            helper(list, node);
        }
    }
    
    // 非递归的N叉树前序遍历
    public List<Integer> preorder(Node root) {
   		List<Integer> result = new ArrayList<>();
        if (root == null) {
            return result;
        }

        Stack<Node> stack = new Stack<>();
        stack.add(root);
        while (!stack.isEmpty()) {
            Node temp = stack.pop();
            result.add(temp.val);
			// 注意这里要入栈的顺序是从右边最后一个子树开始
            for (int i = temp.children.size() - 1; i >= 0; i--) {
                stack.add(temp.children.get(i));
            }
        }

        return result;

2.2 中序遍历:

发现 LeetCode 没有N叉树的中序遍历,关于中序遍历,我们要注意:先遍历最左的一个子树,然后根节点,然后才是遍历其他子节点。
在这里插入图片描述
遍历结果:5、3、6、1、2、4

2.3 后序遍历:(LeetCode 590)

在这里插入图片描述
后序遍历:5、6、3、2、4、1
规律:遍历每个节点,先遍历节点的子节点,最后输入根节点。
这里可以参考二叉树的后序遍历,也使用逆转考虑的方法,先遍历根节点,然后按逆序访问孩子节点,最后将结果进行逆序处理。

    // 递归实现:
    public List<Integer> postorder(Node root) {
        List<Integer> result = new ArrayList<>();
        if (root == null) {
            return result;
        }
        helper(result, root);
        return result;
    }

    private void helper(List<Integer> list, Node root) {
        for (Node node : root.children
        ) {
            helper(list, node);
        }
        list.add(root.val);
    }

	// 非递归:
	public List<Integer> postorder(Node root) {
        List<Integer> list = new ArrayList<>();
        if (root == null) return list;
        
		Stack<Node> stack = new Stack<>();
        stack.add(root);
        while (!stack.isEmpty()) {
            Node temp = stack.pop();
            result.add(temp.val);
            stack.addAll(temp.children);
        }
        // 将结果进行逆序
        Collections.reverse(list);
        return list;
    }

2.4 层序遍历:(LeetCode 429)

    // N叉树的层序遍历
    public List<List<Integer>> levelOrder(Node root) {
        List<List<Integer>> lists = new ArrayList<>();
        if (root == null) {
        	return lists;
        }
        
        Queue<Node> queue = new LinkedList<>();
        queue.add(root);
        List<Integer> list = new ArrayList<>();
        Node temp = null;
        while (!queue.isEmpty()) {
            int levelSize = queue.size();
            for (int i = 0; i < levelSize; i++) {
                temp = queue.poll();
                // 跟二叉树的层序遍历的区别在于,这里加入的是所有子树
                queue.addAll(temp.children);
                list.add(temp.val);
            }
            lists.add(new ArrayList<>(list));
            list.clear();
        }
        
        return lists;
    }
二叉树 层序遍历 java实现 课程设计 改编自csdn上的一份流行版本,增加层序遍历,增加大量注释,附有工程文件、课程设计文档。 立即下载

相关推荐

LVGL 离线字体转换lv_font_conv本地安装

LVGL FONT CONV 离线版本

liu132641的专栏 3382

Java实现树的层序遍历

文章目录前言实现Java 实现层序遍历一Java 实现层序遍历二总结 前言 最近居家办公,我们这周工作量比较少,于是我早早的进入了摸鱼时光,但是看到女朋友还在那辛苦的处理数据,一遍遍的重复工作。心想为何不写个程序,让女票也解放出来,一起快乐的摸鱼呢。 于是研究了下女友的工作,主要是从网站的一个画布流程上复制文本到Excel,并且将文本编号,指明下一个节点是哪个文本。 打开浏览器,F12 看了下响应数据,就是普通的 JSON 格式。 一共不到10个流程,也就懒得再去用程序爬取数据了,手动copy数据到文本文件

pzzhao的博客 2518

清理异常值(MAD:绝对中位差)

清理异常数据: 中位数绝对偏差(MAD):用来描述单变量样本在定量数据中可变的一种标准 在统计学中,绝对中位差是刻画一元数据样本变化的一个鲁棒度量。由公式可以看出,其求解还算简单,给定一个数据样本集,首先求其中位数,然后求原始数据减去中位数的绝对值从而形成一个新的数据样本,再求新的数据样本的中位数即为绝对中位差。比如说有一个数据样本集X={2 3 8 7 9 6 4},这时候数据的中位数是6,原...

spider_man 1万+

二叉树的的前中后,层次遍历(java版本)

介绍如何使用递归来实现二叉树的前中后,层次遍历

qq_56320180的博客 1872

嵌入式开发语言-C语言编程

C语言编程概述环境在Windows上构建C语言的环境安装在Mac上构建C语言的环境安装 概述 “C语言”被称为适合嵌入式系统开发的编程语言之一。 C语言在一般的编程中也是熟悉的开发语言,但实际上,如果试着使用C语言制作微型计算机的控制程序等,就必须使用与“普通的C程序”不同的使用方法。 作为一般的C语言的学习方法,使用“printf”“scanf”等标准函数的程序开发是固定的,但这些都是以UNIX和Windows等环境上的应用程序开发为前提的。 对此,没有显示器和键盘的嵌入式系统的微型计算机控制程序,该如何

编程老王 7975

避坑指南:C#用S7NetPlus读写西门子PLC字符串(String/WString)的完整方案

本文详细解析了C#通过S7NetPlus读写西门子PLC字符串(String/WString)的完整方案,包括内存布局、编码差异和字节序处理等关键技术细节。提供了实战优化的代码示例和常见问题排查指南,帮助开发者避免乱码、截断等常见陷阱,提升工业自动化项目的开发效率。

weixin_32956805的博客 320

LEETCODE:二叉树的层序遍历JAVA

给你二叉树的根节点root,返回其节点值的。(即逐层地,从左到右访问所有节点)。root = [1][[1]]root = [][][0, 2000]用一个全局列表 ans 表示所有层,其中 ans.get(deep) 对应第 deep 层的节点值集合。每次递归时,deep 表示当前节点所在的层号(从 0 开始)。如果 ans 的大小不足以容纳当前层(即 ans.size() < deep + 1),就添加一个新的空列表。然后将当前节点的值加入对应层的列表中。

weixin_58628068的博客 1610

UVM和System verilog笔记总结(四)

virtual sequence 即虚seq,用于管理多个实sequence的执行顺序。 下面有三个sequence,此时需要virtual sequence去管理这三个的顺序。 virtual sequence和virtual sequencer需要成对写,使用例化实的sequence和sequencer控制: 此时在virtual sequence里面启动,而不是之前在test.sv里面用default或start函数启动。具体方法如下:先例化 再启动,用 `uvm_do_on 实sequence

weixin_42655118的博客 641

Java 一文详解二叉树的层序遍历

Java 一文详解二叉树的层序遍历

abc123mma的博客 1575

【LangChain编程:从入门到实践】实现多模态代理

【LangChain编程:从入门到实践】实现多模态代理 关键词:LangChain, 多模态代理, 自然语言处理, 机器学习, 知识图谱, 对话系统, 代码生成, AI代理 1. 背景介绍 随着人工智

欢迎来到我的优快云空间!这里聚焦AI大模型应用实战,分享前沿技术、实战案例与开发经验。 578

OpenClaw实战五|企业文档AI助理:对接内部知识库+自动答疑+文档生成,员工自助查资料零等待

企业最大的隐性成本,不是设备、不是房租,而是内部知识的混乱与流失。OpenClaw企业文档AI助理,本质是给企业做了一个7×24小时在线、永不疲倦、精准无误、自动更新的内部知识管家。它不替代HR、行政、IT,而是把他们从无穷无尽的重复问答、机械文档编写里解放出来,去做更有价值的管理、服务、优化工作。对中小企业来说,不用买昂贵的知识库系统、不用招开发、不用做复杂集成,一台私有化服务器,两天就能落地,性价比拉满。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 143

[Java/数据结构]树的基本概念、二叉树的创建和遍历

先看这么一张树的图片,从根延伸出枝干,枝干再继续分成多个叶子,我们把这样的模型抽象出来,称作树。树有一个特殊的节点,也就是根节点,根节点没有前驱。树的子树之间互不相交。除了根节点外,每个节点只有一个前驱(父节点),可以有多个后继。因此树是没有环的。

2501_93882415的博客 415

EtherCAT主站IGH-- 49 -- 搭建xenomai系统及自己的IGH主站

以上就是搭建xenomai系统及自己的IGH主站的内容。有不明白的地方欢迎留言;有建议欢迎留言,我后面编写文档好改进。创作不容,如果文档对您有帮助,记得给个赞。

常驻客栈的博客--嵌入式EtherCAT 3154

二叉树的前序、中序、后序、层序遍历,Java实现(递归、非递归)

关于二叉树的内容,我觉得二叉树最核心的地方就是它的几种遍历方式,基本上所有的问题都是围绕着几种遍历方式来的。因此就在这总结一下这几种遍历方式。 前序遍历 一、简介 前序遍历(DLR),是二叉树遍历的一种,也叫做先根遍历、先序遍历,可记做根左右。 前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树。 若二叉树为空则结束返回,否则...

丸啊~ 6916

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Java实现二叉树的先序、中序、后序、层序遍历(递归+非递归方法),附带自己深入浅出的讲解

本文只涉及了二叉树的先序、中序、后序和层序的递归和非递归遍历。结合自己的经验总结,和简单易懂的图形,深入浅出的进行介绍。

Java Punk 9490

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

java实现二叉树树的非递归遍历

二叉树递归 参考:java使用递归,非递归方式实现二叉树的三种常见遍历方式 代码实现 Node类 public class Node { int data; Node leftChild = null; Node rightChild = null; public Node(int data) { this.data = data; }...

weixin_41826973的博客 855

二叉树的前中后层序遍历(递归、非递归Java实现)

1 二叉树的前中后序递归实现 树的前中后序的遍历这个是很常见的问题,其递归做法相对简单,呜呜,但是刷题的时候好像都要用非递归 //前序遍历 List<Integer> preList = new ArrayList<Integer>(); public List<Integer> preOrder(TreeNode root){ if(root == nul...

努力变得不菜的菜鸡的博客 818

Java数据结构二叉树的前、中、后序遍历和层序遍历(递归和非递归实现)

文章目录二叉树的基本操作-遍历(一)前序遍历(preOrderTraversal)递归实现非递归实现(二)中序遍历递归实现非递归实现(三)后序遍历递归实现非递归实现(四)层序遍历 二叉树的基本操作-遍历 所谓的遍历(Traversal)是指沿着某条搜索路线,依次对树中每个节点均做一次且仅作一次的访问。访问节点后需要进行的操作看具体的问题(比如打印节点内容,数据计算等)。遍历二叉树是其他很多方法的基础,很重要。 二叉树的遍历就前中后和层序遍历四种。前三种有着固定的遍历顺序。 (一)前序遍历(preOrde

zxc的博客 1405

二叉树的遍历(JAVA递归和非递归版)

二叉树的遍历(JAVA递归和非递归版)二叉树二叉树的先序遍历二叉树的中序遍历插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 二叉树 若是对二叉树的基本概念有所遗忘,可参考二叉树百...

Chen_programmer的博客 835

Java实现二叉树的遍历(递归和非递归)

现有一颗如下图所示的二叉树 一、基本概念 (1)先序遍历(深度优先遍历): 前、中、后这三个词是针对根节点的访问顺序而言的 先访问根结点,再访问左子结点,最后访问右子结点。 图中的二叉树的先序遍历的顺序是1 2 4 8 9 5 3 6 7 (2)中序遍历: 先访问左子结点,再访问根结点,最后访问右子结点。 图中的二叉树的中序遍历的顺序是8 4 9 2 5 1 6 3 7 (3)后序遍历: 先访问...

meihuai7538的博客 958

java递归创建二叉树及遍历二叉树

java递归创建二叉树 1.二叉树结点的结构 用C语言的指针概念来看,二叉树的结点中应包括三个域,分别为两个指针域和一个数据域,指针域分别为left域和right域,表示指向二叉树的左右子孩子,数据域(data域)存放该结点本身的数据。 class Node{ Node left; //指向左孩子 Node right; //指向右孩子 int data; //数据域 Node...

swy66的博客 3095

二叉树非递归遍历算法 java_java二叉树的非递归遍历

二叉树的递归遍历比较简单,这里就不聊了。今天主要聊聊二叉树的非递归遍历,主要借助于“栈”后进先出的特性来保存节点的顺序,先序遍历和中序遍历相对来说比较简单,重点理解后序遍历。1. 先看看节点类型://二叉树的节点类型private class Node{int data; //节点值Node leftChild; //左孩子Node rightChild; //右孩子public Node(int...

weixin_39915308的博客 704

【Java BST树 递归和非递归实现】简单理解

BST树 一、基本概念 二叉搜索树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树 二、创建结点类和二叉树类 public class BSTree<T exte...

qq_44682003的博客 659

二叉树遍历四种必会算法(递归遍历、非递归遍历、既不用递归也不用栈遍历(三种深度优先),层序遍历(广度优先))

二叉树遍历四种必会算法(递归遍历、非递归遍历、既不用递归也不用栈遍历(三种深度优先),层序遍历(广度优先)) 采用递归遍历就很简单了,想好前序(左根右)、中序(根左右)、后序(左右根)三种遍历的顺序与终止递归逻辑

带雪老萝卜的博客呢 2069

Java实现二叉树的前序、中序、后序、层序遍历(非递归方法)

Java实现二叉树的前序、中序、后序、层序遍历(非递归方法)   在上一篇博客中,实现了Java中二叉树的四种遍历方式的递归实现,接下来,在此实现Java中非递归实现二叉树的前序、中序、后序、层序遍历,在非递归实现中,借助了栈来帮助实现遍历。前序和中序比较类似,也简单一些,但是后序遍历需要两个栈来进行辅助,稍微复杂一些,层序遍历中借助了一个队列来进行实现。   同样是那棵二叉树 前序...

没有伞的孩子必须努力奔跑!—小林 422
上一篇: 链表相关题目总结(含leetcode链表题Java代码)
下一篇: 【LeetCode 105 106 889】重建二叉树(给定树的前中后序遍历方式中的两种来重建二叉树)
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值