发布时间:2026/8/27 19:44:17
从零开始的敲代码生活--数据结构篇(二叉树) 一、二叉树基础概念树由根节点和若干个子节点构成的具有一对多关系的数据的集合称为树形结构。术语说明空树一个结点都没有根节点最顶层节点叶子节点(终端节点)没有子节点的结点称为叶子节点(节点的度为 0)分支节点有子节点的节点节点的度节点的子节点个数树的深度树的层数树的度(广度)树中节点最大的度是该树的广度二叉树树的广度为二的树形结构称为二叉树且各节点的左右子节点不能交换。满二叉树在不增加层数的前提下无法再增加一个节点。K 层满二叉树第 K 层的节点个数$2^{(K-1)}$K 层总共节点个数$2^K - 1$完全二叉树在满二叉树基础上按照从左至右从上至下的顺序增加节点该树是完全二叉树在满二叉树基础上按照从下至上从右至左的顺序删除节点该树是完全二叉树满二叉树一定是完全二叉树二叉树的遍历深度优先遍历算法前序遍历根、左子树、右子树 → ABFGCDHIE中序遍历左子树、根、右子树 → FBCGAHIDE后序遍历左子树、右子树、根 → FCGBIHEDA广度优先遍历算法层序遍历从上至下从左至右逐层遍历 → ABDFGHECI由遍历序列还原二叉树已知前序遍历和中序遍历结果可以唯一还原一棵二叉树已知后序遍历和中序遍历结果可以唯一还原一棵二叉树**文件的创建方式**二叉树采用前序遍历的方式创建字符串ABF##GC###DH#I##E##中#表示该位置为空子树(NULL)。文件说明文件说明tree.h头文件二叉树结点结构体定义 函数声明tree.c源文件二叉树创建、遍历、求结点个数、求深度、释放等功能实现cyclequeue.h头文件层序遍历辅助循环队列(存储树结点指针)cyclequeue.c源文件循环队列功能实现main.c测试 main 函数二、头文件 tree.h#ifndef _TREE_H #define _TREE_H #include stdio.h #include stdlib.h #include string.h #include cyclequeue.h typedef char Data_t; /* 二叉树结点结构体:数据域 左子树指针 右子树指针 */ typedef struct tree_node { Data_t data; // 数据域:保存的数据 struct tree_node *pl; // 指针域:左子树根结点地址 struct tree_node *pr; // 指针域:右子树根结点地址 }TNode_t; extern TNode_t *create_tree(); extern void show_pro_tree(TNode_t *ptree); extern void show_mid_tree(TNode_t *ptree); extern void show_pos_tree(TNode_t *ptree); extern int get_tree_node_cnt(TNode_t *ptree); extern int get_tree_deep(TNode_t *ptree); extern void free_tree(TNode_t *ptree); extern void lay_tree(TNode_t *ptree); extern void show_lay_tree(TNode_t *ptree); #endif三、功能实现 tree.ccreate_tree 创建二叉树功能按前序遍历顺序读取全局数组 bin_tree[] 中的数据创建二叉树读到#表示该位置为空子树返回 NULL。返回树根结点指针malloc 失败返回 NULL。Data_t bin_tree[] ABF##GC###DH#I##E##; int i 0; TNode_t *create_tree() { if(bin_tree[i] #) { i; return NULL; } TNode_t *ptree malloc(sizeof(TNode_t)); if(ptree NULL) { printf(malloc fail\n); return NULL; } ptree-data bin_tree[i]; ptree-pl create_tree(); ptree-pr create_tree(); return ptree; }pro_tree 前序遍历功能按根、左子树、右子树的顺序递归遍历打印结点。void pro_tree(TNode_t *ptree) { if(ptree NULL) { return; } printf(%c,ptree-data); pro_tree(ptree-pl); pro_tree(ptree-pr); return; }pos_tree 后序遍历功能按左子树、右子树、根的顺序递归遍历打印结点。void pos_tree(TNode_t *ptree) { if(ptree NULL) { return; } pos_tree(ptree-pl); pos_tree(ptree-pr); printf(%c,ptree-data); return; }mid_tree 中序遍历功能按左子树、根、右子树的顺序递归遍历打印结点。void mid_tree(TNode_t *ptree) { if(ptree NULL) { return; } mid_tree(ptree-pl); printf(%c,ptree-data); mid_tree(ptree-pr); return; }show_pro_tree / show_mid_tree / show_pos_tree 遍历封装功能分别调用 pro_tree、mid_tree、pos_tree 完成遍历并在结尾打印换行。void show_pro_tree(TNode_t *ptree) { pro_tree(ptree); printf(\n); } void show_mid_tree(TNode_t *ptree) { mid_tree(ptree); printf(\n); } void show_pos_tree(TNode_t *ptree) { pos_tree(ptree); printf(\n); }get_tree_node_cnt 求结点个数功能递归统计二叉树结点总个数(1 左子树个数 右子树个数)。返回结点个数空树返回 0。int get_tree_node_cnt(TNode_t *ptree) { if(ptree NULL) { return 0; } return 1 get_tree_node_cnt(ptree-pl) get_tree_node_cnt(ptree-pr); }get_tree_deep 求树的深度功能递归求二叉树深度(左子树深度与右子树深度较大者 1)。返回树的深度空树返回 0。int get_tree_deep(TNode_t *ptree) { if(ptree NULL) { return 0; } return get_tree_deep(ptree-pl) get_tree_deep(ptree-pr) ? get_tree_deep(ptree-pl)1 : get_tree_deep(ptree-pr)1; }free_tree 释放二叉树功能按后序顺序递归释放所有结点(先释放左、右子树最后释放根结点)。void free_tree(TNode_t *ptree) { if(ptree NULL) { return; } free_tree(ptree-pl); free_tree(ptree-pr); free(ptree); }lay_tree 层序遍历功能借助循环队列实现广度优先遍历。根结点先入队循环出队打印结点并将其左、右孩子依次入队直到队列为空。返回:void空树直接返回。void lay_tree(TNode_t *ptree) { if(ptree NULL) { return; } CQue_t *pcque create_cyclequeue(); if(pcque NULL) { return; } en_cycle_queue(pcque,ptree); while(!is_empty_cycle_queue(pcque)) { TNode_t *ptemp NULL; de_cycle_queue(pcque,ptemp); printf(%c,ptemp-data); if(ptemp-pl ! NULL) { en_cycle_queue(pcque,ptemp-pl); } if(ptemp-pr ! NULL) { en_cycle_queue(pcque,ptemp-pr); } } free_cycqueue(pcque); return; } void show_lay_tree(TNode_t *ptree) { lay_tree(ptree); printf(\n); }四、层序遍历辅助循环队列层序遍历需要借助循环队列存储结点指针实现从上至下、从左至右逐层访问。该循环队列与《数据结构篇(队列)》中的循环队列实现完全一致仅存储的数据类型由 int 改为树结点指针struct tree_node。头文件 cyclequeue.h#ifndef _CYCLEQUEUE_H #define _CYCLEQUEUE_H #include stdio.h #include stdlib.h #define CYCQUE 10 struct tree_node; typedef struct tree_node* CQData_t; typedef struct cycle_queue { CQData_t *pbase; int head; int tail; }CQue_t; extern CQue_t *create_cyclequeue(); extern int is_empty_cycle_queue(CQue_t *pcque); extern int is_full_cycle_queue(CQue_t *pcque); extern int en_cycle_queue(CQue_t *pcque,CQData_t data); extern int de_cycle_queue(CQue_t *pcque,CQData_t *data); extern void free_cycqueue(CQue_t *pcque); #endifcyclequeue.c 说明各函数的实现逻辑与《数据结构篇(队列)》中的循环队列完全相同create_cyclequeue分配管理结构体 数组空间head、tail 置 0is_empty_cycle_queuehead tail判空is_full_cycle_queue(tail1) % CYCQUE head判满en_cycle_queue队尾下标处写入tail (tail1) % CYCQUEde_cycle_queue读取队头下标处数据head (head1) % CYCQUEfree_cycqueue先释放数组空间再释放管理结构体唯一区别typedef struct tree_node* CQData_t;使队列元素为树结点指针用于存放层序遍历过程中等待访问的结点。五、测试 main 函数 main.c#include tree.h int main(void) { TNode_t *ptree create_tree(); if(ptree NULL) { return -1; } show_pro_tree(ptree); show_mid_tree(ptree); show_pos_tree(ptree); show_lay_tree(ptree); int tree_node_cnt 0; printf(tree_node_cnt %d\n,get_tree_node_cnt(ptree)); printf(tree_deep %d\n,get_tree_deep(ptree)); free_tree(ptree); return 0; }六、编译运行 内存检测编译gcc main.c tree.c cyclequeue.c -o tree_demo运行程序./tree_demovalgrind 检测内存泄漏写二叉树务必检测内存泄漏保证每一块 malloc 都有对应的 freevalgrind --leak-checkfull ./tree_demo运行输出结果ABFGCDHIE FBCGAHIDE FCGBIHEDA ABDFGHECI tree_node_cnt 9 tree_deep 4

