import java.util.LinkedList; import java.util.Queue; import java.util.Scanner; import java.util.Stac

2023-05-16

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;

/*
  Created by Flynnon on 17-2-25.
  对二叉树的递归定义、前序、后序、中序、层序遍历方法的归纳
 */

/**
 * 定义节点类
 * 为了简单就不定义getter/setter方法了
 */
class Node {
    public int value;
    public Node left;
    public Node right;

    public Node() {
        this(0);
    }

    public Node(int v) {
        this.value = v;
        this.left = null;
        this.right = null;
    }
}

/**
 * 对二叉树进行操作的工具类
 */
class PrintBinaryTree {

    //私有化构造函数
    private PrintBinaryTree(){
        throw new RuntimeException("该工具类不应该被实例化");
    }

    /**
     * 层序遍历二叉树(每一行从左到右,整体上从上到下)
     * 主要思路:利用队列先进先出的性质保存顺序
     * @param root 要遍历的二叉树的根节点
     */
    public static void levelTraversal(Node root) {
        Queue<Node> q = new LinkedList<>();
        q.add(root);
        while (!q.isEmpty()) {
            Node temp = q.poll();
            if (temp != null) {
                System.out.print(temp.value + "  ");
                q.add(temp.left);
                q.add(temp.right);
            }
        }
    }

    /**
     * 前序遍历二叉树(递归) root->left->right
     * @param root 要遍历的二叉树的根节点
     */
    public static void preOrderRec(Node root) {
        if (root == null) {
            return;
        }
        System.out.print(root.value + "  ");
        preOrderRec(root.left);
        preOrderRec(root.right);
    }

    /**
     * 前序遍历二叉树(非递归) root->left->right
     * 主要思路:利用栈保存未打印的节点,然后逐个出栈处理,在此过程中更新栈
     * @param root 要遍历的二叉树的根节点
     */
    public static void preOrderUnRec(Node root) {
        Stack<Node> stack = new Stack<>();
        stack.push(root);
        Node temp;
        while (!stack.empty()) {            //root==null时,只会空转一个循环,因此无需判断
            temp = stack.pop();
            if (temp != null) {
                System.out.print(temp.value + "  ");
                stack.push(temp.right);     //注意:这里的入栈顺序是先right后left
                stack.push(temp.left);      //     以保证从栈中取出时为先left后right
            }
        }
    }

    /**
     * 后序遍历二叉树(递归)
     * @param root 要遍历的二叉树的根节点
     */
    public static void postOrderRec(Node root) {
        if (root == null) {
            return;
        }
        postOrderRec(root.left);
        postOrderRec(root.right);
        System.out.print(root.value + "  ");
    }

    /**
     * 后序遍历二叉树(非递归) left->right->root
     * 主要思路:利用栈保存未打印的节点,然后逐个出栈,进行判断,并根据需要更新栈
     *         因为是处理完左右子树后,再处理根(回溯),所以需要一个记录上一个被打印的节点的引用
     * @param root 要遍历的二叉树的根节点
     */
    public static void postOrderUnRec(Node root) {
        if (root == null) {
            return;
        }
        Stack<Node> stack = new Stack<>();
        stack.push(root);
        //cur:当前节点  pre:上一个被打印的节点
        Node cur, pre = null;
        while (!stack.empty()) {
            //查看(不是取出)栈顶的结点
            cur = stack.peek();
            //如果当前结点没有孩子结点(叶子节点)
            //或者孩子节点都已被打印过(这里不可能出现有两个子节点却只打印了其中一个的情况)
            //说明该打印当前节点了
            if ((cur.left == null && cur.right == null) ||
                    (pre != null && (pre == cur.left || pre == cur.right))) {
                System.out.print(cur.value + "  ");  //打印当前结点
                stack.pop();                         //被打印的节点(当前节点)出栈
                pre = cur;                           //更新pre的值
            } else {
                if (cur.right != null)          //若未轮到当前节点,将当前节点的右节子点、左子节点入栈
                    stack.push(cur.right);      //注意:这里的入栈顺序是先right后left
                if (cur.left != null)           //     以保证从栈中取出时为先left后right
                    stack.push(cur.left);
            }
        }
    }

    /**
     * 中序遍历二叉树(递归)
     * @param root 要遍历的二叉树的根节点
     */
    public static void inOrderRec(Node root) {
        if (root == null) {
            return;
        }
        inOrderRec(root.left);
        System.out.print(root.value + "  ");
        inOrderRec(root.right);
    }

