进阶实验4-3.5 哈夫曼编码 (30 分)
这是学了哈夫曼编码后立马写的,当时写出来感觉很不错哈哈哈
(PS:回来复习加个注释,代码懒得优化了)
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
int n, m;
string s1[100];
struct node{
int w; //权重
int p; //父节点
int l; //左孩子
int r; //右孩子
}ht[4000]; //哈夫曼树
struct code{
string s;
}hc[64]; // 哈夫曼编码
void CreateHafuman() { //建立哈夫曼树
int i, j, lnode, rnode;
int min1, min2;
for(i = 0; i < 2 * n - 1; i++) //总结点是 2*n - 1 比较特殊
ht[i].p = ht[i].l = ht[i].r = -1; //初始化
for(i = n; i < 2 * n - 1; i++) { //从初始 n个节点以后建树
min1 = min2 = inf;
lnode = rnode = -1;
for(j = 0; j < i; j++) { //向前找
if(ht[j].p == -1) { //找没有父亲的节点
if(ht[j].w < min1) { //找第一个最小值
min2 = min1;
rnode = lnode;
min1 = ht[j].w;
lnode = j;
} else if(ht[j].w < min2) { //找第二个最小值
min2 = ht[j].w;
rnode = j;
}
}
}
ht[i].w = ht[lnode].w + ht[rnode].w; //当前 i节点的值是两个最小值的和
ht[i].l = lnode; ht[i].r = rnode;
ht[lnode].p = i; ht[rnode].p = i; // 当前 i节点是两个最小值节点的父节点
}
}
void CreatCode() { //哈夫曼编码
int i, j, f;
for(i = 0; i < n; i++) {
j = i;
f = ht[i].p;
while(f != -1) { //从此时 i一直找到根节点
if(ht[f].l == j) //编码可以自己改
hc[i].s += '0';
else
hc[i].s += '1';
j = f;
f = ht[f].p;
}
}
}
int main() {
int i, j;
char a;
cin >> n;
for(i = 0; i < n; i++)
cin >> a >> ht[i].w;
CreateHafuman();
CreatCode();
int len = 0;
for(i = 0; i < n; i++)
len += hc[i].s.length() * ht[i].w;
cin >> m;
while(m--) {
int len1 = 0, f = 1;
for(i = 0; i < n; i++) {
cin >> a;
cin >> s1[i];
len1 += s1[i].length() * ht[i].w;
}
if(len1 != len)
cout << "No" << endl;
else {
for(i = 0; i < n; ++i) {
for(j = 0; j < n; ++j)
{
if(i == j) continue;
int l1 = s1[j].length(), l2 = s1[i].length();
if(l1 >= l2) {
if(s1[j].substr(0,l2) == s1[i]) {
f = 0; break;
}
}
}
if(f == 0) break;
}
if(f)
cout << "Yes" << endl;
else
cout << "No" << endl;
}
}
return 0;
}