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。
相关推荐
Logic1013 小时前
C语言/数据结构组合数学题解:数字好排列计数——质数倍数分类与阶乘取模
c语言·数据结构·算法·组合数学·时间复杂度·排列·取模运算
碧海银沙音频科技研究院3 小时前
炬芯ATS3089智能手表烧录方法
人工智能·驱动开发·嵌入式硬件·算法
维克兜率天4 小时前
【维克】统计套利:寻找市场的“定价误差“
人工智能·python·算法
aqiu1111114 小时前
【C++算法打怪专栏】LeetCode 1. 两数之和(哈希表解法总结)
c++·算法·leetcode
楚识科技4 小时前
票据 OCR 识别技术深度解析:从算法原理到企业级落地实现
算法·ocr
longlongzihan4 小时前
LeetCode 25. K 个一组翻转链表 (迭代+分组反转法)
算法·leetcode·链表
xuxigifxfh4 小时前
牛客:BISHI8 大整数哈希
java·算法·哈希算法
涉密IT资质笔记4 小时前
涉密资质投入产出分析模型:时间成本、四块成本构成与 ROI 决策框架
java·开发语言·算法
木井巳4 小时前
【BFS 解决拓扑排序】火星词典
java·算法·leetcode·广度优先·宽度优先·图搜索算法
北风toto4 小时前
KMP 算法详解:从暴力匹配到 O(n+m) 的字符串搜索
java·开发语言·算法