文章目录

  • 先上效果图
  • 然后上代码
    • 测试用例:
  • 思路
  • 写在最后

先上效果图

然后上代码

 /*** 中序遍历返回节点数组* @param root 根节点* @return 中序遍历节点数组*/std::vector<TreeNode *> inorderTraversal(TreeNode *root) {std::vector<TreeNode *> res;std::stack<TreeNode *> stk;while (root != nullptr || !stk.empty()) {while (root != nullptr) {stk.push(root);root = root->left;}root = stk.top();stk.pop();res.push_back(root);root = root->right;}return res;}
    /*** 利用下划线和正反斜杠打印出美观的二叉树,没有破坏二叉树结构,但传入的root会有变化* @param root  二叉树根节点*/void printTree(TreeNode *root) {if (!root)return;auto tmp = root;std::vector<TreeNode *> intv = inorderTraversal(tmp);//中序遍历节点数组std::string template_str;//模板string,表示每行打印string的长度int location = 0;std::unordered_map<TreeNode *, int> first_locations;//存储节点对应在本行string中的首位置for (auto &i : intv) {location = template_str.size();template_str += std::to_string(i->val) + " ";first_locations[i] = location;}for (auto &i:template_str)i = ' ';//把模板全部置为空格方便后续使用//层序遍历std::queue<TreeNode *> q;q.push(root);while (!q.empty()) {int currentLevelSize = q.size();int cur_loc = 0;std::string tmp_str1 = template_str, tmp_str2 = template_str;//1为节点所在行,2为其下一行for (int i = 1; i <= currentLevelSize; ++i) {auto node = q.front();q.pop();cur_loc = first_locations[node];std::string num_str = std::to_string(node->val);//左边,如果存在左孩子,那么在第二行对应位置打印'/',在第一行补上'_'if (node->left) {q.push(node->left);int first_loc = first_locations[node->left] + 1;tmp_str2[first_loc++] = '/';while (first_loc < cur_loc)tmp_str1[first_loc++] = '_';}//中间,对应位置打印节点值(有可能为多位数)for (int j = 0; j < num_str.length(); ++j, ++cur_loc) {tmp_str1[cur_loc] = num_str[j];}//右边,如果存在右孩子,那么在第二行对应位置打印'\',在第一行补上'_'if (node->right) {q.push(node->right);int last_loc = first_locations[node->right] - 1;tmp_str2[last_loc] = '\\';while (cur_loc < last_loc) {tmp_str1[cur_loc++] = '_';}}}//打印两行std::cout << tmp_str1 << std::endl;std::cout << tmp_str2 << std::endl;}}

测试用例:

tools.hpp

#include <sstream>
#include "iostream"
#include "stdlib.h"
#include "vector"
#include "cmath"
#include "algorithm"
#include "map"
#include "fstream"
#include "queue"
#include "unordered_map"
#include "unordered_set"
#include "stack"//Definition for a binary tree node.
struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode() : val(0), left(nullptr), right(nullptr) {}TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};namespace tools {// Binary tree*********************************************************/*** 中序遍历返回节点数组* @param root 根节点* @return 中序遍历节点数组*/std::vector<TreeNode *> inorderTraversal(TreeNode *root) {std::vector<TreeNode *> res;std::stack<TreeNode *> stk;while (root != nullptr || !stk.empty()) {while (root != nullptr) {stk.push(root);root = root->left;}root = stk.top();stk.pop();res.push_back(root);root = root->right;}return res;}void trimLeftTrailingSpaces(std::string &input) {input.erase(input.begin(), find_if(input.begin(), input.end(), [](int ch) {return !isspace(ch);}));}void trimRightTrailingSpaces(std::string &input) {input.erase(find_if(input.rbegin(), input.rend(), [](int ch) {return !isspace(ch);}).base(), input.end());}TreeNode *stringToTreeNode(std::string input) {trimLeftTrailingSpaces(input);trimRightTrailingSpaces(input);input = input.substr(1, input.length() - 2);if (!input.size()) {return nullptr;}std::string item;std::stringstream ss;ss.str(input);getline(ss, item, ',');TreeNode *root = new TreeNode(stoi(item));std::queue<TreeNode *> nodeQueue;nodeQueue.push(root);while (true) {TreeNode *node = nodeQueue.front();nodeQueue.pop();if (!getline(ss, item, ',')) {break;}trimLeftTrailingSpaces(item);if (item != "null") {int leftNumber = stoi(item);node->left = new TreeNode(leftNumber);nodeQueue.push(node->left);}if (!getline(ss, item, ',')) {break;}trimLeftTrailingSpaces(item);if (item != "null") {int rightNumber = stoi(item);node->right = new TreeNode(rightNumber);nodeQueue.push(node->right);}}return root;}/*** 利用下划线和正反斜杠打印出美观的二叉树,没有破坏二叉树结构,但传入的root会有变化* @param root  二叉树根节点*/void printTree(TreeNode *root) {if (!root)return;auto tmp = root;std::vector<TreeNode *> intv = inorderTraversal(tmp);//中序遍历节点数组std::string template_str;//模板string,表示每行打印string的长度int location = 0;std::unordered_map<TreeNode *, int> first_locations;//存储节点对应在本行string中的首位置for (auto &i : intv) {location = template_str.size();template_str += std::to_string(i->val) + " ";first_locations[i] = location;}for (auto &i:template_str)i = ' ';//把模板全部置为空格方便后续使用//层序遍历std::queue<TreeNode *> q;q.push(root);while (!q.empty()) {int currentLevelSize = q.size();int cur_loc = 0;std::string tmp_str1 = template_str, tmp_str2 = template_str;//1为节点所在行,2为其下一行for (int i = 1; i <= currentLevelSize; ++i) {auto node = q.front();q.pop();cur_loc = first_locations[node];std::string num_str = std::to_string(node->val);//左边,如果存在左孩子,那么在第二行对应位置打印'/',在第一行补上'_'if (node->left) {q.push(node->left);int first_loc = first_locations[node->left] + 1;tmp_str2[first_loc++] = '/';while (first_loc < cur_loc)tmp_str1[first_loc++] = '_';}//中间,对应位置打印节点值(有可能为多位数)for (int j = 0; j < num_str.length(); ++j, ++cur_loc) {tmp_str1[cur_loc] = num_str[j];}//右边,如果存在右孩子,那么在第二行对应位置打印'\',在第一行补上'_'if (node->right) {q.push(node->right);int last_loc = first_locations[node->right] - 1;tmp_str2[last_loc] = '\\';while (cur_loc < last_loc) {tmp_str1[cur_loc++] = '_';}}}//打印两行std::cout << tmp_str1 << std::endl;std::cout << tmp_str2 << std::endl;}}}

main.cpp

#include "tools.hpp"
int main() {tools::printTree(tools::stringToTreeNode("[1,1,1,1,1,1,1,11,3,213,21,13,21,31,321,321,654,684,1,87,94,1,1687,941,4,984,21,65,4987]"));return 0;
}

运行结果如前面效果图。

思路

首先中序遍历得到每个节点在每行的位置
比如这个树长这样
那么它的中序遍历就是4 2 5 1 10 3;
按中序遍历的顺序逐个插入节点值字符串空格,得到字符串"4 2 5 1 10 3 ";
如果每行的节点都按上述字符串的位置摆放,是不会出现矛盾的,而且预留了'\'、'/'、'_'的位置。

//中序遍历模板string
4 2 5 1 10 3
//按行按模板摆放1 2        3
4   5   10
//增加符号__1___/      \2       _3 / \     /
4   5   10

写在最后

为啥写这个,完全是因为在网上没找到类似的程序,可能是我关键词没搜索对吧;
还有就是闲的,很久不写博客都快忘了这个东西了;
最后就是我又想造福大众了,点个赞让我知道这篇文章帮过你。

c++二叉树打印(只为美观)相关推荐

  1. 二叉排序树遍历二叉树打印简单图书管理系统

    二叉排序树的实现 实验内容: 解决方案与关键代码: 解决方案: 编程生成二叉排序树 非递归二叉树遍历 先序 中序 后序 二叉树的打印 简单图书系统 二叉排序树图书管理系统 图书类 构造函数BTree ...

  2. 《剑指offer》-- 二叉树的下一个结点、对称二叉树、按之字性顺序打印二叉树、把二叉树打印成多行

    一.二叉树的下一个结点: 1.题目: 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针. 2.解题思路: 分析二叉树 ...

  3. 二叉树打印叶子节点,非递归_使用递归打印链接列表中的备用节点

    二叉树打印叶子节点,非递归 Solution: 解: Input: A singly linked list whose address of the first node is stored in ...

  4. android 打印机列表中,在android中打印只搜索打印机

    我已经做了一个android应用程序,我试图打印一个示例文本文件,我想使用wifi连接打印机,我试过这个链接Wifi printing in android但它只是去搜索wifi打印机和什么都不做,我 ...

  5. 剑指offer——面试题60:把二叉树打印成多行

    剑指offer--面试题60:把二叉树打印成多行 Solution1: 20180911重做.经典题目.牢记做法! /* struct TreeNode {int val;struct TreeNod ...

  6. Excel打印表格如何美观又漂亮

    Excel打印表格如何美观又漂亮 目录 Excel打印表格如何美观又漂亮 1.首先点击打印预览,勾选 "显示边距",看见表格没有充满整个页面,再点击"关闭打印预览&quo ...

  7. 剑指offer编程试题Java实现--60.把二叉树打印成多行

    个人博客:小景哥哥 60.把二叉树打印成多行 题目描述 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行. import java.util.ArrayList; import java ...

  8. 剑指Offer(Java实现)把二叉树打印成多行

    题目描述 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行. 解题思路 利用辅助空间链表或队列来存储节点,每层输出. 代码实现 import java.util.ArrayList; i ...

  9. 《剑指offer》把二叉树打印成多行

    题目:从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行. 解析:层次遍历二叉树,要点是要用队列存储节点信息.还有个问题,如何知道要换层?答案是用一个计数器current指示当前层的节点个 ...

最新文章

  1. .NET Winform也能画出类似QQ、飞信这样的窗口风格和控件效果
  2. python删除重复值所在的行数_使用python读取txt文件的内容,并删除重复的行数方法...
  3. 65% 的钱被头部玩家拿走,人工智能要进入下半场?
  4. (0106)iOS开发之iOS13 适配
  5. 干货:嵌入式C语言源代码优化方案(非编译器优化)
  6. mysql断电同步不起作用_mysql主从同步因断电产生的不能同步问题
  7. yzmcms图片自适应代码_基于segment.js制作的非常有创意的分段式SVG文字动画特效...
  8. ajax请求完之前的loading加载
  9. BFS(广度优先算法)
  10. c语言的log算法实现,C语言中有关log函数的算法
  11. python词云词频分析_Python数据挖掘:WordCloud词云配置过程及词频分析
  12. 核密度估计_拔剑-浆糊的传说_新浪博客
  13. Python基于周立功盒子的二次开发的封装和调用
  14. 再谈目前QQ空间主流的赚钱方法
  15. 电脑开机转到计算机状态页面,如何让电脑每次开机都恢复原来的状态?-开机启动项怎么设置...
  16. Linux 下的截屏并编辑的工具-flamshot安装及使用
  17. PHP compact() 函数,好用!
  18. Kali中常用的代理工具以及使用
  19. STM32超低功耗入门之关机模式
  20. 深度学习入门必看25个基本概念

热门文章

  1. 基于java实现下载excel
  2. eggjs mysql_阿里开源eggjs,eggjs+ejs+mysql 初始化项目,简单记录
  3. CRUD的意思???
  4. 安卓修改包名和Project
  5. Html转义字符表详细记录
  6. Docker下删除镜像报错 (cannot be forced) - image has dependent child images
  7. 如何彻底关闭2345流氓软件附带的广告(弹窗,工具栏搜索taskbarsearch,右下角信息展示)
  8. gateway sentinel 熔断 不起作用_熔断器交流与直流有什么区别?错过这篇文章悔之晚矣!【超详细】上海民熔...
  9. 微信开发网页授权的两种方式
  10. Fastqc使用说明