    /**
     * 中序遍历二叉树(非递归) left->root->right
     * 主要思路:模拟递归的过程,将左子树节点不断的压入栈,直到左叶子,然后处理栈顶节点的右子树
     * @param root 要遍历的二叉树的根节点
     */
    public static void inOrderUnRec(Node root) {
        Stack<Node> stack = new Stack<>();
        Node cur = root;                    //纯粹是为了好看...JVM会优化
        while (cur != null || !stack.isEmpty()) {  //当root==null时,不会进入循环,因此无需判断
            while (cur != null) {           //从当前节点开始,从上到下将最左边的那一列节点入栈
                stack.push(cur);
                cur = cur.left;
            }
            cur = stack.pop();              //取出栈顶的节点(该节点左节点为null,因此现在该打印它)
            System.out.print(cur.value + "  ");
            cur = cur.right;                //定位到已打印的节点的右子节点
        }
    }

    /**
     * 前序递归构造二叉树 root->left->right
     * @param scanner 输入流,用于读取节点值
     * @return 构造完成的二叉树的根节点
     */
    public static Node createTreeNode(Scanner scanner) {
        assert scanner!=null;
        Node root = null;                 //声明当前根节点
        int data = scanner.nextInt();
        if (data > 0) {                             //若当前节点存在(这里为了简单以负数为占位符)
            root = new Node(data);                  //使用其它顺序构造二叉树,只需更改这三句即可
            root.left = createTreeNode(scanner);
            root.right = createTreeNode(scanner);
        }
        return root;
    }
}

/**
 * 测试类
 */
public class BinaryTree{
    // 这里以节点值分别为1-7的满二叉树为例
    // 1 2 4 -1 -1 5 -1 -1 3 6 -1 -1 7 -1 -1
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        Node root = PrintBinaryTree.createTreeNode(sc);
        sc.close();
        System.out.print("层序遍历:");
        PrintBinaryTree.levelTraversal(root);
        System.out.print("\n中序递归遍历:");
        PrintBinaryTree.inOrderRec(root);
        System.out.print("\n中序非递归遍历:");
        PrintBinaryTree.inOrderUnRec(root);
        System.out.print("\n前序递归遍历:");
        PrintBinaryTree.preOrderRec(root);
        System.out.print("\n前序非递归遍历:");
        PrintBinaryTree.preOrderUnRec(root);
        System.out.print("\n后序递归遍历:");
        PrintBinaryTree.postOrderRec(root);
        System.out.print("\n后序非递归遍历:");
        PrintBinaryTree.postOrderUnRec(root);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

import java.util.LinkedList; import java.util.Queue; import java.util.Scanner; import java.util.Stac 的相关文章

  • 在 Java 中连接和使用 Cassandra

    我已经阅读了一些关于 Cassandra 是什么以及它可以做什么的教程 但我的问题是如何在 Java 中与 Cassandra 交互 教程会很好 如果可能的话 有人可以告诉我是否应该使用 Thrift 还是 Hector 哪一个更好以及为什
  • Spring Batch 多线程 - 如何使每个线程读取唯一的记录?

    这个问题在很多论坛上都被问过很多次了 但我没有看到适合我的答案 我正在尝试在我的 Spring Batch 实现中实现多线程步骤 有一个包含 100k 条记录的临时表 想要在 10 个线程中处理它 每个线程的提交间隔为 300 因此在任何时
  • 为什么 i++ 不是原子的?

    Why is i Java 中不是原子的 为了更深入地了解 Java 我尝试计算线程中循环的执行频率 所以我用了一个 private static int total 0 在主课中 我有两个线程 主题 1 打印System out prin
  • 如何在 Play java 中创建数据库线程池并使用该池进行数据库查询

    我目前正在使用 play java 并使用默认线程池进行数据库查询 但了解使用数据库线程池进行数据库查询可以使我的系统更加高效 目前我的代码是 import play libs Akka import scala concurrent Ex
  • Java JDBC:更改表

    我希望对此表进行以下修改 添加 状态列 varchar 20 日期列 时间戳 我不确定该怎么做 String createTable Create table aircraft aircraftNumber int airLineCompa
  • 在 HTTPResponse Android 中跟踪重定向

    我需要遵循 HTTPost 给我的重定向 当我发出 HTTP post 并尝试读取响应时 我得到重定向页面 html 我怎样才能解决这个问题 代码 public void parseDoc final HttpParams params n
  • 制作一个交互式Windows服务

    我希望我的 Java 应用程序成为交互式 Windows 服务 用户登录时具有 GUI 的 Windows 服务 我搜索了这个 我发现这样做的方法是有两个程序 第一个是服务 第二个是 GUI 程序并使它们进行通信 服务将从 GUI 程序获取
  • Android:捕获的图像未显示在图库中(媒体扫描仪意图不起作用)

