前言:最近在给我的小程序(数据结构算法演示)增加题库时,做了很多考研真题,所以在这里给大家总结下做题的思路和考点
题型1:哈夫曼树性质
- 结点度数为0或者2
- 一定是二叉树
- n0=n2+1
- n1=0
- n=n0+n1+n2
- n2有可能为0,即一个结点的特殊情况
- 父结点权值等于两个子结点权值之和
- 权值非负
- 结点N的子树任意结点的权值都小于N的权值
- 其他
- 深度高的结点的权值一定不大于深度低的结点的权值:即N1(h1)和N2(h2),若h1>h2,那么N1<=N2(这个可通过反证法+构造哈夫曼树过程推断出)
(简单
)考察结点数、度数相关
n个具有权值的叶子结点构造的霍夫曼树包含的结点总数是()
A. n-1
B. n+1
C. 2n-1
D. 2n+1
答案:C. 直接记住上面性质可得答案
2019年408单选题
对n个互不相同的符号进行哈夫曼编码。若生成的哈夫曼树共有115个结点,则n的值是()
A. 56
B. 57
C. 58
D. 69
答案:C. 直接记住n0=n2+1,n1=0,这里n就是n0,可得答案
华东师范大学单选题
下列哪个数不可能是某棵哈夫曼树的结点个数?
A. 803
B. 308
C. 83
D. 以上选项都不对
答案:B n=n0+n2=2n2+1
关于结点数和度数的解题思路
- 需要把问题抽象成
n0、n1、n2
- 直接套用性质即可:
n0=n2+n1,n1=0
(简单
)考察树形态的知识点
2010年408单选题
对n(n≥2)个权值均不相同的字符构成哈夫曼树,关于该树的叙述中,错误的是()
A. 该树一定是一颗完全二叉树
B. 树中一定没有度为1的结点
C. 树中两个权值最小的结点一定是兄弟结点
D. 树中任一非叶结点的权值一定不小于下一层任一结点的权值
答案:A. A显然错误,BCD也可以通过上面总结的性质得到正确与否
下列有关霍夫曼树(huffman)的说法,其中正确的是()
A. 霍夫曼树一定是一颗完全二叉树
B. 霍夫曼树与二叉排序树是同义词
C. 霍夫曼树结点的度数只可能是0或者2
D. 霍夫曼树结点的度数有可能为0、1、2
答案:C. 显而易见
题型2:计算WPL
知识点参考这个juejin.cn/post/709831… 推荐选择方案3和方案2
(简单
)给出哈夫曼树直接计算WPL
计算下图哈夫曼树的带权路径长度长度()
答案:37+52+16+21+22+30+10+12=200 已经给出了哈夫曼树,直接用方法二计算即可
(中等
)给出叶结点权值直接计算WPL
2021年408单选题
若某二叉树有5个叶子结点,其权值分别为10,12,16,21,30。则其最小的带权路径长度(WPL)是()
A. 89
B. 200
C. 208
D. 209
答案:B. 使用方案2或者方案3即可计算WPL
(中等
)给出编码的权重,计算编码平均长度
重庆大学单选题
Huffman编码树中所有结点(含叶结点)的权重分别为:
0.05,0.15,0.18,0.2,0.26,0.36,0.38,0.62,1.0。则该Huffman编码平均编码长度是()
A. 2.2
B. 2.8
C. 3.4
D. 3.6
答案:A. 因为每个叶结点哈夫曼编码的长度=路径长度,所以这里的平均编码长度就相当于WPL。
因此采用方法二或者方法三计算WPL即可
(困难
)求WPL值的算法题
2014年408算法题
二叉树的带权路径长度(WPL)是二叉树中所有叶结点的带权路径长度之和。给定一棵二叉树T,
采用二叉链表存储,结点结构为:(left,weight,right)。
其中叶结点的weight域保存该结点的非负权值。
设root为指向T的根结点的指针,请设计求T的WPL的算法
答案思路:遍历哈夫曼树(用自己最熟悉的遍历方法),计算所有非根结点的权值之和即可
下面我也给出方法1的计算WPL的代码,可以发现写起来很复杂,且必须要按层遍历来做
/**
*
* @param root
* @param maxSize 队列最大值
* @return 按层遍历计算WPL
*/
int getTreeWpl(struct TreeNode *root, int maxSize) {
if (root == NULL) {
return 0;
}
// 动态数组做队列
struct TreeNode **queue = (struct TreeNode **) malloc(sizeof(struct TreeNode *) * maxSize);
int rear = 0, front = 0;
// 根结点入队
queue[rear++] = root;
// 当前层的size
int currentSize = 1;
// 下一层的size
int nextSize = 0;
int level = 0;
struct TreeNode *temp;
int wpl = 0;
while (rear > front) {
// 出队
temp = queue[front++];
currentSize--;
if (temp->left == NULL && temp->right == NULL) {
wpl += (temp->data * level);
}
if (temp->left) {
queue[rear++] = temp->left;
nextSize++;
}
if (temp->right) {
queue[rear++] = temp->right;
nextSize++;
}
if (currentSize == 0) {
// 说明这一层已经遍历完
currentSize = nextSize;
nextSize = 0;
level++;
}
}
return wpl;
}
困难算法题:给定叶结点权值数组,求WPL值
方案1:用递归的方式计算WPL
方案2:先构造一个哈夫曼树,然后遍历哈夫曼树计算WPL(太麻烦、不推荐)
题型3:哈夫曼树构造
- 每次都选最小权值的两个结点向上合成一个新结点
- 贪心
- n个叶结点的哈夫曼树:要进行n-1次合并操作
- 每次最小权值的两个结点只需要是兄弟就行,没有要求顺序
- 哈夫曼树不唯一
- n个叶结点的哈夫曼树:有2^(n-1)种形态的哈夫曼树
(简单
)构造过程的概念题
只要记住怎么构造哈夫曼树、基本就没问题
构造霍夫曼树依据的基本思路是
A. 回溯算法
B. 贪心算法
C. 分治算法
D. 递归算法
答案:B
我自己编的题
以1,2,3对应叶结点的权值构造的哈夫曼树有多少种形态?
答案:一共4种:2^2=4
(简单
)给叶结点权值,手画哈夫曼树
分别以 6,3,8,12,5,7 对应叶结点的权值构造的哈夫曼树的深度为()
A. 6
B. 5
C. 4
D. 3
答案:C
这题有没有什么简单办法:是不是可以通过结点数推断深度呢?
很显然是不行,因为权值不一样树的形态不确定,所以直接画树即可
(困难
)考察构造过程中关键点:每次都是选择最小的两个结点合成父结点
需要灵活应变,记住每次都选两个最小权值结点构造二叉树这条原则
2012年408应用题
设有 6 个有序表 A、B、C、D、E、F,分别含有10、35、40、50、60和200个数据元素,各表中元素按升序排列。
要求通过5次两两合并,将6个表最终合并成1个升序表,并在最坏情况下比较的总次数达到最小
1. 给出完整的合并过程,并求出最坏情况下比较的总次数。
2. 根据你的合并过程,描述 N(N≥2)个不等长升序表的合并策略,并说明理由。
答案:总比较次数为:44+84+109+194+394=825
这题看起来和哈夫曼树无关,但是简单思考下每次两两合并的最坏情况的次数是两个个数相加,
这就和哈夫曼树构造很类似,而且一个数越早参与到合并,对最后的总次数影响就越大;因此这就是哈夫曼树构造过程
2015年408选择题
下列选项给出的是从根分别到达两个叶结点路径上的权值序列,能属于同一棵哈夫曼树的是()
A. 24,10,5 和 24,10,7
B. 24,10,5 和 24,12,7
C. 24,10,10 和 24,14,11
D. 24,10,5 和 24,14,6
答案:D 排除法来做,记住每次都是最小的权值的连个结点合成新结点
第一眼看上去什么24,10,5这都是啥跟啥啊,看题意这是路径上结点的权值,所以需要手画以下才能明白,
比如A:第一个结点24肯定只能是根结点,
第二个结点是10,所以24的子结点只能是10和14,所以10的子结点是5和7
5+7!=10,所以不对
题型4:哈夫曼编码
- 哈夫曼编码是前缀码
- 任何一个字符的编码都不能是其他字符编码的前缀
- 解决二义性
- 哈夫曼编码是平均长度最短的编码方式
- 存储空间代价最小的编码方式
- 定理:在变长编码中,如果码字长度严格按照对应符号出现的概率大小逆序排列,则其平均码字长度为最小
- 叶结点编码长度=叶结点路径长度
- 哈夫曼编码过程
- 构造哈夫曼树
- 左0右1
(简单
)直接考察编码应用
2017年408选择题
已知字符集{a,b,c,d,e,f,g,h},若各字符的哈夫曼编码依次是
0100,10, 0000, 0101,001, 011,11,0001,
则编码序列 0101001001001011110101 的译码结果是()
A. a c g a b f h
B. a d b a g b b
C. a f b e a g d
D. a f e e f g d
答案:D 哈弗曼编码唯一性,所以直接匹配就行
2018年408选择题
已知字符集{a,b,c,d,e,f,g,h},若个字符出现的次数分别为6,3,8,2,10,4,
则对应字符集中各字符的哈弗曼编码可能是()
A. 00,1011,01,1010,11,100
B. 00,100,110,000,0010,01
C. 10,1011,11,0011,00,010
D. 0011,10,11,0010,01,000
答案:A.
我们要把问题抽象下,既然是哈夫曼编码,肯定要代价小,也就是说次数越少长度越短,也就是次数等于权重,所以画出哈夫曼树我们便知道字符集的编码是哪些了
所以解题步骤还是:画哈夫曼树+编码
(简单
)考察前缀码
2014年408单选题
5个字符有如下4种编码方案,不是前缀编码的是()
A. 01,0000,0001,001,1
B. 011,000,001,010,1,
C. 000,001,010,011,100
D. 0,100,110,1110,1100
答案:D 理解前缀码概念的送分题
(中等
)哈夫曼编码和哈夫曼树性质、构造结合的应用
关于编码只需要记住左0右1、前缀码,加上其他哈夫曼知识万物皆可解决哈
南京航空航天大学单选题
根据使用频率为5个字符设计的哈夫曼编码不可能是()
A. 000,001,010,011,1
B. 0000,0001,001,01,1
C. 000,001,01,10,11
D. 00,100,101,110,111
答案:D
1. 如果不是前缀码肯定不是哈夫曼
2. 左0右1画出对应哈夫曼树,判断是否满足哈夫曼树性质
D对应的哈夫曼树,有度数为1的结点,所以肯定不是哈夫曼编码
对于一个字符集中具有不同权值的字符进行Huffman编码时,
如果已知某个字符的Huffman编码为 0101,对于其他字符的Huffman编码;请分析说明
1. 具有哪些特征的编码是不可能的
2. 具有哪些特征的编码是一定会有的
答案:
1. 0,01,010和以0101为前缀的编码
2. 以1,00,011,0100为前缀的编码
这题比较巧妙,只给了一个字符的编码,所以还是按照左0右1的原则画哈夫曼树,同时根据哈夫曼树构造过程的要求补齐其他确定的结点,如下图,然后记住一点编码一定是叶结点就行