程序设计:控制台输出二叉树 二叉树的形象显示

       本文指导你编写一个输出到字符控制台的形象的二叉树展示。

目录

一般的Tree显示方式

理想的显示方式

实现方法

计算显示位置

输出数据

计算显示位置的代码

输出数据的代码


一般的Tree显示方式

        编写二叉树算法时调试是很头疼的,如何显示成一目了然的树结构呢?以目录树方式显示当然比较简单,类似windows控制台的Tree命令的效果:

        这种输出只需要正确计算节点的缩进级别就可以了,用一个递归函数很容易就实现了。

        但是这种输出方式并不方便查看,不容易直接看到两个子节点。而我们一般讲解二叉树的时候都是横向排版,两个子节点排在父节点下面的同一行。

理想的显示方式

        理想的显示方式如下图所示:

        这就是程序的实际输出效果,左子节点左边有个“[”,右子节点右边有个“]”,这样每一组子节点就一目了然,左子树整个都显示在父节点的左边,右子树整个都显示在父节点右边。

        由于我们的目的不是做完美的界面,所以不会考虑ncurse库这种能随意绘制的方式(如果这样不如直接用图形界面了),我们只考虑一般的逐行输出的控制台。

实现方法

        要想实现这种效果,需要分两步来做:

  1. 计算整个左子树的宽度,从而确定节点显示位置
  2. 根据计算好的显示位置自上而下输出数据

计算显示位置

        计算显示位置是个比较复杂的事情,因为每个节点的显示宽度是不确定的,需要预先确定每个节点的宽度,然后根据结构计算正确的位置,如果子节点缺失,没必要占用显示空间。

        既然这么复杂,我们可以把问题拆开,把计算精确位置留给第二步,把每个节点当成一个格子,这一步只计算格子位置。

        计算出的格子位置如何保存呢?这就需要一个表格,这个表格的行列数刚好容纳整个二叉树。仔细观察一下上面的输出示例图形,每一个节点都独立占据一列,因为表格的列数就是总的节点数,行数就是树的深度。

        这样很容易预先申请一个二维数组,然后根据计算出的位置设置里面的值,最后将这个二维数组输出就可以了。

输出数据

        经过上一步,输出数据已经在二维数组里,如何显示就比较容易了。只需要预先计算一下每列的最大显示宽度,然后逐个输出就可以了。

        当然为了实现这个功能,最好有一些包装类,以简化操作。

计算显示位置的代码

        这只是示意代码:

	//树形显示,px为偏移量,左边元素数
	void _check_show_tree(Table& table, T_SIZE h, bool left = true, T_SIZE line = 0, T_SIZE px = 0)
	{
		//thelog << h << " " << line << " " << px << endi;
		if (!_check_is_data_node(h))
		{
			//thelog << "空" << endi;
			return;
		}

		T_SIZE leftCount = _check_get_count(TREE_NODE::at(h).hLeft);
		//thelog << "leftCount " << leftCount << endi;
		T_SHM_SIZE pos = px + leftCount;
		table.SetData(line, pos, TREE_NODE::at(h).toString2(left));//设置自身数据
		//thelog << "TREE_NODE::at(h).hLeft " << TREE_NODE::at(h).hLeft << endi;
		_check_show_tree(table, TREE_NODE::at(h).hLeft, true, line + 1, px);//处理左子项
		//thelog << "TREE_NODE::at(h).hRight " << TREE_NODE::at(h).hRight << endi;
		_check_show_tree(table, TREE_NODE::at(h).hRight, false, line + 1, pos + 1);//处理右子项
	}

        解释一下这个代码:

        Table是个包装好的类,能通过table.SetData()直接对某个位置设置值。

        T_SIZE h 就是节点的指针或者句柄,这里实际上是位置索引。

        _check_is_data_node(h) 判断一个位置是否是有效位置,相当于判断是不是空指针。

        TREE_NODE::at(h) 获取位置上的节点对象的引用。

        TREE_NODE::at(h).toString2(left) 这个代码获得节点的显示字符串,参数控制是否是左节点,左节点添加“[”,右节点添加“]”。

        基本逻辑就是:

        如果不是有效节点,返回0

        否则返回1+左节点树的总节点数+右节点数的总节点数

