打印二叉树

2023-10-27

摘要

https://wylu.github.io/posts/91f36751/

本文将使用两种展示方式打印一颗二叉树,效果如下:

8
├── 12
│   ├── 14
│   │   ├── 20
│   │   │   └── 15
│   │   └── 13
│   └── 10
│       ├── 11
│       └── 9
└── 4
    ├── 6
    │   ├── 7
    │   └── 5
    └── 2
        ├── 3
        └── 1
                 /----- 20
                 |       \----- 15
         /----- 14
         |       \----- 13
 /----- 12
 |       |       /----- 11
 |       \----- 10
 |               \----- 9
8
 |               /----- 7
 |       /----- 6
 |       |       \----- 5
 \----- 4
         |       /----- 3
         \----- 2
                 \----- 1

构建二叉树

为了方便测试,我们需要构建一颗二叉树,这里使用前序遍历序列和中序遍历序列来重建二叉树。

public class TreeNode {
    public int val;
    public TreeNode left;
    public TreeNode right;

    public TreeNode(int x) {
        val = x;
    }
}
/**
 * @File    :   Tree.java
 * @Time    :   2020/03/23 17:46:15
 * @Author  :   wylu
 * @Version :   1.0
 * @Contact :   15wylu@gmail.com
 * @License :   (C)Copyright 2020, wylu-CHINA-SHENZHEN
 * @Desc    :
 */
public class Tree {
    private static TreeNode mk(int[] pre, int[] in,
                               int startPre, int endPre,
                               int startIn, int endIn) {
        if (startPre == endPre) {
            return null;
        }
        TreeNode root = new TreeNode(pre[startPre]);
        // 中序遍历序列根结点索引
        int idx = startIn;
        while (idx < endIn && in[idx] != root.val) {
            idx++;
        }

        // 左子树序列长度
        int llen = idx - startIn;
        // 左右子树序列中点(右子树序列起始点)
        int mpre = startPre + 1 + llen;
        root.left = mk(pre, in, startPre + 1, mpre, startIn, idx - 1);
        root.right = mk(pre, in, mpre, endPre, idx + 1, endIn);
        return root;
    }

    /**
     * 利用前序遍历序列和中序遍历序列构建一颗二叉树
     * 
     * @param pre 前序遍历序列
     * @param in  中序遍历序列
     * @return
     */
    public static TreeNode mkTree(int[] pre, int[] in) {
        if (pre == null || in == null || pre.length == 0 || pre.length != in.length) {
            return null;
        }
        return mk(pre, in, 0, pre.length, 0, in.length);
    }
}

调用示例:

public static void main(String[] args) {
    // Case 1
    int[] pre = {1, 2, 4, 7, 3, 5, 6, 8};
    int[] in = {4, 7, 2, 1, 5, 3, 8, 6};
    TreeNode root = Tree.mkTree(pre, in);
}

二叉树打印类

/**
 * @File : TreePrinter.java
 * @Time : 2020/03/23 17:47:57
 * @Author : wylu
 * @Version : 1.0
 * @Contact : 15wylu@gmail.com
 * @License : (C)Copyright 2020, wylu-CHINA-SHENZHEN
 * @Desc :
 */
public class TreePrinter {
    private static void linuxStyle(TreeNode root, StringBuilder sb, String prefix, String childPrefix) {
        if (root == null) {
            return;
        }
        sb.append(prefix);
        sb.append(root.val);
        sb.append("\n");
        linuxStyle(root.right, sb, childPrefix + "├── ", childPrefix + "│   ");
        linuxStyle(root.left, sb, childPrefix + "└── ", childPrefix + "    ");
    }

    public static StringBuilder getLinuxStyle(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        linuxStyle(root, sb, "", "");
        return sb;
    }

    /**
     * z
     * ├── c
     * │ ├── a
     * │ └── b
     * └── d
     *
     * @param root
     */
    public static void prtLinuxStyle(TreeNode root) {
        System.out.println(getLinuxStyle(root).toString());
    }

    public static StringBuilder horizontalStyle(TreeNode root, StringBuilder sb) {
        if (root.right != null) {
            horizontalStyle(root.right, sb, true, "");
        }
        sb.append(root.val).append("\n");
        if (root.left != null) {
            horizontalStyle(root.left, sb, false, "");
        }
        return sb;
    }