    我遇到以下问题 我正在开发一个应用程序 用户可以在其中拍照 附加到帖子中 并将图片保存到外部存储中 我希望这张照片也显示在图片库中 并且我正在使用媒体扫描仪意图 但它似乎不起作用 我在编写代码时遵循官方的Android开发人员指南 所以我不
  • 无法展开 RemoteViews - 错误通知

    最近 我收到越来越多的用户收到 RemoteServiceException 错误的报告 我每次给出的堆栈跟踪如下 android app RemoteServiceException Bad notification posted fro
  • JavaMail 只获取新邮件

    我想知道是否有一种方法可以在javamail中只获取新消息 例如 在初始加载时 获取收件箱中的所有消息并存储它们 然后 每当应用程序再次加载时 仅获取新消息 而不是再次重新加载它们 javamail 可以做到这一点吗 它是如何工作的 一些背
  • 我可以使用 HSQLDB 进行 junit 测试克隆 mySQL 数据库吗

    我正在开发一个 spring webflow 项目 我想我可以使用 HSQLDB 而不是 mysql 进行 junit 测试吗 如何将我的 mysql 数据库克隆到 HSQLDB 如果您使用 spring 3 1 或更高版本 您可以使用 s
  • 从 127.0.0.1 到 2130706433,然后再返回

    使用标准 Java 库 从 IPV4 地址的点分字符串表示形式获取的最快方法是什么 127 0 0 1 到等效的整数表示 2130706433 相应地 反转所述操作的最快方法是什么 从整数开始2130706433到字符串表示形式 127 0
  • getResourceAsStream() 可以找到 jar 文件之外的文件吗?

    我正在开发一个应用程序 该应用程序使用一个加载配置文件的库 InputStream in getClass getResourceAsStream resource 然后我的应用程序打包在一个 jar文件 如果resource是在里面 ja
  • 总是使用 Final?

    我读过 将某些东西做成最终的 然后在循环中使用它会带来更好的性能 但这对一切都有好处吗 我有很多地方没有循环 但我将 Final 添加到局部变量中 它会使速度变慢还是仍然很好 还有一些地方我有一个全局变量final 例如android Pa
  • 如何在控制器、服务和存储库模式中使用 DTO

    我正在遵循控制器 服务和存储库模式 我只是想知道 DTO 在哪里出现 控制器应该只接收 DTO 吗 我的理解是您不希望外界了解底层域模型 从领域模型到 DTO 的转换应该发生在控制器层还是服务层 在今天使用 Spring MVC 和交互式
  • 声明的包“”与预期的包不匹配

    我可以编译并运行我的代码 但 VSCode 中始终显示错误 早些时候有一个弹出窗口 我不记得是什么了 我点击了 全局应用 从那以后一直是这样 Output is there but so is the error The declared
  • 在 Maven 依赖项中指定 jar 和 test-jar 类型

    我有一个名为 commons 的项目 其中包含运行时和测试的常见内容 在主项目中 我添加了公共资源的依赖项
  • 如何实现仅当可用内存较低时才将数据交换到磁盘的写缓存

    我想将应用程序生成的数据缓存在内存中 但如果内存变得稀缺 我想将数据交换到磁盘 理想情况下 我希望虚拟机通知它需要内存并将我的数据写入磁盘并以这种方式释放一些内存 但我没有看到任何方法以通知我的方式将自己挂接到虚拟机中before an O
  • Spring Boot @ConfigurationProperties 不从环境中检索属性

    我正在使用 Spring Boot 1 2 1 并尝试创建一个 ConfigurationProperties带有验证的bean 如下所示 package com sampleapp import java net URL import j
  • 使用 xpath 和 vtd-xml 以字符串形式获取元素的子节点和文本

    这是我的 XML 的一部分

随机推荐

  • 灵活的按键处理程序 FlexibleButton,C程序编写,无缝兼容任意的处理器,支持任意 OS 和 non-OS

    灵活的按键处理程序 FlexibleButton 前言概述获取测试DEMO 程序说明程序入口用户初始化代码事件处理代码 FlexibleButton 代码说明按键事件定义按键注册接口按键事件读取接口按键扫描接口 问题和建议 前言 正好工作中
  • http请求头header、请求体body、请求行介绍

    HttpServletRequest对象代表客户端的请求 当客户端通过http协议请求访问 服务器的时候 http请求头的所有信息都封装在这个对象中 xff0c 通过这个对象 xff0c 可以获取客户端请求的所有信息 http请求包含请求行
  • 理解字节序 大端字节序和小端字节序

