算法实践11 哈夫曼编码
问题:
给定字符集\(C={x_1,x_2,\dots,x_n}\)和每个字符的频率\(f(x_i)\),求关于\(C\)的一个最优前缀码
解析
将所有的字符丢进一个堆中,按出现频率从小到大排序。按照哈夫曼算法,优先取出两个堆顶的元素,把它们出现的频率加在一起,再丢到堆里,直到只剩一个元素,就是最终得到的答案。
设计
while (q.size() > 1) {
取出栈顶的两个元素进行合并编号,建立结点关系
放回栈里
}
分析
for循环\(O(n)\),维护堆\(O(nlogn)\),算法时间复杂度\(O(nlogn)\)
源码
https://github.com/Sstee1XD/Algorithm_homework/tree/main/实验11 哈夫曼编码
#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
const int inf = 0x3f3f3f3f;
const int N = 1e3 + 7;
int n;
int fa[N], ww[N];
vector<int> son[N];
struct Node {
int id, w;
bool operator < (const Node &a) const {
return w > a.w;
}
};
void solve() {
scanf("%d", &n);
priority_queue<Node> q;
for (int i = 1; i <= n; ++i) {
scanf("%d", &ww[i]);
q.push({i, ww[i]});
}
while (q.size() > 1) {
Node l = q.top();
q.pop();
Node r = q.top();
q.pop();
int id = ++n, w = l.w + r.w;
ww[id] = w;
fa[l.id] = id, fa[r.id] = id;
son[id].push_back(l.id);
son[id].push_back(r.id);
q.push({id, w});
}
fa[q.top().id] = -1;
q.pop();
for (int i = 1; i <= n; ++i) {
printf("id:%d\tweight:%d\tparent:%d\t", i, ww[i], fa[i]);
if (son[i].size() == 0) {
printf("lson:-1\trson:-1\n");
} else {
printf("lson:%d\trson:%d\n", son[i][0], son[i][1]);
}
}
}
int main() {
// scanf("%d", &t);
int t = 1;
while (t--) solve();
return 0;
}
/*
8
5 5 10 10 10 15 20 25
*/

浙公网安备 33010602011771号