相关新闻

2026/8/27 19:39:16

1.6万元预算游戏主机:9800X3D + 5060 Ti 16G配置与装机全攻略

1.6万元预算组一台打游戏的主机,核心锁定 AMD 9800X3D 和华硕 5060 Ti 16G 显卡,这个方案的重点不是把配件列表拉满,而是把预算、兼容性和实际游戏体验一起考虑清楚。很多人看到“X3D 16G显存”就觉得可以通吃所有场景,实际装机时…

2026/8/27 19:39:16

驯服 PUNKs:ES|QL 如何查询 Elasticsearch 从未被告知的字段

作者:来自 Elastic Alexander Spies 在 Elasticsearch 9.5 中,ES|QL 可以查询未映射的字段。它会从 _source 中读取这些字段,或者返回 null,因此即使某个字段从映射中消失,查询仍然可以正常工作,从而避免需…

2026/8/27 19:39:16

AI使用与职业疏忽:从注意义务到可辩护的决策流程

不使用AI会不会有一天被定性成疏忽?这个问题最近在我自己团队里被问了很多次。往年大家讨论的是“AI能做什么”,现在已经开始讨论“不用AI会不会担责”。这个变化非常实际,因为它把AI从一个效率工具抬升到了责任工具的位置。围绕这个问题的答…

