数据结构(5)二叉树的存储、创建与四种遍历算法
一、二叉树的基本概念二叉树Binary Tree是每个节点最多拥有两棵子树的树结构通常子树被称作左子树和右子树。1.1 二叉树的递归定义二叉树是 nn≥0个节点的有限集合该集合或者为空集空二叉树或者由一个根节点和两棵互不相交的、分别称为左子树和右子树的二叉树组成。1.2 二叉树的性质第 i 层最多有 2^(i-1) 个节点深度为 k 的二叉树最多有 2^k - 1 个节点叶子节点数 n₀ 度为2的节点数 n₂ 1。1.3 二叉树的存储本文采用链式存储每个节点包含一个数据域和两个指针域分别指向左孩子和右孩子。二、二叉树的节点定义btree.h#ifndef _BTREE_H_ #define _BTREE_H_ typedef int data_t; typedef struct btnode { data_t data; // 数据域 struct btnode *pl; // 指向左子树 struct btnode *pr; // 指向右子树 } btree_t; // 二叉树节点类型 #endif三、由前序和中序序列手动还原二叉树已知一棵二叉树的先序序列为A B D F C E G H中序序列为B F D A G E H C手动还原这棵二叉树。3.1 还原过程基本原理前序遍历根→ 左 → 右第一个元素是根中序遍历左 →根→ 右根的左边是左子树右边是右子树Step 1确定整棵树的根前序序列第一个元素是A所以A 是根。Step 2在中序序列中划分左右子树中序序列B F D A G E H C以A为分界A 的左边B F D→ A 的左子树A 的右边G E H C→ A 的右子树Step 3递归还原左子树B F D左子树节点集合为 {B, F, D}对应前序序列为B D F前序中紧跟 A 之后的 3 个属于左子树的元素。前序中B排第一 →B 是左子树的根在中序B F D中B 左边为空 → B 没有左子树B 右边F D→ B 的右子树继续分析F DB 的右子树对应前序D F前序中D排第一 →D 是根在中序F D中D 左边F→ D 的左子树D 右边为空 → D 没有右子树F是叶子节点Step 4递归还原右子树G E H C右子树节点集合为 {G, E, H, C}对应前序序列为C E G H。前序中C排第一 →C 是右子树的根在中序G E H C中C 左边G E H→ C 的左子树C 右边为空 → C 没有右子树继续分析G E HC 的左子树对应前序E G H前序中E排第一 →E 是根在中序G E H中E 左边G→ E 的左子树E 右边H→ E 的右子树G和H都是叶子节点3.2 还原结果最终得到的二叉树结构如下A / B \ D / F C / E / \ G H也可以画得更完整A / \ B C \ / D E / / \ F G H3.3 后序遍历验证后序遍历左 → 右 → 根F D B G H E C A先遍历左子树F → D → B再遍历右子树G → H → E → C最后根A合并F D B G H E C A✓3.4 后序线索树后序遍历序列F → D → B → G → H → E → C → A在后序遍历序列中每个节点的前驱序列中前一个和后继序列中后一个如下节点前驱pre后继postF无第一个DDFBBDGGBHHGEEHCCEAAC无最后一个后序线索树中利用空指针域存放遍历序列中的前驱/后继信息左指针指前驱右指针指后继其中首节点 F 的前驱线索和末节点 A 的后继线索为空。3.5 将二叉树转换为对应的树或森林转换规则二叉树转树/森林的核心是左孩子右兄弟表示法的逆过程——节点的左孩子转为树中的第一个孩子节点的右兄弟转为树中的下一个兄弟。转换过程1.从根节点 A 开始A 的左孩子 B 变成 A 的第一个孩子A 的右孩子 C 变成 A 的下一个兄弟——但 A 是根无兄弟所以 C 作为 A 的另一个孩子即 B 的右兄弟 → A 的第二个孩子2.但更准确地说A 的左子树和右子树分别构成两棵树形成森林第一棵树根为 AA 的左孩子 B 是 A 的第一个孩子D 是 B 的孩子F 是 D 的孩子第二棵树根为 CE 是 C 的孩子G 和 H 是 E 的孩子森林的树形表示 第一棵树 第二棵树 A C | | B E | / \ D G H | F四、二叉树的创建代码实现扩展先序序列采用扩展先序序列递归创建二叉树。遇到空节点时用#标记。例如序列ABDG##H###CE#I##F##对应的二叉树结构如下A / \ B C / / \ D E F / \ \ G H I核心代码#include stdio.h #include stdlib.h #include btree.h char tree_seq[] ABDG##H###CE#I##F##; int idx 0; // 当前读取位置 btree_t *create_btree(void) { char data tree_seq[idx]; if (data #) { return NULL; // # 表示空节点结束 } btree_t *new malloc(sizeof(btree_t)); if (new NULL) { printf(malloc fail!\n); return NULL; } new-data data; new-pl create_btree(); // 递归创建左子树 new-pr create_btree(); // 递归创建右子树 return new; }思路解析1.从序列中读取一个字符2.如果是#返回NULL表示该子树为空3.否则创建新节点填入数据然后递归创建左子树和右子树4.全局变量idx记录当前读取到序列的第几个字符。五、二叉树的四种遍历方式5.1 前序遍历Pre-Order根 → 左 → 右int pre_order_traverse(btree_t *t) { if (t NULL) return 0; printf(%c , t-data); // 根 pre_order_traverse(t-pl); // 左子树 pre_order_traverse(t-pr); // 右子树 return 0; }输出A B D G H C E I F5.2 中序遍历In-Order左 → 根 → 右int in_order_traverse(btree_t *t) { if (t NULL) return 0; in_order_traverse(t-pl); // 左子树 printf(%c , t-data); // 根 in_order_traverse(t-pr); // 右子树 return 0; }输出G D H B A E I C F5.3 后序遍历Post-Order左 → 右 → 根int post_order_traverse(btree_t *t) { if (t NULL) return 0; post_order_traverse(t-pl); // 左子树 post_order_traverse(t-pr); // 右子树 printf(%c , t-data); // 根 return 0; }输出G H D B I E F C A5.4 三种递归遍历的对比总结遍历方式访问顺序特点前序遍历根 → 左 → 右适合复制/序列化树结构中序遍历左 → 根 → 右对二叉搜索树结果为有序序列后序遍历左 → 右 → 根适合释放内存/计算树的大小递归遍历的共同模式终止条件t NULL时返回递归结构三个函数的代码结构完全相同只是printf语句的位置不同。5.5 层序遍历Level-Order逐层从左到右层序遍历需要借助队列来实现属于广度优先搜索BFS的思想。#include linkqueue.h int layer_order_traverse(btree_t *t) { if (t NULL) return -1; // 步骤1创建队列根节点入队 node_t *pq linkqueue_create(); enqueue(pq, t); // 步骤2循环出队、打印、子节点入队 while (is_empty(pq) ! 1) { btree_t *data NULL; dequeue(pq, data); printf(%c , data-data); if (data-pl ! NULL) enqueue(pq, data-pl); // 左孩子入队 if (data-pr ! NULL) enqueue(pq, data-pr); // 右孩子入队 } // 步骤3销毁队列 linkqueue_destroy(pq); return 0; }输出A B C D E F G H I为什么层序遍历需要队列队列的 FIFO 特性保证了同一层的节点先被访问其子节点后被访问从而实现逐层遍历。六、二叉树的销毁释放二叉树内存需要采用后序遍历的顺序左 → 右 → 根必须先释放子节点再释放父节点否则会丢失子节点的引用野指针。int btree_destroy(btree_t *t) { if (t NULL) return -1; btree_destroy(t-pl); // 递归销毁左子树 btree_destroy(t-pr); // 递归销毁右子树 free(t); // 释放根节点 return 0; }七、主函数与完整运行结果int main(int argc, const char *argv[]) { btree_t *root create_btree(); printf(前序遍历: ); pre_order_traverse(root); putchar(\n); printf(中序遍历: ); in_order_traverse(root); putchar(\n); printf(后序遍历: ); post_order_traverse(root); putchar(\n); printf(层序遍历: ); layer_order_traverse(root); putchar(\n); // btree_destroy(root); // 释放二叉树 return 0; }运行结果text前序遍历: A B D G H C E I F 中序遍历: G D H B A E I C F 后序遍历: G H D B I E F C A 层序遍历: A B C D E F G H I八、总结遍历方式实现方式核心数据结构时间复杂度空间复杂度前序遍历递归系统调用栈O(n)O(h)h为树高中序遍历递归系统调用栈O(n)O(h)后序遍历递归系统调用栈O(n)O(h)层序遍历迭代队列链表实现O(n)O(w)w为最大层宽学习要点回顾1.链式队列的核心入队 尾插出队 头删两者配合保证 FIFO2.二叉树是递归结构遍历算法天然适合递归实现3.前/中/后序遍历的区别仅在于printf的位置4.已知前序 中序序列可以唯一还原二叉树前序定根中序分左右子树5.层序遍历是唯一的非递归遍历需要队列辅助6.销毁二叉树必须使用后序顺序避免野指针7.二叉树可以通过左孩子右兄弟的逆规则转换为树或森林。