输出数据的代码

        第一步,计算每个列的最大宽度

        第二步,按照每个列的最大宽度输出每个字段,为了格式整齐,一定要用空格来填补,不可以用tab。数据中最好不要有tab、回车换行之类的东西,也不要有中文。

(这里是结束)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/120133.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Flink SQL DataGen Connector 示例

Flink SQL DataGen Connector 示例 1、概述 使用 Flink SQL DataGen Connector&#xff0c;可以快速地生成符合规则的测试数据&#xff0c;可以在不依赖真实数据的情况下进行开发和测试。 2、使用示例 创建一个名为 “users” 的表&#xff0c;包含 6 个字段&#xff1a;id…

PHP分类信息网站源码系统 电脑+手机+微信端三合一 带完整前后端部署教程

大家好啊&#xff01;今天源码小编来给大家分享一款PHP分类信息网站类源码系统。这款源码系统是一套专业的信息发布类网站综合管理系统&#xff0c;适合各类地方信息和行业分类站点建站。随着这几年我们国家网民爆炸式的增 长&#xff0c;网络信息也随之越来越庞大&#xff0c;…

为什么亚马逊的轻量应用服务器这么受欢迎 | 个人体验 | 优势所在

文章目录 &#x1f33a;前言⭐什么是轻量应用服务器&#x1f6f8;特点 &#x1f384;亚马逊轻量应用服务器体验如何&#x1f339;亚马逊轻量应用服务器的优势 &#x1f33a;前言 作为一为开发者&#xff0c;我们要开发部署一个自己的网站&#xff0c;要选择一个性能好的服务器…

算法训练 第六周

一、用栈实现队列 本题要求我们使用栈这个数据结构来模拟实现队列的各种操作&#xff0c;我们的具体思路是使用两个栈&#xff0c;将一个栈当作输入栈&#xff0c;用于压入 push传入的数据&#xff1b;另一个栈当作输出栈&#xff0c;用于 pop和 peek 操作。每次 pop 或 peek 时…

大数据学习之Spark性能优化

文章目录 Spark三种任务提交模式宽依赖和窄依赖StageSpark Job的三种提交模式 Shuffle机制分析未优化的Hash Based Shuffle优化后的Hash Based ShuffleSort-Based Shuffle Spark之checkpointcheckpoint概述checkpoint与持久化的区别checkPoint的使用checkpoint源码分析 Spark程…

实现前后端分离开发:构建现代化Web应用

文章目录 什么是前后端分离开发&#xff1f;为什么要采用前后端分离开发&#xff1f;前后端分离的最佳实践1. 定义API2. 使用RESTful风格3. 选择适当的前端框架4. 选择合适的后端技术5. 数据交互格式6. 前端路由7. 自动化构建和部署8. 跨域问题 示例&#xff1a;前后端分离开发…

代码随想录算法训练营第四十七天 | LeetCode 198. 打家劫舍、213. 打家劫舍 II、337. 打家劫舍 III

代码随想录算法训练营第四十七天 | LeetCode 198. 打家劫舍、213. 打家劫舍 II、337. 打家劫舍 III 文章链接&#xff1a;打家劫舍 打家劫舍 II 打家劫舍 III 视频链接&#xff1a;打家劫舍 打家劫舍 II 打家劫舍 III 1. LeetCode 198. 打家劫舍 1.1 思路 我们要去偷钱&#…

【论文阅读】Generating Radiology Reports via Memory-driven Transformer (EMNLP 2020)

资料链接 论文原文&#xff1a;https://arxiv.org/pdf/2010.16056v2.pdf 代码链接&#xff08;含数据集&#xff09;&#xff1a;https://github.com/cuhksz-nlp/R2Gen/ 背景与动机 这篇文章的标题是“Generating Radiology Reports via Memory-driven Transformer”&#xf…

Leetcode—2586.统计范围内的元音字符串数【简单】

2023每日刷题&#xff08;二十二&#xff09; Leetcode—2586.统计范围内的元音字符串数 实现代码 class Solution { public:int vowelStrings(vector<string>& words, int left, int right) {int ans 0;for(int i left; i < right; i) {string s words[i];i…

解决:ImportError: cannot import name ‘get_config‘

