数据结构( 二叉树)
⚙️第一部分Makefile 基本操作详解1.1 什么是 MakefileMakefile 是一个自动化构建工具make的配置文件。它描述了项目中各个源文件之间的依赖关系以及如何编译和链接生成最终的可执行文件。在大中型 C/C 项目中手动输入gcc main.c func.c -o app不仅繁琐而且每次修改一个文件就要重新编译所有文件效率低下。Makefile 能够只重新编译被修改过的文件从而大幅节省构建时间。1.2 Makefile 的核心规则Makefile 由一条条规则组成每条规则的基本格式为目标(target): 依赖(prerequisites) [Tab] 命令(recipe)目标 (target)要生成的文件名通常是一个可执行文件或一个.o文件。依赖 (prerequisites)生成目标所需要的源文件或其他目标。命令 (recipe)实际执行的编译指令必须以一个 Tab 键开头不能用空格。当make执行时它会比较目标文件和依赖文件的修改时间。如果依赖比目标新或者目标不存在则执行命令重新生成目标。1.3 一个简单的 Makefile 示例假设项目包含main.c、queue.c、queue.h最终的 Makefile 可以这样写# 定义变量习惯上使用大写 CC gcc CFLAGS -Wall -g TARGET app OBJS main.o queue.o 链接目标将所有 .o 文件链接成可执行文件 $(TARGET): $(OBJS) $(CC) $(CFLAGS) $^ -o $ 编译规则每个 .c 文件单独编译成 .o 文件 main.o: main.c queue.h $(CC) $(CFLAGS) -c main.c -o main.o queue.o: queue.c queue.h $(CC) $(CFLAGS) -c queue.c -o queue.o 清理目标 clean: rm -f $(OBJS) $(TARGET)变量说明CC指定 C 编译器。CFLAGS编译选项。-Wall显示所有警告-g生成调试信息。$自动化变量代表目标文件。$^自动化变量代表所有依赖文件。$自动化变量代表第一个依赖文件。1.4 使用通配符简化 Makefile当源文件很多时可以使用通配符和模式规则来简化书写CC gcc CFLAGS -Wall -g TARGET app SRCS $(wildcard *.c) # 查找当前目录下所有 .c 文件 OBJS $(SRCS:.c.o) # 将 .c 替换为 .o $(TARGET): $(OBJS) $(CC) $(CFLAGS) $^ -o $ 模式规则将所有 .c 文件编译成对应的 .o 文件 %.o: %.c $(CC) $(CFLAGS) -c $ -o $ clean: rm -f $(OBJS) $(TARGET)关键点解析wildcard函数用于获取匹配的文件列表。$(SRCS:.c.o)是一种替换引用将列表中所有.c后缀替换为.o。%.o: %.c是一条模式规则表示任意一个.o文件都依赖于同名的.c文件。这样就不需要为每个文件单独写规则了。1.5 Makefile 中的常用命令与注意事项make默认执行第一个目标通常为all或直接是最终目标。make clean执行clean目标清理编译产物。.PHONY声明伪目标确保即使当前目录存在名为clean的文件make clean依然会执行命令。命令前加可以静默执行不显示命令本身如echo Building...。核心价值掌握 Makefile 意味着你能够高效地管理任何规模的 C/C 项目理解 IDE 底层构建原理并具备独立排查编译链接错误的能力。第二部分二叉树与遍历2.1 二叉树的基本概念二叉树是一种树形结构每个节点最多有两个子节点左孩子left child和右孩子right child。二叉树是计算机科学中最重要的数据结构之一广泛应用于表达式解析、搜索算法二叉搜索树、堆、哈夫曼编码等场景。根节点root树的最顶层节点没有父节点。叶子节点leaf没有子节点的节点。深度depth从根节点到某个节点的路径长度根节点深度通常为 0。高度height从该节点到最远叶子节点的最长路径上的边数。2.2 二叉树的存储结构通常采用链式存储每个节点包含数据域、左孩子指针、右孩子指针typedef struct TreeNode { int data; // 数据域 struct TreeNode *left; // 左孩子指针 struct TreeNode *right; // 右孩子指针 } TreeNode;2.3 创建二叉树节点TreeNode* createNode(int data)创建单个节点分配内存并初始化。TreeNode* createNode(int data) { TreeNode *node (TreeNode*)malloc(sizeof(TreeNode)); if (node NULL) { // 内存不足 printf(内存分配失败\n); exit(1); } node-data data; // 赋值数据 node-left node-right NULL; // 左右孩子初始为空 return node; }2.4 手动构建一棵示例二叉树为方便测试我们手动构建如下结构/* 1 / \ 2 3 / \ \ 4 5 6 */TreeNode* buildSampleTree() { TreeNode *root createNode(1); root-left createNode(2); root-right createNode(3); root-left-left createNode(4); root-left-right createNode(5); root-right-right createNode(6); return root; }2.5 二叉树的遍历方式遍历是指按照某种顺序访问树中的每一个节点。主要分为两大类深度优先遍历DFS沿着树的深度遍历分为先序、中序、后序。广度优先遍历BFS逐层遍历即层序遍历。2.5.1 先序遍历Pre-order顺序根 → 左子树 → 右子树对于示例树输出应为1 2 4 5 3 6void preOrder(TreeNode *root) { if (root NULL) return; // 递归出口空树 printf(%d , root-data); // 1. 访问根节点 preOrder(root-left); // 2. 递归遍历左子树 preOrder(root-right); // 3. 递归遍历右子树 }2.5.2 中序遍历In-order顺序左子树 → 根 → 右子树对于示例树输出应为4 2 5 1 3 6。若用于二叉搜索树中序遍历会得到有序序列。void inOrder(TreeNode *root) { if (root NULL) return; inOrder(root-left); // 1. 遍历左子树 printf(%d , root-data); // 2. 访问根节点 inOrder(root-right); // 3. 遍历右子树 }2.5.3 后序遍历Post-order顺序左子树 → 右子树 → 根对于示例树输出应为4 5 2 6 3 1。常用于释放树的内存先删子节点再删父节点。void postOrder(TreeNode *root) { if (root NULL) return; postOrder(root-left); // 1. 遍历左子树 postOrder(root-right); // 2. 遍历右子树 printf(%d , root-data); // 3. 访问根节点 }2.5.4 层序遍历Level-order—— BFS逐层从上到下、从左到右访问。对于示例树输出应为1 2 3 4 5 6。层序遍历需要借助队列来实现void levelOrder(TreeNode *root) { if (root NULL) return; // 使用链式队列此处需引入之前实现的 LinkQueue或直接用循环数组模拟 LinkQueue q; initLinkQueue(q); enLinkQueue(q, root); // 根节点入队 while (!isEmptyLink(amp;q)) { TreeNode *cur NULL; deLinkQueue(amp;q, amp;cur); // 出队一个节点 printf(%d , cur-gt;data); // 访问该节点 if (cur-gt;left) // 左孩子不空则入队 enLinkQueue(amp;q, cur-gt;left); if (cur-gt;right) // 右孩子不空则入队 enLinkQueue(amp;q, cur-gt;right); } printf(\n); }注意上述LinkQueue需要将数据类型改为TreeNode*。实际工程中通常使用独立的队列实现或使用 C STL 的queue。2.6 释放二叉树的内存必须使用后序遍历的方式释放确保先释放子节点再释放父节点否则会产生内存泄漏或野指针。void freeTree(TreeNode *root) { if (root NULL) return; freeTree(root-left); // 先释放左子树 freeTree(root-right); // 再释放右子树 free(root); // 最后释放根节点 }2.7 完整测试示例int main() { TreeNode *root buildSampleTree(); printf(先序遍历: ); preOrder(root); printf(\n); printf(中序遍历: ); inOrder(root); printf(\n); printf(后序遍历: ); postOrder(root); printf(\n); printf(层序遍历: ); levelOrder(root); freeTree(root); return 0; }总结二叉树是递归定义的完美体现。四种遍历方式覆盖了绝大多数应用场景先序可用于拷贝树中序可获得有序序列BST后序用于安全释放内存层序用于按层处理如图像渲染。掌握它们就掌握了树形结构的基础。

