当前位置: 首页 > article >正文

从一道经典OJ题出发:详解二叉树‘凹入表示法’的输出技巧与C++实现

从一道经典OJ题出发详解二叉树‘凹入表示法’的输出技巧与C实现1. 凹入表示法的独特魅力与实现挑战在算法竞赛和数据结构面试中二叉树的输出格式往往成为区分选手水平的关键细节。不同于常见的层序遍历或图形化展示凹入表示法Indented Notation以其独特的视觉呈现方式能够清晰展现树形结构的层级关系。这种表示法要求每个子节点比其父节点多缩进固定空格数通常为3个形成类似文件目录结构的视觉效果。实现凹入表示法的核心挑战在于如何优雅地控制递归过程中的缩进量。让我们先看一个典型示例的输出效果BiTree a b d c e这种输出方式虽然不如图形化表示直观但在纯文本环境下能准确反映树形结构特别适合OJ系统的输出限制。更重要的是它训练了开发者对递归和树形结构的深度理解能力。2. 递归实现中的缩进控制艺术实现凹入表示法的关键在于递归函数中缩进参数的传递。以下是核心代码实现void printIndented(BiTree node, int depth) { if (node nullptr || node-data #) return; // 打印缩进 for (int i 0; i depth; i) cout ; // 每个层级缩进3个空格 cout node-data endl; // 递归处理子树深度1 printIndented(node-lchild, depth 1); printIndented(node-rchild, depth 1); }这段代码的精妙之处在于深度参数传递depth参数记录当前递归层级决定缩进量先序递归顺序根-左-右的顺序确保父节点总是出现在子节点上方边界条件处理遇到空节点(#)立即返回避免无效访问提示在实际OJ题目中通常要求初始调用时depth0表示根节点不缩进3. 完整解题框架的模块化设计一个完整的二叉树OJ题目通常包含多个关联操作。以下是模块化设计的推荐结构struct TreeNode { char val; TreeNode *left; TreeNode *right; TreeNode(char x) : val(x), left(nullptr), right(nullptr) {} }; class BinaryTreeSolution { public: // 1. 建树 TreeNode* buildTree(const string preorder) { static int index 0; if (index preorder.size() || preorder[index] #) { index; return nullptr; } TreeNode* node new TreeNode(preorder[index]); node-left buildTree(preorder); node-right buildTree(preorder); return node; } // 2. 凹入表示法输出 void printIndented(TreeNode* root, int depth 0) { /* 实现见上一节 */ } // 3. 三种遍历序列 void preorder(TreeNode* root, string res) { if (!root) return; res root-val; preorder(root-left, res); preorder(root-right, res); } // 4. 交换左右子树 void swapSubtrees(TreeNode* root) { if (!root) return; swap(root-left, root-right); swapSubtrees(root-left); swapSubtrees(root-right); } // 5. 统计叶子节点 int countLeaves(TreeNode* root) { if (!root) return 0; if (!root-left !root-right) return 1; return countLeaves(root-left) countLeaves(root-right); } };这种封装方式具有以下优势高内聚低耦合每个功能独立成方法可复用性相同方法可用于不同问题的求解易于测试可以单独验证每个功能模块4. 边界条件与特殊情况的处理在实际编码中以下边界情况需要特别注意空树处理if (root nullptr) { cout Empty tree endl; return; }单节点树输入a## 输出 BiTree a完全左斜树输入a#b#c### 输出 BiTree a b c带空节点的表示扩展先序序列中用#表示空节点凹入表示法中不显示空节点注意OJ题目通常对输出格式有严格要求包括空格数量、换行位置等务必仔细阅读题目说明5. 性能优化与代码风格建议对于算法竞赛和面试场景代码不仅要正确还需要考虑以下方面时间复杂度对比操作时间复杂度空间复杂度建树O(n)O(n)凹入表示法O(n)O(h)交换子树O(n)O(h)统计叶子节点O(n)O(h)推荐的代码优化技巧避免全局变量使用局部变量或类成员变量代替// 不推荐 int leafCount 0; // 推荐 int countLeaves(TreeNode* root) { if (!root) return 0; /* ... */ }使用现代C特性// 使用智能指针管理内存 unique_ptrTreeNode buildTree(...) { /* ... */ }输入处理优化// 一次性读取所有输入 string input; getline(cin, input); TreeNode* root buildTree(input);6. 教学案例从零实现完整OJ解答让我们通过一个完整案例演示如何系统性地解决这类问题问题描述 给定扩展先序序列实现凹入表示法输出三种遍历序列叶子节点计数子树交换后的上述操作解决方案#include iostream #include string #include algorithm using namespace std; struct TreeNode { char val; TreeNode *left, *right; TreeNode(char x) : val(x), left(nullptr), right(nullptr) {} }; class BinaryTreeProcessor { int index; string preorderSeq; TreeNode* build() { if (index preorderSeq.size() || preorderSeq[index] #) { index; return nullptr; } TreeNode* node new TreeNode(preorderSeq[index]); node-left build(); node-right build(); return node; } public: TreeNode* buildTree(const string seq) { index 0; preorderSeq seq; return build(); } void printIndented(TreeNode* node, int depth 0) { if (!node) return; cout string(depth * 3, ) node-val endl; printIndented(node-left, depth 1); printIndented(node-right, depth 1); } void traverse(TreeNode* root, string pre, string in, string post) { if (!root) return; pre root-val; traverse(root-left, pre, in, post); in root-val; traverse(root-right, pre, in, post); post root-val; } int countLeaves(TreeNode* root) { if (!root) return 0; if (!root-left !root-right) return 1; return countLeaves(root-left) countLeaves(root-right); } void swapSubtrees(TreeNode* root) { if (!root) return; swap(root-left, root-right); swapSubtrees(root-left); swapSubtrees(root-right); } }; int main() { string input ab#d##ce###; BinaryTreeProcessor processor; // 原始树处理 TreeNode* root processor.buildTree(input); cout BiTree\n; processor.printIndented(root); string pre, in, post; processor.traverse(root, pre, in, post); cout pre_sequence : pre endl; cout in_sequence : in endl; cout post_sequence : post endl; cout Number of leaf: processor.countLeaves(root) endl; // 交换子树后处理 processor.swapSubtrees(root); cout BiTree swapped\n; processor.printIndented(root); pre.clear(); in.clear(); post.clear(); processor.traverse(root, pre, in, post); cout pre_sequence : pre endl; cout in_sequence : in endl; cout post_sequence : post endl; return 0; }这个实现展示了几个关键实践封装完整解决方案所有操作封装在BinaryTreeProcessor类中分离构建与处理逻辑buildTree与各种操作解耦简洁的字符串处理使用string类简化序列构建避免重复代码traverse方法同时生成三种遍历序列7. 常见错误分析与调试技巧在实现凹入表示法时开发者常会遇到以下典型问题错误1缩进量不正确// 错误示例缩进量累积错误 void printWrong(TreeNode* node, int spaces) { if (!node) return; cout string(spaces, ) node-val endl; printWrong(node-left, spaces); // 后置导致问题 printWrong(node-right, spaces); }修正方法printCorrect(node-left, spaces 1); // 使用表达式而非自增 printCorrect(node-right, spaces 1);错误2忽略空节点处理// 错误示例未处理#节点 void visit(TreeNode* node) { cout node-val; // 可能访问空节点 }修正方法void visitSafe(TreeNode* node) { if (node node-val ! #) cout node-val; }调试建议可视化小树先用3-4个节点的小树测试检查边界条件空树、单节点树、单边树输出中间状态在递归中打印当前深度和节点值使用内存检测工具确保没有内存泄漏8. 扩展思考与其他表示法的对比凹入表示法与其他树形表示方式各有优劣表示方法优点缺点适用场景凹入表示法简单直观易于文本输出大型树结构显示不清晰OJ题目、简单调试输出括号表示法紧凑节省空间层级关系不明显序列化存储图形化表示最直观易于理解需要图形支持实现复杂教学演示、可视化工具层序遍历表示符合广度优先思维无法直接体现父子关系某些特定算法需求对于需要频繁调试树形结构的开发者建议掌握多种表示法的转换技巧。例如以下是将凹入表示法转换为括号表示法的实现string toParenthesisNotation(TreeNode* root) { if (!root) return ; if (!root-left !root-right) return string(1, root-val); string left toParenthesisNotation(root-left); string right toParenthesisNotation(root-right); return string(1, root-val) ( left , right ); }在实际项目开发中根据具体需求选择合适的表示法往往能达到事半功倍的效果。凹入表示法虽然简单但在需要快速验证树形结构的场景下仍然是不可替代的调试工具。

相关文章:

从一道经典OJ题出发:详解二叉树‘凹入表示法’的输出技巧与C++实现

从一道经典OJ题出发:详解二叉树‘凹入表示法’的输出技巧与C实现 1. 凹入表示法的独特魅力与实现挑战 在算法竞赛和数据结构面试中,二叉树的输出格式往往成为区分选手水平的关键细节。不同于常见的层序遍历或图形化展示,凹入表示法&#xff0…...

ESFT-gate-summary-lite:AI快速提炼文本关键信息

ESFT-gate-summary-lite:AI快速提炼文本关键信息 【免费下载链接】ESFT-gate-summary-lite ESFT-gate-summary-lite模型,基于DeepSeek-ai的开源项目,专注于提升基础模型摘要能力。源自ESFT-vanilla-lite,强化文本摘要,…...

嵌入式系统开发中的关键技术术语解析

嵌入式系统开发中的56个关键技术术语解析1. 数据转换基础概念1.1 采样与保持特性采集时间(Tacq)是从释放保持状态到采样电容电压稳定至新输入值的1 LSB范围之内所需的时间。在采样-保持电路中,这个参数直接影响系统的动态性能。孔径延迟(tAD)描述从时钟信号的采样沿…...

OpenClaw技能分享:GLM-4.7-Flash驱动的邮件自动处理系统

OpenClaw技能分享:GLM-4.7-Flash驱动的邮件自动处理系统 1. 为什么需要自动化邮件处理 每天早晨打开邮箱,看到堆积如山的未读邮件总让人头皮发麻。作为一个小团队的负责人,我经常需要处理客户咨询、内部沟通、会议邀请等各种类型的邮件。最…...

避免踩坑:Unity中Resources.LoadAll的正确使用姿势(含multiple模式Sprite处理)

Unity资源加载进阶:Resources.LoadAll与Sprite图集高效处理指南 在Unity开发中,资源加载是每个项目都无法绕开的核心环节。特别是当处理包含多张小图的Sprite图集时,很多开发者会陷入性能陷阱和功能误区。本文将深入剖析Resources.LoadAll的正…...

CAN总线波特率计算器工具开发指南(Python+PyQt5)

CAN总线波特率计算器工具开发指南(PythonPyQt5) 在汽车电子工程领域,CAN总线作为车载网络的骨干,其通信质量直接影响整车系统的稳定性。而波特率作为CAN通信的基础参数,其配置精度直接决定了总线能否正常工作。传统的手…...

基于西门子PLC的矿井通风控制系统(含IO表、PLC引脚图、程序) PLC程序设计,价格便宜

基于西门子PLC的矿井通风控制系统(含IO表、PLC引脚图、程序) PLC程序设计,价格便宜,plc触摸屏上位机程序设计,编写。 西门子plc仿真程序设计 提供程序说明, plc程序代写 PLC程序设计、代做 图片为案例 接设…...

UniHacker:跨平台支持的开源工具快速部署方案

UniHacker:跨平台支持的开源工具快速部署方案 【免费下载链接】UniHacker 为Windows、MacOS、Linux和Docker修补所有版本的Unity3D和UnityHub 项目地址: https://gitcode.com/GitHub_Trending/un/UniHacker UniHacker作为一款专业的开源工具,凭借…...

TIG电弧熔池一体化与MIG电弧熔滴蒸汽一体化

TIG电弧熔池一体化MIG电弧熔滴蒸汽一体化最近在搞焊接数值模拟的朋友估计都被TIG和MIG的热力耦合模型折腾过。这俩工艺看着都是电弧焊,实际在建模时完全不是一个次元的难度。今天咱们就扒一扒TIG熔池和MIG熔滴这对冤家的建模套路。先说TIG电弧熔池一体化建模。核心难…...

语言清洗令:禁用for循环的第一年——软件测试从业者的专业复盘与策略革新

2025年全球编程社区发起的“语言清洗运动”,标志着软件开发范式的重大转折。这项运动的核心是禁用传统循环语句(如for、while),以推动声明式编程的普及,减少迭代错误并提升代码可读性。作为软件测试从业者,…...

使用 HashMap 优化嵌套循环:Java 对象数组转换

本文旨在提供使用 HashMap 优化 Java 嵌套循环的有效方法,特别是当循环涉及对象数组并进行相等检查时。通过将内部循环转换为 HashMap 查询可以显著降低时间复杂性,提高代码性能。本文将提供详细的步骤和示例代码,以帮助读者理解和应用此优化…...

leOS2:基于看门狗定时器的轻量级嵌入式调度器

1. leOS2:基于看门狗定时器的轻量级嵌入式调度器 leOS2(little embedded Operating System 2)是一个专为资源受限的8位AVR微控制器设计的极简实时调度器。它不依赖于通用定时器(如Timer0/Timer1),而是创造…...

手把手教你用Swaks和Gophish绕过SPF,搭建自己的邮件钓鱼测试环境(附避坑指南)

企业级邮件安全测试实战:从SPF绕过到钓鱼环境搭建 邮件安全测试已成为企业安全防护体系中不可或缺的一环。据统计,超过90%的网络攻击始于钓鱼邮件,而其中近40%的成功攻击源于SPF配置不当或完全缺失。本文将系统性地介绍如何构建一个完整的邮件…...

SEO_从零开始,手把手教你制定SEO优化方案(126 )

<h2>SEO优化的基本概念</h2> <p>SEO&#xff0c;全称Search Engine Optimization&#xff0c;是搜索引擎优化的简称&#xff0c;旨在提高网站在搜索引擎中的自然排名&#xff0c;从而增加网站的可见度和流量。对于初学者来说&#xff0c;SEO可能听起来有点复…...

别再傻傻分不清了!IM和RTC到底差在哪?从微信聊天到腾讯会议的技术选择

IM与RTC技术选型指南&#xff1a;从协议栈到商业场景的深度解析 当你的产品经理在白板上画出一个"消息气泡"和一个"视频通话图标"时&#xff0c;技术团队首先需要面对的灵魂拷问是&#xff1a;这到底该用IM架构还是RTC架构&#xff1f;2019年某在线教育初创…...

告别代码噩梦:用Awesome-Dify-Workflow零代码30分钟实现企业级登录系统

告别代码噩梦&#xff1a;用Awesome-Dify-Workflow零代码30分钟实现企业级登录系统 【免费下载链接】Awesome-Dify-Workflow 分享一些好用的 Dify DSL 工作流程&#xff0c;自用、学习两相宜。 Sharing some Dify workflows. 项目地址: https://gitcode.com/GitHub_Trending/…...

C# : 引用类型都存在堆上吗

不完全是&#xff0c;这里要精确区分&#xff1a;引用类型的实例大多数存在堆上&#xff0c;但引用本身不一定在堆上。我们拆开来说&#xff1a;引用类型本身 vs 引用变量对象实例&#xff08;类的实例&#xff09;绝大多数情况下分配在 堆上由 垃圾回收器 管理生命周期引用变量…...

ArcGIS字段值提取:别再手动截取了,用Python和VB脚本5分钟搞定

ArcGIS字段值提取&#xff1a;Python与VB脚本高效自动化方案 引言&#xff1a;告别低效手工操作 在GIS数据处理工作中&#xff0c;属性表字段值的提取是再常见不过的操作。想象一下这样的场景&#xff1a;你手头有一份包含数万条记录的行政区划数据&#xff0c;需要从"BSM…...

别再只调PID了!基于STM32C8T6的电磁循迹小车,从硬件滤波到软件算法的抗干扰全攻略

电磁循迹小车的抗干扰实战&#xff1a;从硬件滤波到软件优化的全链路解决方案 当你的电磁循迹小车在实验室里跑得风生水起&#xff0c;一到比赛现场却频频"抽风"&#xff0c;这往往不是PID参数调得不够好&#xff0c;而是整个系统的抗干扰设计存在漏洞。本文将带你深…...

Pixel Fashion Atelier企业应用:支持Webhook回调的自动化素材生成流水线搭建

Pixel Fashion Atelier企业应用&#xff1a;支持Webhook回调的自动化素材生成流水线搭建 1. 项目背景与价值 Pixel Fashion Atelier是一款基于Stable Diffusion与Anything-v5的图像生成工作站&#xff0c;专为企业级素材生产需求设计。传统AI工具往往面临两大挑战&#xff1a…...

Vue项目里用Frappe-Gantt 0.6.1做项目管理甘特图,我踩过的坑都在这了

Vue项目中集成Frappe-Gantt的避坑指南与工程化实践 在最近的一个敏捷开发项目中&#xff0c;我们需要为产品团队提供一个直观的任务进度管理工具。经过几轮技术选型&#xff0c;最终选择了Frappe-Gantt 0.6.1作为基础组件。这个选择并非一帆风顺——从最初的简单集成到最终形成…...

终极指南:5个实用技巧解决Rainmeter开发中的内存保护异常问题

终极指南&#xff1a;5个实用技巧解决Rainmeter开发中的内存保护异常问题 【免费下载链接】rainmeter Desktop customization tool for Windows 项目地址: https://gitcode.com/gh_mirrors/ra/rainmeter 在Rainmeter桌面定制工具的开发过程中&#xff0c;内存保护异常&a…...

解锁音乐格式终极指南:一键解决加密音频播放难题

解锁音乐格式终极指南&#xff1a;一键解决加密音频播放难题 【免费下载链接】unlock-music 在浏览器中解锁加密的音乐文件。原仓库&#xff1a; 1. https://github.com/unlock-music/unlock-music &#xff1b;2. https://git.unlock-music.dev/um/web 项目地址: https://gi…...

手把手教你用EFR32BG22实现BLE串口透传(附GATT配置全流程)

EFR32BG22低功耗蓝牙串口透传开发实战指南 在物联网终端设备开发中&#xff0c;蓝牙串口透传是最基础也最实用的功能之一。本文将带您深入EFR32BG22芯片的蓝牙开发世界&#xff0c;从零开始构建一个高效的BLE串口透传服务。不同于简单的代码搬运&#xff0c;我们将重点关注GATT…...

ESP32烧录全攻略:从命令行到GUI工具,新手也能轻松搞定

ESP32烧录全攻略&#xff1a;从命令行到GUI工具&#xff0c;新手也能轻松搞定 第一次接触ESP32开发板时&#xff0c;那块小小的芯片里蕴藏着无限可能&#xff0c;但如何将自己的代码"装进"这个硬件大脑却成了拦路虎。记得我最初尝试烧录时&#xff0c;面对各种专业术…...

百度快速排名优化技术(百度seo排名优化)

百度快速排名优化技术是一种针对搜索引擎结果页面&#xff08;SERP&#xff09;排名优化的技术手段&#xff0c;通过优化网站的内容、结构和用户体验等方面&#xff0c;提高网站在搜索引擎中的排名&#xff0c;从而获得更多的流量和潜在客户。下面&#xff0c;我将介绍百度快速…...

哔哩下载姬DownKyi实用指南:从新手到高手的进阶之路

哔哩下载姬DownKyi实用指南&#xff1a;从新手到高手的进阶之路 【免费下载链接】downkyi 哔哩下载姬downkyi&#xff0c;哔哩哔哩网站视频下载工具&#xff0c;支持批量下载&#xff0c;支持8K、HDR、杜比视界&#xff0c;提供工具箱&#xff08;音视频提取、去水印等&#xf…...

易语言实现阶乘与组合数计算

是的&#xff0c;我听说过易语言&#xff0c;它是一款面向中文使用者的编程语言&#xff0c;以其直观的中文语法和图形化界面开发能力而著称。 一、 数学概念解析 在深入编程实现前&#xff0c;我们先明确两个基础的数学概念。 1. 阶乘 阶乘 是所有小于及等于该数的正整数的…...

如何通过FCEUX实现NES游戏的完美模拟?超实用指南

如何通过FCEUX实现NES游戏的完美模拟&#xff1f;超实用指南 【免费下载链接】fceux FCEUX, a NES Emulator 项目地址: https://gitcode.com/gh_mirrors/fc/fceux 5个步骤3个技巧&#xff0c;让你快速掌握NES模拟器 核心价值&#xff1a;重温和探索经典游戏的最佳选择 …...

提升效率:用快马一键生成网络应用用户认证api模块

最近在开发一个网络应用时&#xff0c;遇到了用户认证模块的重复开发问题。每次新建项目都要从头写注册登录逻辑&#xff0c;不仅耗时还容易出错。后来发现了InsCode(快马)平台的智能生成功能&#xff0c;帮我快速解决了这个问题。 用户认证模块的核心需求 网络应用中&#xff…...