二十二、计算WPL
文章目录
- 二十二、计算WPL
- 题目描述
- 解题思路
- 上机代码
题目描述
Huffman编码是通信系统中常用的一种不等长编码,它的特点是:能够使编码之后的电文长度最短。
输入:
第一行为要编码的符号数量n
第二行~第n+1行为每个符号出现的频率
输出:
对应哈夫曼树的带权路径长度WPL
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 5 7 5 2 4 9 |
WPL=60 | 1秒 | 64M | 0 |
测试用例 2 | 5 2 4 2 3 3 |
WPL=32 | 1秒 | 64M | 0 |
解题思路
哈夫曼树的带权路径长度WPL,按道理来讲应该规规矩矩地建立哈夫曼树,逐层计算数值再求和。
当然,我们也有更好的思路,抛开哈夫曼树,只要抓住了其中的数学本质,借助队列一样可以算出 WPL 。
对于输入的序列,然后按照从小到大顺序加入队列中。
每次取出队列中的前两个小值,将两个值的和加到 sum
中,再将求和后的新值再次加入队列中,继续从队列中选取两个最小的值,n 个值一共选 n-1 次。这样,我们就模拟出了哈夫曼树的计算过程,每次取两个最小的值,将求和后的新值继续与其他值做比较再选取。
因为每次要取出的是两个最小的值,这其中涉及到了一个排序的问题,普通的队列只能按照加入的顺序进行读取,是无法实现排序的,因此我们使用优先队列来进行值的选取(优先队列自带了排序功能,方便好用)。每次需要的是最小值,所以我们对输入序列的元素取负值,这样可以保证队列中的最大值就是原序列中的最小值。
在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有*先出 (first in, largest out)的行为特征。对于普通的数值来说,数值越大,优先级越高。
上机代码
#include<iostream>
#include<queue>
#include<cstdio>
#include<cstdlib>
using namespace std;
priority_queue<int>q;
int main()
{
int n, i, x, sum = 0, t;
cin >> n;
for (i = 0; i<n; i++)
{
cin >> x;
q.push(-x);//存入负值
}
//一共选n-1次
for (i = 1; i<n; i++)
{
t = q.top();
sum -= q.top();
q.pop();
t += q.top();
sum -= q.top();
q.pop();
q.push(t);
}
cout <<"WPL="<< sum << endl;
//system("pause");
return 0;
}