    private static void horizontalStyle(TreeNode root, StringBuilder sb, boolean isRight,
            String indent) {
        if (root.right != null) {
            horizontalStyle(root.right, sb, true, indent + (isRight ? "        " : " |      "));
        }
        sb.append(indent);
        sb.append(isRight ? " /" : " \\");
        sb.append("----- ");
        sb.append(root.val).append("\n");
        if (root.left != null) {
            horizontalStyle(root.left, sb, false, indent + (isRight ? " |      " : "        "));
        }
    }

    /**
     *                 /----- 20
     *                 |       \----- 15
     *         /----- 14
     *         |       \----- 13
     * /----- 12
     * |       |       /----- 11
     * |       \----- 10
     * |               \----- 9
     * 8
     * |              /----- 7
     * |      /----- 6
     * |      |       \----- 5
     * \----- 4
     *        |       /----- 3
     *        \----- 2
     *                \----- 1
     *
     * @param root
     */
    public static void prtHorizontalStyle(TreeNode root) {
        System.out.println(horizontalStyle(root, new StringBuilder()).toString());
    }

    public static void main(String[] args) {
        // Case 1
        int[] pre = {1, 2, 4, 7, 3, 5, 6, 8};
        int[] in = {4, 7, 2, 1, 5, 3, 8, 6};
        TreeNode root = Tree.mkTree(pre, in);
        TreePrinter.prtLinuxStyle(root);
        TreePrinter.prtHorizontalStyle(root);

        // Case 2
        pre = new int[] {8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 20, 15};
        in = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 20};
        root = Tree.mkTree(pre, in);
        TreePrinter.prtLinuxStyle(root);
        TreePrinter.prtHorizontalStyle(root);
    }
}

References

https://stackoverflow.com/questions/4965335/how-to-print-binary-tree-diagram

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

打印二叉树 的相关文章

  • Java中字符串中特殊字符的替换

    Java中如何替换字符串 E g String a adf sdf 如何替换和避免特殊字符 您可以删除除此之外的所有字符可打印的 ASCII 范围 http en wikipedia org wiki ASCII ASCII printab
  • Hibernate注解放置问题

    我有一个我认为很简单的问题 我见过两种方式的例子 问题是 为什么我不能将注释放在字段上 让我举一个例子 Entity Table name widget public class Widget private Integer id Id G
  • 在文本文件中写入多行(java)

    下面的代码是运行命令cmd并使用命令行的输出生成一个文本文件 下面的代码在 Eclipse 的输出窗口中显示了正确的信息 但在文本文件中只打印了最后一行 谁能帮我这个 import java io public class TextFile
  • Java:如何从转义的 URL 获取文件?

    我收到了一个定位本地文件的 URL 事实上我收到的 URL 不在我的控制范围内 URL 按照 RFC2396 中的定义进行有效转义 如何将其转换为 Java File 对象 有趣的是 URL getFile 方法返回一个字符串 而不是文件
  • Cassandra java驱动程序协议版本和连接限制不匹配

    我使用的java驱动程序版本 2 1 4卡桑德拉版本 dsc cassandra 2 1 10cql 的输出给出以下内容 cqlsh 5 0 1 Cassandra 2 1 10 CQL spec 3 2 1 Native protocol
  • Hazelcast 分布式锁与 iMap

    我们目前使用 Hazelcast 3 1 5 我有一个简单的分布式锁定机制 应该可以跨多个 JVM 节点提供线程安全性 代码非常简单 private static HazelcastInstance hInst getHazelcastIn
  • Java 8 流 - 合并共享相同 ID 的对象集合

    我有一系列发票 class Invoice int month BigDecimal amount 我想合并这些发票 这样我每个月都会收到一张发票 金额是本月发票金额的总和 例如 invoice 1 month 1 amount 1000
  • 将 SignedHash 插入 PDF 中以进行外部签名过程 -workingSample

    遵循电子书第 4 3 3 节 PDF 文档的数字签名 https jira nuxeo com secure attachment 49931 digitalsignatures20130304 pdf 我正在尝试创建一个工作示例 其中 客
  • 普罗米修斯指标 - 未找到

    我有 Spring Boot 应用程序 并且正在使用 vertx 我想监控服务和 jvm 为此我选择了 Prometheus 这是我的监控配置类 Configuration public class MonitoringConfig Bea
  • Javafx过滤表视图

    我正在尝试使用文本字段来过滤表视图 我想要一个文本字段 txtSearch 来搜索 nhs 号码 名字 姓氏 和 分类类别 我尝试过在线实施各种解决方案 但没有运气 我对这一切仍然很陌生 所以如果问得不好 我深表歉意 任何帮助将不胜感激 我
  • Jersey 客户端请求中未设置 Content-Length-Header

    我正在使用 Jersey Client 访问网络服务 如下所示 response r accept MediaType TEXT PLAIN TYPE header content length 0 post String class 其中
  • 如何在JSTL中调​​用java方法? [复制]

    这个问题在这里已经有答案了 这可能是重复的问题 我只想调用不是 getter 或 setter 方法的方法例如 xyz 类的 makeCall someObj stringvalue Java类 Class XYZ public Strin
  • 测试弱引用

    在 Java 中测试弱引用的正确方法是什么 我最初的想法是执行以下操作 public class WeakReferenceTest public class Target private String value public Targe
  • Netty:阻止调用以获取连接的服务器通道?

    呼吁ServerBootstrap bind 返回一个Channel但这不是在Connected状态 因此不能用于写入客户端 Netty 文档中的所有示例都显示写入Channel从它的ChannelHandler的事件如channelCon
  • 替换后增量

    我自己已经有一个问题了 但我想扩展它后增量示例 https stackoverflow com questions 51308967 post increment with example char a D int b 5 System o
  • 将 Azure AD 高级自定义角色与 Spring Security 结合使用以进行基于角色的访问

    我创建了一个演示 Spring Boot 应用程序 我想在其中使用 AD 身份验证和授权 并使用 AD 和 Spring Security 查看 Azure 文档 我执行了以下操作 package com myapp contactdb c
  • Java中的Object类是什么?

    什么是或什么类型private Object obj Object http download oracle com javase 6 docs api java lang Object html是Java继承层次结构中每个类的最终祖先 从
  • spring中如何使用jackson代替JdkSerializationRedisSerializer

    我在我的一个 Java 应用程序中使用 Redis 并且正在序列化要存储在 Redis 中的对象列表 但是 我注意到使用 RedisTemplate 会使用 JdkSerializationRedisSerializer 相反 我想使用 J
  • 如何使用 JSch 将多行命令输出存储到变量中

    所以 我有一段很好的代码 我很难理解 它允许我向我的服务器发送命令 并获得一行响应 该代码有效 但我想从服务器返回多行 主要类是 JSch jSch new JSch MyUserInfo ui new MyUserInfo String
  • 调整添加的绘制组件的大小和奇怪的摆动行为

    这个问题困扰了我好几天 我正在制作一个特殊的绘画程序 我制作了一个 JPanel 并添加了使用 Paint 方法绘制的自定义 jComponent 问题是 每当我调整窗口大小时 所有添加的组件都会 消失 或者只是不绘制 因此我最终会得到一个