相关新闻

linux根文件系统是如何加载的

linux根文件系统是如何加载的

问题:内核在磁盘文件系统中,要加载内核,就必须先加载文件系统。但根文件系统又是被内核负责加载的,它是内核的启动参数,没有它,内核是无法启动的。到底先有鸡,还是先有蛋?机器是如何…

2026/10/27 11:58:07 阅读更多 →
Manus上下文工程:大模型能力释放的创新实践

Manus上下文工程:大模型能力释放的创新实践

1. Manus与上下文工程的创新结合Manus作为新一代AI工程平台,其核心突破在于将传统的大模型能力释放问题转化为可量化、可复制的上下文工程体系。这种思路转变直接解决了当前大模型应用中的三个关键痛点:响应不可控、知识碎片化和任务连贯性差。我在实际企…

2026/10/28 10:47:23 阅读更多 →
深度学习新手入门:从零搭建PyTorch环境到MNIST手写数字识别实战

深度学习新手入门:从零搭建PyTorch环境到MNIST手写数字识别实战

在实际项目中,很多开发者对深度学习抱有浓厚兴趣,但面对复杂的理论、庞大的框架和繁琐的环境配置,常常感到无从下手,最终停留在“Hello World”阶段。本文旨在为希望快速上手并完成第一个深度学习项目的初学者,提供一条…

2026/10/25 8:59:34 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/10/27 17:33:32 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/10/28 7:28:00 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/28 9:02:11 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/10/27 18:20:50 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/10/28 9:00:54 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/10/28 7:29:02 阅读更多 →

日新闻

周新闻

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/27 13:55:19 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/28 9:01:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/27 19:19:37 阅读更多 →