POJ - 1521 Entropy (Huffman编码)
题目大意:
输入一行的字符串, 分别用8bit-ASCII编码和Huffman编码, 求出编码后所占的空间以及压缩比(ASC/Huffman)
思路: 利用优先队列实现Huffman编码, 其中并不需要建树, 只需要求出每个字符出现的频数, 借助优先队列求出根节点的频次.
Huffman编码的实现过程类似于经典题 "合并果子".
Huffman编码的本质是贪心的思想, 出现频次多的放在树的上层, 少的放在下层, 以此作为贪心的策略, 即可得到最优的Huffman编码.
同时注意, 对于本题有一个需要注意的点, 对于只有相同字符的字符串需要特判一下, Huffman树编码前提条件是需要多字符的树.
完整代码如下:
/*
* @Author: Hellcat
* @Date: 2020-03-28 11:13:41
*/
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <string>
using namespace std;
int main() {
string s;
priority_queue<int, vector<int>, greater<int> > q;
while(getline(cin, s) && s != "END") {
while(q.size()) q.pop();
int Asc = s.length() * 8;
sort(s.begin(), s.end());
int t = 1;
for(int i = 1; i < s.length(); i++) {
if(s[i] != s[i-1]) {
q.push(t); t = 1;
}
else t++;
}
q.push(t);
int Huff = 0;
if(q.size() == 1) Huff = t; // 只出现一种字符时特判
while(q.size() > 1) {
int a = q.top(); q.pop();
int b = q.top(); q.pop();
q.push(a+b);
Huff += (a+b);
}
q.pop();
printf("%d %d %.1f\n", Asc, Huff, (double)Asc/Huff*1.0);
}
}