随机推荐

  • 辟谣、催债、倒闭.....2018年后,将再无创业黄金期!

    导读 上下游没钱了 信贷机构没钱了 风险投资人也没钱了 中小企业成本和资金压力大 企业违约 到期没法还债 非银行金融机构爆雷 大量出问题 股市非理性下滑 所有人进入新一轮升级性迷茫 由于各项成本的抬升 未来 不缺钱也不缺资源的头部企业将变得
  • Spark 基础教程

    Spark是基于内存计算的大数据并行计算框架 可用于构建大型的 低延迟的数据分析应用程序 Spark特点 运行速度快 Spark使用先进的DAG Directed Acyclic Graph 有向无环图 执行引擎 以支持循环数据流与内存计算
  • 软件发布之版本命名

    简介软件的版本命名与编号 img src http blog csdn net ppbage aggbug 747919 aspx width 1 height 1
  • unity--触屏游戏中如何判断点击的位置的左右&触屏游戏中如何判断点击的位置的左右&通过反转对象,让左侧运动的动画应用于右侧运动&通过代码改变图层覆盖顺序(Sorting Layer)

    文章目录 触屏游戏中如何判断点击的位置的左右 使用获取到的触碰坐标来进行左右移动 通过反转对象 让左侧运动的动画应用于右侧运动 通过代码改变图层覆盖顺序 Sorting Layer 触屏游戏中如何判断点击的位置的左右 我们先要有一个可以反馈
  • osg学习(四十)osg::Viewer的realize创建窗体的几种方式

    能够根据屏幕数 创建不同位置的窗口 void Viewer realize 在某一个屏幕上创建无边框窗口 在某一个屏幕上创建正常窗口 在所有屏幕上创建正常窗口 一个窗口 窗口位置可以跨屏幕 osgViewer SingleWindow实现
  • promise笔记

    promise笔记 以下笔记主要参考axios官网里的promise教程 写在这里方便以后复习或者查找 Promise javascript info 可以通过这个链接进行学习 更加详细 文章目录 promise笔记 1 介绍 2 基本语法
  • 将字符串格式的时间格式化

    时间格式化 param Number date 时间戳 param DateString fmt 时间格式 dateFormat yyyy MM dd hh mm ss S gt 2016 03 12 20 13 32 232 return
  • Object.create 以及 Object.setPrototypeOf

    第一部分 Object crate 方法是es5中的关于原型的方法 这个方法会使用指定的原型对象以及属性去创建一个新的对象 语法 Object create proto propertiesObjecy 参数 proto 必须的 一个对象
  • 云计算简介

    什么是 云 迁移至云端 在云中运行 在云中存储 从云端访问 当今时代 似乎一切都在 云 中进行 但是 云 究竟是一个什么样的概念 简单来说 云就是互联网连接的另一端 你可以从云端访问各种应用程序和服务 也可以在云端安全存储你的数据 云 之所
  • 扫描二维码 跳转到小程序指定页面

    注意 必须发布代码之后才能使用扫描二维码跳转 规则 1 二维码规则 填写你要生成的二维码的链接 2 小程序功能页面 要跳转的小程序的页面 3 测试链接 也填同样的链接 4 将上面的链接生成一个二维码 测试链接 5 通过微信扫描这个二维码跳转
  • 安装Apex库

    在Linux系统下安装Apex库 1 安装流程 按顺序使用如下命令 git clone https github com NVIDIA apex cd apex pip3 install v no cache dir 注意 不能直接使用pi
  • iOS 多线程

    1 怎么用GCD实现多读单写 dispatch barrier async 2 ios系统为我们提供的几种多程序技术各自的特点是怎样的 GCD 实现一些简单的线程同步 子线程的分派 包括一些类似于多读单写 nsoperation 比如adn
  • 2022年最佳的9种逆向工程工具[持续更新]

    逆向是复杂的 然而 软件开发人员经常在面临一项具有挑战性的任务时转向反向工程 增强软件安全性 使软件与第三方组件兼容 维护遗留代码 等等 在本文中 我们将描述我们的软件逆向程序在工作中所依赖的主要工具 并展示如何使用这些工具的实际示例 本文
  • python输入多组测试数据_python ddt数据驱动实例代码分享

    python ddt数据驱动最简实例 在接口自动化测试中 往往一个接口的用例需要考虑 正确的 错误的 异常的 边界值等诸多情况 然后你需要写很多个同样代码 参数不同的用例 如果测试接口很多 不但需要写大量的代码 测试数据和代码柔合在一起 可
  • STM32基于HAL库带FreeRTOS系统的Freemodbus移植

    STM32基于HAL库移植带FreeRTOS系统的Freemodbus移植 移植前提 下载所需源码 可能的win10 IAR设置 从站注意定义寄存器数量大小 效果查询报文 效果回复报文 移植事件 定时器 串口 事件移植 串口移植 定时器移植
  • Electron+React+Antd将网页打包成应用程序完整步骤(electron-builder (搭建热更新) 或 electron-packager(不搭建热更新))

    一 创建React项目 ps 由于写的时候没注意 包安装有的用npm有的用yarn 大家统一用一个就行 尽量不要使用cnpm ps 源码地址 git clone https github com Aug Sunrise electron t
  • 【mysql】mysql表分区、索引的性能测试

    概述 mysql分区表概述 google搜索一下 RANGE COLUMNS partitioning 主要测试mysql分区表的性能 load 500w 条记录 大约在10min左右 batch insert 1 9w条记录 没建立索引
  • 小米升级后开机显示无服务器,小米手机升级后无法开机解决方法

    方法1 刷机 在关机的状态下 进rec中双清 音量上键和开机键按住出来第一个mi画面全部松手 再按住音量加 然后在双清 然后关机音量下键和开机键同时摁住进入fastboot模式 出现米兔修机器人界面 线刷开发版刷机包和教程可以到http w
  • vue3中keep-alive和vue-router的结合使用

    vue3中keep alive和vue router的结合使用 前言 代码 一 为何要使用keep alive 二 vue2中使用keep alive 将 router view 组件包含于 keep alive 即可 三 vue3中使用k
  • 打印二叉树

    摘要 https wylu github io posts 91f36751 本文将使用两种展示方式打印一颗二叉树 效果如下 8 12 14 20 15 13 10 11 9 4 6 7 5 2 3 1 20