    以下内容参考了 http www ruanyifeng com blog 2016 11 byte order html https blog csdn net yishengzhiai005 article details 3967252
  • opencvSharp 学习笔记(二)

    参考文章 xff1a https github com shimat opencvsharp samples tree master SamplesCS Samples 参考opencvsharp的官方sample xff0c 在vs201
  • C++局部对象的析构

    class A span class hljs keyword public span A Func span class hljs attribute span span class hljs attribute span A A spa
  • BIND中基数树的建立

    BIND9新引入了视图的概念 xff0c 简单的来讲就是能根据不同的来源IP来返回不同的数据 其中网段的存储 xff0c 网段的快速匹配都是用基数树来实现的 下面是BIND创建基数树的代码 BIND的IP地址结构 span class hl
  • HTTP协议解析及C/C++代码实现

    超文本传输协议 HTTP 是分布式 协作 超媒体信息系统的应用层协议 这是自 1990 年以来万维网数据通信的基础 HTTP 是一种通用且无状态的协议 xff0c 它可以用于其他目的 xff0c 也可以使用其请求方法 错误代码和标头的扩展
  • C语言发邮件(带账号密码认证),简单的libesmtp实例

    需要安装libesmtp开发环境 xff0c centos下可以用yum安装 yum install libesmtp devel 编译时加上 lesmtp选项 xff0c 账号密码等替换成自己的 gcc o mail mail c les
  • 怎样在Markdown中贴图片

    前言 Markdown真的是一个很优秀的文本标记语言 语法也很简单 熟悉之后基本上可以完全抛弃Word了 用来写文档 一些博客 再好不过了 可是Markdown还是有一个痛点 那就是不大好贴图片 贴图 怎么样在markdown中贴图就不多说
  • 【四】【vlc-android】播放控制交互与demux解复用层、媒体数据流拉取层的具体数据传递和控制流程源码分析

    1 VLC中有很多demux mux encoder decoder模块 xff0c 因此需要先了解这些模块的加载原理 xff0c 模块的加载原理基本一致 xff0c 因此举例分析MP4解复用模块如何加载完成的 xff0c 主要流程如下 x
  • vs2013 设置不显示输出窗口

    工具 选项 项目与解决方案 常规 取消 在生成开始时显示输出窗口 的勾选
  • @Param注解的用法解析

    实例一 64 Param注解单一属性 dao层示例 Public User selectUser 64 param userName String name 64 param userpassword String password xml
  • mybatis choose标签的使用

    有时候我们并不想应用所有的条件 xff0c 而只是想从多个选项中选择一个 而使用if标签时 xff0c 只要test中的表达式为 true xff0c 就会执行 if 标签中的条件 MyBatis 提供了 choose 元素 if标签是与
  • Socket长连接实现思路

    长连接的正确实现方式 1 不关闭流实现长连接 xff1f 流关闭了而不关闭Socket xff0c 还是无法达到长连接的效果的 xff0c 所以 xff0c 要长连接 xff0c 流必须不能关闭 xff01 那么 xff0c 是不是直接不关
  • com.jacob.com.ComFailException: VariantChangeType failed

    调用jacob组件出错 com jacob com ComFailException VariantChangeType failed 在C Windows System32 config systemprofile下创建文件夹Deskto
  • CRC8校验 java实现

    以下为CRC8的实现 span class hljs keyword package span server span class hljs javadoc CRC8相关计算 encode utf 8 span class hljs jav
  • Java list add方法和addAll方法效率

    结论是 在数据量较小时 add方法配合for循环遍历比addAll来得快 但是在大量数据时 addAll的方法的效率更高 list addAll 是浅拷贝 只是将内存中的地址进行了拷贝 指向了原先list的末尾做了拼接
  • STM32——USART1重映射

    前言 为了使不同器件封装的外设 IO 功能数量达到最优 xff0c 可以把一些复用功能重新映射到其他一些引脚上 STM32 中有很多内置外设的输入输出引脚都具有重映射 remap 的功能 我们知道每个内置外设都有若干个输入输出引脚 xff0
  • Pg数据库比较时间大小

    postgresql 比较两个时间差大于 N个小时 摘要 PG 中时间想减后为interval xff0c 比较两个时间大于某个小时或者分钟等可以直接通过interval来实现 example1 xff1a 判断两个时间差大于4个小时 se
  • import java.util.LinkedList; import java.util.Queue; import java.util.Scanner; import java.util.Stac

    span class hljs keyword import span java util LinkedList span class hljs keyword import span java util Queue span class