相关新闻

显卡健康检测利器:memtest_vulkan显存稳定性测试全攻略

显卡健康检测利器:memtest_vulkan显存稳定性测试全攻略

显卡健康检测利器:memtest_vulkan显存稳定性测试全攻略 【免费下载链接】memtest_vulkan Vulkan compute tool for testing video memory stability 项目地址: https://gitcode.com/gh_mirrors/me/memtest_vulkan 在数字时代,显卡已成为计算机系统…

2026/10/17 14:54:10 阅读更多 →
CPPM报名需要什么资料?在职采购人员准备指南

CPPM报名需要什么资料?在职采购人员准备指南

很多采购人员已经具备多年工作经验,却因为不清楚报名资料、审核流程和时间安排,迟迟没有开始准备。实际上,提前把个人信息和工作经历整理清楚,可以减少报名阶段反复补充材料的情况。一、CPPM报名通常需要哪些资料不同批次的具体要…

2026/10/17 14:54:14 阅读更多 →
5分钟免费iOS激活锁绕过指南:Applera1n解锁iPhone 6s-X完整方案

5分钟免费iOS激活锁绕过指南:Applera1n解锁iPhone 6s-X完整方案

5分钟免费iOS激活锁绕过指南:Applera1n解锁iPhone 6s-X完整方案 【免费下载链接】applera1n icloud bypass for ios 15-16 项目地址: https://gitcode.com/gh_mirrors/ap/applera1n Applera1n是一款专为iOS 15-16系统设计的免费激活锁绕过工具,专…