解决&#xff1a;ImportError: cannot import name ‘get_config’ 背景 今天使用Conda构建项目运行环境的时候报错&#xff1a;ImportError: cannot import name ‘get_config’ ##报错问题 from keras.callbacks import LearningRateScheduler, ModelCheckpointFile "D…

GreenPlum简介

简介 Greenplum是一家总部位于**美国加利福尼亚州&#xff0c;为全球大型企业用户提供新型企业级数据仓库(EDW)、企业级数据云(EDC)和商务智能(BI)提供解决方案和咨询服务的公司&#xff0c;在全球已有&#xff1a;纳斯达克&#xff0c;纽约证券交易所&#xff0c;Skype. FOX&…

idea 模板参数注释 {@link}

1. 新增组 2. 设置方法注释及变量 增加模板文本 ** * $param$ * return {link $return$} */3. 设置变量表达式 勾选跳过param 参数表达式 groovyScript("def result ;def params \"${_1}\".replaceAll([\\\\[|\\\\]|\\\\s], ).split(,).toList();def param…

7.spark sql编程

目录 概述RDD ,Datasets,DataFrames 之间的区别Datasets , DataFrames和 RDD 入门people.jsonSparkSession创建 DataFramesDataFrame 操作编程方式运行 sql 查询创建 DatasetsDataFrames 与 RDDs 互相转换使用反射推断模式编码问题 编程指定 Schema官方文档的代码不全问题 结束…

idea使用gradle教程 (idea gradle springboot)2024

这里白眉大叔&#xff0c;写一下我工作时候idea怎么使用gradle的实战步骤吧 ----windows 环境----------- 1-本机安装gradle 环境 &#xff08;1&#xff09;下载gradle Gradle需要JDK的支持&#xff0c;安装Gradle之前需要提前安装JDK8及以上版本 https://downloads.gra…

Python - 面向现实世界的人脸复原 GFP-GAN 简介与使用

目录 一.引言 二.GFP-GAN 简介 1.GFP-GAN 数据 2.GFP-GAN 架构 3.GFP-GAN In Wave2Lip 三.GFPGAN 实践 1.环境搭建 2.模型下载 3.代码测试 4.测试效果 四.总结 一.引言 近期 wav2lip 大火&#xff0c;其通过语音驱动唇部动作并对视频质量进行修复&#xff0c;其中…

【微信小程序】新版获取手机号码实现一键登录(uniapp语法)(完整版附源码)

需求 如图&#xff0c;点击按钮&#xff0c;获取用户手机号实现一键登录&#xff0c;当然&#xff0c;用户也可以自行输入其他手机号进行登录 问题 要想获取用户手机号并不复杂&#xff0c;但由于近几年微信小程序获取手机号的api进行了更新&#xff0c;当前很多帖子使用的…

VB.NET—DataGridView控件教程详解

目录 前言: 过程: 第一步: 第二步: 第三步: 第四步: 第五步&#xff1a; 番外篇: 总结: 前言: DataGridView是.NET FormK中的一个Windows窗体控件&#xff0c;它提供了一个可视化的表格控件&#xff0c;允许用户以表格形式显示和编辑数据。它通常用于显示和编辑数据库…

Rust教程5:泛型和特征

文章目录 泛型函数特征特征泛型 Rust系列&#xff1a;初步⚙所有权⚙结构体和枚举类⚙函数进阶 泛型函数 Rust采纳了C中的泛型机制&#xff0c;并且形式上也几乎借鉴了C&#xff0c;示例如下 fn add<T: std::ops::Add<Output T>>(a:T, b:T) -> T {a b } fn…

Java智慧工地管理平台可视化大数据建造工地APP源码

建筑行业是国民经济的重要物质生产部门和支柱产业之一&#xff0c;同时&#xff0c;建筑业也是一个安全事故多发的高危行业。如何加强施工现场安全管理、降低事故发生频率、杜绝各种违规操作和不文明施工、提高建筑工程质量&#xff0c;是摆在各级政府部门、施工企业面前的一道…

一文学会Scala【Scala一站式学习笔记】

文章目录 为什么要学习Scala语言什么是Scala如何快速掌握Scala语言Scala环境安装配置Scala命令行 Scala的基本使用变量数据类型操作符if 表达式语句终结符循环高级for循环 Scala的集合体系集合SetListMapArrayArrayBuffer数组常见操作Tuple总结 Scala中函数的使用函数的定义函数…