2026/8/27 20:14:19

CSAPP 3.3 Data Formats(数据格式)

第 5 课|3.3:数据格式x86 的历史宽度名称x86 名称位数字节数常见整数后缀byte81bword162wdouble word324lquad word648qx86 起源于 16 位的 8086,因此 word 固定表示 16 位。处理器扩展到 32 位和 64 位后,旧名称仍被保留&#xf…

2026/8/27 20:14:19

Java 服务调用下游接口注意点

目录 1. 必须设置超时2. 重试策略,不能无脑重试3. 熔断、降级、隔离4. 限流5. 异常处理,区分不同失败类型6. 请求参数与响应处理7. 线程池注意8. 超时时间的设计,链路整体考虑9. 资源与连接池(HTTP 客户端)10. 业务层…

2026/8/27 20:14:19

AI编程助手Skill不生效?环境配置与加载链路排查指南

最近在调整 AI 编程助手的工作流,遇到了一个特别折磨人的现象:明明按照说明把 Skill 装好了,工具列表里也能看到,但真正调用的时候,要么静默无反应,要么报一句“没有找到对应技能”。反复看了好几遍配置&am…

2026/8/27 20:14:19

个人AI助手工程化指南:从聊天玩具到稳定工作流入口

airi酱 这个名字,第一次听很容易让人以为是一个虚拟角色或聊天机器人,但真正动手做过个人 AI 助手项目的人会明白,这类项目最难的不是让模型开口说话,而是让它稳定地、可复用地产出结果。 我见过不少类似的实践:把一个…

2026/8/27 20:14:19

数学建模竞赛:基于需求预测与优化模型的蔬菜定价补货决策

1. 项目概述:从超市货架到数学模型的挑战每次走进超市的生鲜区,看到那些码放整齐、色泽鲜亮的蔬菜,你有没有想过,这些菜的价格是怎么定出来的?为什么今天西红柿贵了五毛,明天黄瓜又打折了?货架上…

2026/8/27 20:09:18

工程化思维的工具化落地方法

工程化思维的工具化落地方法把重复劳动交给工具前,先确认重复的是规则还是表象。若每次处理依赖不同业务判断,过早自动化只会把例外隐藏得更深。 找到稳定边界 收集真实任务,标出共同输入、产物格式和失败分支。边界稳定后才沉淀为脚本、模板…

2026/8/26 9:13:28

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/27 10:58:22

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/27 7:46:21

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/27 0:01:16

Go语言构建企业级AI服务网关:统一管理英伟达等AI接口调用

1. 项目概述:从零构建一个企业级的AI服务网关 最近在帮一个做内容审核的团队做技术架构升级,他们原来的业务里,每天有几十万张图片和短视频需要过审,最初是接了几个开源的AI模型自己部署,但效果和性能一直不太稳定。后…

2026/8/27 0:01:16

LeetCode Hot100(51-60)算法精解与面试技巧

1. 题目背景与核心价值"hot100(51-60)"这个标题看起来像是某个编程题库或算法练习集中的一组题目编号。在技术社区中,类似命名通常指向LeetCode、牛客网等平台的热门题目集合。作为刷过300题的算法老手,我理解这类题目的核心价值在于&#xff…

2026/8/27 0:01:16

CRC校验实战:从模2除法到HJ212协议排错

1. 为什么一个“校验码”能扛住工业现场90%的数据 corruption? 你有没有遇到过这样的场景:嵌入式设备通过RS-485上传温湿度数据,上位机偶尔收到一帧乱码——温度显示成-273℃,湿度跳到999%,但串口波形看起来完全正常&a…

2026/8/26 19:34:06

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/26 19:17:08

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/26 19:34:05

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…