7-2 哈夫曼树与哈夫曼编码 (30分)
输入格式:
输入有3行。 第1行:符号个数n(2~20)。 第2行:一个不含空格的字符串。记录着本题的符号表。我们约定符号都是单个的小写英文字母,且从字符‘a’开始顺序出现。也就是说,如果 n 为 2 ,则符号表为 ab ;如果 n 为 6,则符号为 abcdef;以此类推。 第3行:各符号出现频率(用乘以100后的整数),用空格分隔。
输出格式:
先输出构造的哈夫曼树带权路径长度。 接下来输出n行,每行是一个字符和该字符对应的哈夫曼编码。字符按字典顺序输出。字符和哈夫曼编码之间以冒号分隔。
例如:
a:10
b:110
输入样例:
在这里给出一组输入。例如:
8
abcdefgh
5 29 7 8 14 23 3 11
输出样例:
在这里给出相应的输出。例如
271
a:0001
b:10
c:1110
d:1111
e:110
f:01
g:0000
h:001
提示: 以上示例数据,按题目要求建立的Haffman Tree如下图:
答案样例:
#include <bits/stdc++.h>
using namespace std;
string alp = "abcdefghijklmnopqrstuvwxyz";
string code[22]; //记录哈夫曼码
int ans; //计算权值
struct Tree {
int Weight;
char name;
Tree *Left, *Right;
};
struct cmp {
bool operator ()(const Tree T1, const Tree T2) {
return T1.Weight >= T2.Weight;
}
};
priority_queue<Tree, vector<Tree>, cmp> q;
string Code;
void dfs(Tree* T) {
if(!T->Left && !T->Right) {
code[T->name - 'a'] = Code;
ans += T->Weight * Code.size();
return;
}
Code.push_back('0');
dfs(T->Left);
Code.pop_back();
Code.push_back('1');
dfs(T->Right);
Code.pop_back();
}
int main() {
int n, W[22];
string str;
cin >> n >> str;
for (int i = 0; i < n; i++)
cin >> W[i], q.push({W[i], str[i], NULL, NULL});
Tree *L, *R, *T;
Tree a, b;
while (!q.empty()) {
a = q.top(), q.pop();
L = new Tree();
L->Weight = a.Weight, L->name = a.name;
L->Left = a.Left, L->Right = a.Right;
if(!q.empty()) {
b = q.top(), q.pop();
R = new Tree();
R->Weight = b.Weight, R->name = b.name;
R->Left = b.Left, R->Right = b.Right;
} else
break;
q.push({a.Weight + b.Weight, '-', L, R});
}
T = L;
dfs(T);
cout << ans << endl;
for (int i = 0; i < n; i++)
cout << alp[i] << ":" << code[i] << endl;
return 0;
}
感谢你的点赞❤⭐
哔哩哔哩/bilibili:羊卓的杨
公众号:羊卓的杨(后期上线实验报告功能)