2026/10/17 13:45:55 阅读更多 →

最新新闻

公钥密码学与伪随机数:密钥生成中的随机源与熵池管理

公钥密码学与伪随机数:密钥生成中的随机源与熵池管理

1. 从一个看似矛盾的问题说起公钥密码学里有一个特别反直觉的事实:你用来加密的密钥是公开的,任何人都能拿到,但别人依然解不开你的密文。这件事第一次接触会觉得像魔术,但支撑它的数学基础其实相当朴素——单向函数。正向计算容易…

2026/10/18 0:48:30 阅读更多 →
信息安全意识PPT设计:从知道到做到的行为转化工具包

信息安全意识PPT设计:从知道到做到的行为转化工具包

简介:本资源是一份面向全民网络安全素养提升的国家网络安全宣传周主题PPT课件,适用于企事业单位安全培训、高校通识教育及社区科普宣讲等场景。内容紧扣信息泄露风险防范与网络安全意识培养,系统梳理了网络安全四大核心特征(机密性…

2026/10/18 0:48:30 阅读更多 →
Hy3-oQ2模型卡深度解读:什么是oQ校准量化,2.7 bits/weight意味着什么

Hy3-oQ2模型卡深度解读:什么是oQ校准量化,2.7 bits/weight意味着什么

【免费下载链接】Hy3-oQ2 项目地址: https://ai.gitcode.com/hf_mirrors/mlx-community/Hy3-oQ2 点击查看 免费下载 Hy3-oQ2 是腾讯混元 Hy3(295B MoE)大模型的 MLX oQ 校准量化版本:以 2.7 bits/weight 的有效精度,把…

2026/10/18 0:48:30 阅读更多 →
LayoutLM v3深度解析:多模态文档智能模型微调实战

LayoutLM v3深度解析:多模态文档智能模型微调实战

每次看到开源社区放出的文档智能模型有实质更新,我都要停下来仔细研究一番,LayoutLM系列就是这中间绕不开的名字。这个系列从最初把文本、布局、图像三种模态塞进同一个预训练框架开始,一步步变成了表格解析、票据识别、合同信息抽取这些场景…

2026/10/18 0:46:29 阅读更多 →
Event2Mind:让机器从事件文本中推理意图与反应

Event2Mind:让机器从事件文本中推理意图与反应

每次读到关于事件理解的研究,我都会习惯性地先想一个问题:机器读一句话,真的“读懂了”吗?拿“这个人被公司开除了”来说,字面上是一个解雇事件,但稍微有点常识的人都会接着想:他慌不慌&#xf…

2026/10/18 0:46:29 阅读更多 →
向量与矩阵范数详解:从L1/L2到谱范数的机器学习应用指南

向量与矩阵范数详解:从L1/L2到谱范数的机器学习应用指南

1. 为什么我们要关心“范数”这个数学工具第一次接触“范数”这个词,很多人会觉得它离实际开发很远,像是数学系课本里才会出现的抽象概念。但如果你做过机器学习、数值计算、信号处理,甚至只是用过正则化去调一个过拟合的模型,那你…

2026/10/18 0:46:29 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 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/16 21:54:38 阅读更多 →
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/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练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/16 14:23:36 阅读更多 →