408数据结构第5章:树与二叉树②——遍历、线索树、森林与哈夫曼

这一篇重点解决408中最常见的过程题:遍历、由遍历序列还原二叉树、线索二叉树、树与森林转换、哈夫曼树和WPL。


一、四种遍历顺序

复制代码
先序:根 左 右
中序:左 根 右
后序:左 右 根
层序:从上到下、从左到右

记忆:

复制代码
先序根最先
中序根中间
后序根最后

例如:

复制代码
        A
       / \
      B   C
     / \   \
    D   E   F

得到:

复制代码
先序:A B D E C F
中序:D B E A C F
后序:D E B F C A
层序:A B C D E F

二、由遍历序列还原二叉树

1. 先序 + 中序

先序第一个元素一定是根。

在中序中找到根以后,中序被分成:

复制代码
左子树 | 根 | 右子树

然后按照左右子树结点数量,再去切先序序列,递归完成。

固定模板:

复制代码
先序找根
中序切左右
递归重建

2. 后序 + 中序

后序最后一个元素一定是根。

固定模板:

复制代码
后序找根
中序切左右
递归重建

3. 先序 + 后序

一般不能唯一确定二叉树。

原因是:如果某结点只有一个孩子,单靠先序和后序无法判断这个孩子是左孩子还是右孩子。

结论:

复制代码
先序 + 中序 -> 一般可唯一确定
后序 + 中序 -> 一般可唯一确定
先序 + 后序 -> 一般不能唯一确定

三、典型还原题

已知:

复制代码
先序:A B D E C F
中序:D B E A C F

先序第一个A是根。

在中序中:

复制代码
D B E | A | C F

所以左子树有3个结点,右子树有2个结点。

继续切先序:

复制代码
左子树先序:B D E
右子树先序:C F

左子树中,B是根:

复制代码
D | B | E

所以D是左孩子,E是右孩子。

右子树中,C是根:

复制代码
C | F

所以C无左孩子,F是右孩子。

最终:

复制代码
        A
       / \
      B   C
     / \   \
    D   E   F

四、层序遍历与队列

层序遍历必须想到队列:

复制代码
根入队
取出队头
访问该结点
左孩子入队
右孩子入队
重复

所以:

复制代码
层序遍历 -> 队列
DFS/递归遍历 -> 栈或递归

五、线索二叉树

线索二叉树的目的:

复制代码
利用原本为空的孩子指针,保存遍历序列中的前驱和后继。

n个结点的二叉链表中:

复制代码
总指针域 = 2n
真实孩子指针 = n-1
空指针 = n+1

因此可利用的原空指针一共有:

复制代码
n+1

中序线索树常考

若某结点左指针为空:

复制代码
可指向中序前驱

若右指针为空:

复制代码
可指向中序后继

注意:线索指针不是孩子指针,必须结合标志位判断。


六、树和森林转换成二叉树

核心口诀:

复制代码
左孩子,右兄弟

意思是:

复制代码
第一个孩子 -> 二叉树中的左孩子
下一个兄弟 -> 二叉树中的右孩子

例如A有三个孩子B、C、D:

复制代码
A.left = B
B.right = C
C.right = D

遍历对应关系

复制代码
树的先根遍历 = 对应二叉树的先序遍历
树的后根遍历 = 对应二叉树的中序遍历

森林也有类似对应:

复制代码
森林先序 = 对应二叉树先序
森林中序 = 对应二叉树中序

七、哈夫曼树

哈夫曼树解决的是:

复制代码
带权路径长度 WPL 最小

构造规则只记一句:

复制代码
每次从当前集合中取最小的两个权值合并。

合并出的新权值重新放回集合,继续选择最小两个。


八、WPL怎么算

WPL定义:

复制代码
WPL = Σ(叶子权值 × 根到叶子的路径长度)

路径长度通常按"边数"计算。

快速算法

构造哈夫曼树时:

复制代码
WPL = 每次合并所得新权值之和

例如权值:

复制代码
2, 3, 7, 9

合并:

复制代码
2+3=5
5+7=12
9+12=21

所以:

复制代码
WPL = 5+12+21 = 38

不必画完整哈夫曼树也能直接算。


九、哈夫曼树结点数量

若有n个初始权值,也就是n个叶子:

复制代码
叶子结点 = n
内部结点 = n-1
总结点 = 2n-1

因为哈夫曼树中不存在度为1的结点。


十、哈夫曼编码

在左右分支分别标记0和1,可以得到哈夫曼编码。

核心性质:

复制代码
哈夫曼编码是前缀编码

也就是:

复制代码
任何一个字符编码都不是另一个字符编码的前缀

所以可以唯一解码。

平均码长

若字符概率为pi,码长为li:

复制代码
平均码长 = Σ(pi * li)

若给频数wi:

复制代码
平均码长 = Σ(wi * li) / Σwi

其中:

复制代码
Σ(wi * li) = WPL

十一、典型哈夫曼计算

权值:

复制代码
5, 7, 10, 15, 20

依次合并:

复制代码
5+7=12
10+12=22
15+20=35
22+35=57

因此:

复制代码
WPL = 12+22+35+57
    = 126

有5个叶子,因此:

复制代码
内部结点 = 4
总结点 = 9

十二、考试高频题型

复制代码
给树 -> 求先中后层序遍历

给先序+中序 -> 还原树

给后序+中序 -> 还原树

问能否唯一确定 -> 看是否含中序

线索树 -> 问前驱、后继、空指针数量

树/森林转二叉树 -> 左孩子右兄弟

哈夫曼 -> 每次合并两个最小值

WPL -> 所有合并值之和

十三、高频失分点

  1. 后序最后一个才是根,不是第一个。

  2. 先序+后序一般不能唯一确定。

  3. WPL的路径长度通常按边数,不要从根结点算1。

  4. 哈夫曼每一轮都要重新从"当前集合"里选最小两个。

  5. 线索指针不是实际孩子。

  6. 树转二叉树一定记"左孩子,右兄弟"。


十四、10秒背诵版

复制代码
先根左右,中左根右,后左右根;
先中能还原,后中能还原,先后一般不唯一;
线索空指针n+1;
树转二叉树:左孩子右兄弟;
哈夫曼两小合并;
WPL等于所有合并值之和;
n个叶子,总结点2n-1。
相关推荐
Jasmine_llq2 小时前
《P15800 [GESP202603 六级] 选数》
数据结构·long long·逆序线性 dp·从后往前推导·转移严格遵循题意·防止总和溢出·复杂度on
疯狂打码的少年3 小时前
【数据结构】串(字符串):基本概念与存储
数据结构·笔记
致Great4 小时前
科研人的 AI,不该只回答问题:我用字节TraeWork 跑了一遍真实研究任务
算法
纵有疾風起4 小时前
线性表的定义与基本操作 — 从逻辑结构到 ADT 接口
数据结构·算法·408·线性表·adt
wuyk5554 小时前
1.栈:后进先出的线性数据结构
c语言·数据结构·stm32·单片机
测试_AI_一辰5 小时前
AI Agent 评测最隐蔽的坑-记忆
人工智能·算法·ai·自动化·ai编程
lucas_AI5 小时前
给YOLO检测器插 LoRA,'插对地方'比'插什么'更要命
人工智能·算法
LuminousCPP5 小时前
数据结构-时间与复杂度|时间/空间复杂度 + 两道力扣练习 + 二分查找复盘
c语言·数据结构·经验分享·算法·leetcode
Nil2085 小时前
leetcode 三数之和
数据结构·算法·leetcode