技术难点

以树状形式打印二叉树的关键难点在于,如何计算和控制每个节点的打印位置

解决思路

将二叉树的所有节点从左往右全部打印出来,正好和二叉树中序遍历的结果是一样的

利用这个特点,我们就可以通过中序遍历结果,来反推每个节点位置,再按广度优先遍历算法,逐行打印即可

具体方案和流程图如下

二叉树


中序遍历

每个字符间要保持一定间隔,所以加上占位符


广度优先遍历

保持每个节点横向位置不变,根据广度优先遍历调整节点层次位置


将占位符替换为连接符和空白字符


这样就大功告成了,思路有了,实现就不难了

注意细节

  • 为了保证所有字符等宽,可将字符转为全角字符
  • 连接符可以用横杠竖杠等字符来代替
  • 每个节点的字符串可能不止一个字符,因此实现时还要考虑节点字符串的长度

实现代码

这里我们只讲解怎么打印二叉树,测试数据的构建,我们直接借用上一章的二叉搜索树

@SuppressWarnings("all")public class BinaryNode<T extends Comparable> {T value;BinaryNode<T> left;BinaryNode<T> right;public int getChildCount() {if (left == null && right == null)return 0;if (left != null && right != null)return 2;return 1;}@Overridepublic String toString() {return String.valueOf(value);}}
import java.util.LinkedHashMap;import java.util.LinkedList;import java.util.List;import java.util.Map;@SuppressWarnings("all")public class BinaryPrinter {BinaryNode root;//中序遍历和广度遍历结果final List<BinaryNode> inorderTraverseList = new LinkedList();final List<BinaryNode> breadthTraverseList = new LinkedList();//所有节点的坐标final Map<BinaryNode, Integer> xMap = new LinkedHashMap();final Map<BinaryNode, Integer> yMap = new LinkedHashMap();//整个输出矩阵中的所有字符final List<List<Character>> charForm = new LinkedList();//下个节点的坐标int nextX;int nextY;public void setRootNode(BinaryNode root) {this.root = root;}public void Print() {//清空旧数据inorderTraverseList.clear();breadthTraverseList.clear();xMap.clear();yMap.clear();charForm.clear();nextX = 0;nextY = 0;//如果节点为空,直接结束if (root == null) {System.out.println("Empty Tree");return;}//中序遍历,计算出每个节点的横向X坐标InorderTraverse(root);//层次遍历,计算出每个节点的纵向Y坐标List<BinaryNode> levelNodeList = new LinkedList();levelNodeList.add(root);BreadthTraverse(levelNodeList);//生成最终的二维字符数组FillCharForm();//打印结果for (List<Character> row : charForm) {for (Character cell : row)System.out.print(cell);System.out.println();}}//中序遍历private void InorderTraverse(BinaryNode node) {if (node.left != null)InorderTraverse(node.left);inorderTraverseList.add(node);xMap.put(node, nextX);nextX = nextX + String.valueOf(node.value).length() + 1;if (node.right != null)InorderTraverse(node.right);}//层次遍历,当前层次的所有节点private void BreadthTraverse(List<BinaryNode> levelNodeList) {if (levelNodeList.isEmpty())return;for (BinaryNode node : levelNodeList)yMap.put(node, nextY);breadthTraverseList.addAll(levelNodeList);nextY = nextY + 1;List<BinaryNode> nextLevelNodeList = new LinkedList();for (BinaryNode node : levelNodeList) {if (node.left != null)nextLevelNodeList.add(node.left);if (node.right != null)nextLevelNodeList.add(node.right);}BreadthTraverse(nextLevelNodeList);}//生成最终的二维字符数组private void FillCharForm() {//填充占位符for (int y = 0; y <= nextY - 1; y++) {List<Character> row = new LinkedList();charForm.add(row);for (int x = 0; x <= nextX - 2; x++) {char character = toFullWidth(' ');row.add(character);}}//填充节点字符串for (BinaryNode node : breadthTraverseList) {int x = xMap.get(node);int y = yMap.get(node);String value = String.valueOf(node.value);for (int i = 0; i < value.length(); i++)setChar(x + i, y, value.charAt(i));}//填充连接符for (BinaryNode node : breadthTraverseList) {if (node.left != null) {int x1 = xMap.get(node.left);int x2 = xMap.get(node);int y = yMap.get(node);setChar(x1, y, '|');for (int i = x1 + 1; i < x2; i++)setChar(i, y, '-');}if (node.right != null) {int x1 = xMap.get(node);int x2 = xMap.get(node.right);int y = yMap.get(node);setChar(x2, y, '|');String value = String.valueOf(node.value);for (int i = x1 + value.length(); i < x2; i++)setChar(i, y, '-');}}}//设置指定位置的字符protected void setChar(int x, int y, char halfChar) {char fullChar = toFullWidth(halfChar);charForm.get(y).set(x, fullChar);}//半角字符转全角字符private char toFullWidth(char halfChar) {if (halfChar == 32)return (char) 12288;if (halfChar < 127)return (char) (halfChar + 65248);return halfChar;}}
@SuppressWarnings("all")public class Demo {public static void main(String[] args) {BinarySearchTree bst = new BinarySearchTree();bst.Insert(90);bst.Insert(30);bst.Insert(99);bst.Insert(20);bst.Insert(50);bst.Insert(40);bst.Insert(70);bst.Insert(60);bst.Insert(80);BinaryPrinter printer = new BinaryPrinter();printer.setRootNode(bst.root);printer.Print();}}

运行结果如下


效果还是相当可以的,大功告成!

【数据结构与算法】【14】以树状形式打印二叉树相关推荐

  1. 横向打印二叉树 java_按树状横向打印二叉树

    问题 假设以二叉链表存储的二叉树中,每个结点所含数据元素均为单字母. 要求实 现二叉树的横向显示问题,如下图所示打印结果. 问题分析 (1) 二叉树的横向显示应是二叉树竖向显示的90°旋转.分析上图可 ...

  2. 数据结构与算法之2-3-4树

    数据结构与算法之2-3-4树 原文来自个人博客(求访问/关注/收藏): https://bbing.com.cn/ CSDN个人博客不定期转载 平衡树 [外链图片转存失败,源站可能有防盗链机制,建议将 ...

  3. 『数据结构与算法』解读树(Tree)和二叉树(Binary Tree)!

    『数据结构与算法』解读树(Tree)和二叉树(Binary Tree)! 文章目录 一. 树 1.1. 树的定义 1.2. 树的基本术语 1.3. 树的性质 二. 二叉树 2.1. 二叉树的定义 2. ...

  4. js遍历树节点下的所有子节点_【数据结构与算法】(3)——树和二叉树

    树 树的基本概念 树是一种非线性的数据结构,样子如图所示: 树的主要特点是树中的数据是分层存储的,每个元素称为树的节点,最顶层有且只有一个元素,称为根节点,其余层可以有任意数量的节点.除了根节点,其余 ...

  5. 数据结构与算法学习笔记-树和二叉树

    声明:本博客仅为本人学习途中做的笔记 采自青岛大学王卓老师的视频教学 主要内容为算法思路,具体代码实现还需修改后才能运行,望各位看官多多包涵,您的点赞与评论是对我最大的肯定! 1.树和二叉树的定义 数 ...

  6. 数据结构与算法3(树型结构)

    树型结构 树形结构: 1.树的基本概念 2.树的表示方法:倒悬树.嵌套法.凹凸法 3.树的专业术语(不同资料略有不同) 4.树的存储 双亲表示法 顺序 孩子表示法 兄弟表示法 树形结构: 1.树的基本 ...

  7. 【数据结构与算法基础】树与二叉树的互化

    前言 数据结构,一门数据处理的艺术,精巧的结构在一个又一个算法下发挥着他们无与伦比的高效和精密之美,在为信息技术打下坚实地基的同时,也令无数开发者和探索者为之着迷. 也因如此,它作为博主大二上学期最重 ...

  8. 树的高度从零还是一开始数_数据结构与算法之1——树与二叉树

    数据结构一直是让人头疼,面试遇到手撕算法题时真是慌得不行,从啥也不会刷题刷到游刃有余,路漫漫其修远兮~~.本人还是个算法菜鸟,而且还是想转行互联网的半吊子(好想拿大厂offer啊,幻想中..),希望能 ...

  9. 树状数组 java_算法模板之树状数组

    什么是树状数组? ​树状数组就是通过数组来模拟一种树形结构,这种树形结构能够维护区间信息.同样类似的数据结构还有线段树,线段树与树状数组相比,它的结点更多,也就是说线段树的常数更大. ​线段树是通过把 ...

最新文章

  1. eax ax ah al
  2. 推荐!国外程序员整理的 C++ 资源大全(https://github.com/fffaraz/awesome-cpp)
  3. 网络爬虫初步:从访问网页到数据解析
  4. 用WPF开发Mapxtreme-- 在.net 4.0 下面开发WPF mapxtreme 程序
  5. MonoBehaviour.FixedUpdate 固定更新
  6. 工业交换机的性能优势有哪些?
  7. no typehandler found for property XXXX 解决
  8. PHP学习——定界符格式引起的错误
  9. linux修改控制台分辨率,linux控制台分辨率
  10. 【转】在Linux下编译与执行Java程序
  11. hokuyo_node代码分析
  12. Anaconda中安装pygame
  13. oracle在cmd中启动数据库实例
  14. 初学SQL Server 2016
  15. Practical JXTA II
  16. Ubuntu 16.04 安装 搜狗输入法
  17. 微博秒拍等网站的视频图片下载工具:在线下载工具
  18. 【干货】一文详解计算机视觉的广泛应用:网络压缩、视觉问答、可视化、风格迁移等
  19. CCCF精选 | 李德毅:机器如何像人一样认知——机器的生命观
  20. 用python画一个动态樱花

热门文章

  1. 图新地球工程版|同豪路易BIM设计成果、CAD、倾斜模型、纬地数据、影像地形等多源项目数据融合展示汇报
  2. echarts官网进不去,处理DNS了还是进不去
  3. 股票基金模拟交易日志5
  4. 【PHP】工银e缴费PHP版本对接?
  5. AI智能呼叫中心系统,主要应用场景有哪些?
  6. 广告算法所需要搞懂的基础知识
  7. Python类调用类的实例方法的方式
  8. bzoj 2732 射箭 半平面交 解题报告
  9. 《28天玩转TensorFlow2》第8天:TensorFlow2构建数据管道—Pandas DataFrame格式
  10. 15. Examples【示例】