判断题:
1-1对N(≥2)个权值均不相同的字符构造哈夫曼树,则树中任一非叶结点的权值一定不小于下一层任一结点的权值。 (T)
解析:考察哈弗曼树的构造方法,哈弗曼树的构造思想就是贪心的思想,每次选择权值最小的两个节点来形成新的节点,自底向上建树,因此对于一棵哈弗曼树来说,树中任一非叶节点的权值一定不小于下一层的任意节点的权值。
单选题:
2-1对N(N≥2)个权值均不相同的字符构造哈夫曼树。下列关于该哈夫曼树的叙述中,错误的是: (2分)
- 树中一定没有度为1的结点
- 树中两个权值最小的结点一定是兄弟结点
- 树中任一非叶结点的权值一定不小于下一层任一结点的权值
- 该树一定是一棵完全二叉树
解析:因为哈弗曼树的构造每一次选择两个权值最小的节点因此,整个哈弗曼树的节点的度要么为0要么为2,不存在度为1的节点。
因此我们第一次的选取就是将权值最小的两个节点来形成哈弗曼树的第一个新节点,因此树中两个权值最小的结点一定是兄弟结点。
根据1-1的分析我们可以知道第三个是正确的。
不难看出哈弗曼树不一定符合完全而二叉树的定义。
2-2设一段文本中包含字符{a, b, c, d, e},其出现频率相应为{3, 2, 5, 1, 1}。则经过哈夫曼编码后,文本所占字节数为: (2分)
- 40
- 36
- 25
- 12
解析:考察哈弗曼树的构造与WPL(带权路径长度)的求法。
应该是10个字符的文本平均占用的字节数。
2-3设一段文本中包含4个对象{a,b,c,d},其出现次数相应为{4,2,5,1},则该段文本的哈夫曼编码比采用等长方式的编码节省了多少位数? (2分)
- 0
- 2
- 4
- 5
解析:等长编码也就是说abcd四个字符用两位二进制数表示(00,01,10,11),采用哈弗曼编码计算WPL为24,比等长编码少了2。
2-4由分别带权为9、2、5、7的四个叶子结点构成一棵哈夫曼树,该树的带权路径长度为: (2分)
- 23
- 37
- 44
- 46
解析:考察哈弗曼树的建立与WPL的求法。
2-5已知字符集{ a, b, c, d, e, f, g, h }。若各字符的哈夫曼编码依次是 0100, 10, 0000, 0101, 001, 011, 11, 0001,则编码序列 0100011001001011110101 的译码结果是:(2分)
- acgabfh
- adbagbb
- afbeagd
- afeefgd
解析:因为哈夫曼编码使得两两之间不会互为前缀码,因此可以唯一确定序列。
2-6若以{4,5,6,3,8}作为叶子节点的权值构造哈夫曼树,则带权路径长度是()。 (2分)
- 28
- 68
- 55
- 59
解析:同上。
2-7下列叙述错误的是()。 (2分)
- 一棵哈夫曼树的带权路径长度等于其中所有分支结点的权值之和
- 当一棵具有n 个叶子结点的二叉树的WPL 值为最小时,称其树为哈夫曼树,其二叉树的形状是唯一的
- 哈夫曼树是带权路径长度最短的树,路径上权值较大的结点离根较近
- 哈夫曼树的结点个数不能是偶数
解析:对于第四个,我们知道n个叶子节点,那么其哈弗曼树的节点数为2*n-1。
2-8哈夫曼树是n个带权叶子结点构成的所有二叉树中()最小的二叉树。 (2分)
- 权值
- 高度
- 带权路径长度
- 度
解析:哈弗曼树的性质。
2-9(neuDS)在哈夫曼树中,任何一个结点它的度都是( )。 (2分)
- 0或1
- 1或2
- 0或2
- 0或1或2
解析:哈弗曼树的性质。
编程题:
7-1 修理牧场 (25 分)
农夫要修理牧场的一段栅栏,他测量了栅栏,发现需要N块木头,每块木头长度为整数Li个长度单位,于是他购买了一条很长的、能锯成N块的木头,即该木头的长度是Li的总和。
但是农夫自己没有锯子,请人锯木的酬金跟这段木头的长度成正比。为简单起见,不妨就设酬金等于所锯木头的长度。例如,要将长度为20的木头锯成长度为8、7和5的三段,第一次锯木头花费20,将木头锯成12和8;第二次锯木头花费12,将长度为12的木头锯成7和5,总花费为32。如果第一次将木头锯成15和5,则第二次锯木头花费15,总花费为35(大于32)。
请编写程序帮助农夫计算将木头锯成N块的最少花费。
输入格式:
输入首先给出正整数N(≤104),表示要将木头锯成N块。第二行给出N个正整数(≤50),表示每段木块的长度。
输出格式:
输出一个整数,即将木头锯成N块的最少花费。
输入样例:
8
4 5 1 2 1 3 1 1
输出样例:
49
AC代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
priority_queue<int, vector<int>, greater<int> > que;
int n, x;
cin >> n;
for(int i = 0; i < n; i++)
{
cin >> x;
que.push(x);
}
int ans = 0;
while(que.size() != 1)
{
int a = que.top();
que.pop();
int b = que.top();
que.pop();
int c = a + b;
ans += c;
que.push(c);
}
cout << ans << endl;
return 0;
}