- gf24240 的博客
《梦溪笔谈·C++》卷三十二:手搓哈夫曼树
- 2025-7-28 10:58:44 @
前言
写哈夫曼树太 suffering 了,还好有 dp 。
哈夫曼树理论部分
详见: 树论 、哈夫曼树&二叉搜索树
哈夫曼树代码部分
意外的死机故障不可避。
这是原版(未完成):
#include <map>
#include <queue>
#include <iostream>
using namespace std;
struct node
{
int t;
int c;
node* fa;
node* lc;
node* rc;
bool operator<(const node& other) const {
return t > other.t; // 注意:这是为了创建最小堆
}
};
string str;
priority_queue <node> q;
void make()
{
while (q.size() > 1)
{
node fst = q.top(); q.pop();
node sec = q.top(); q.pop();
node* nw = new node;
nw->t = fst.t + sec.t;
nw->c = -1;
nw->lc = new node(fst);
nw->rc = new node(sec);
nw->lc->fa = nw;
nw->rc->fa = nw;
q.push(*nw);
}
}
int main()
{
cin >> str;
string snt = str;
map <int, int> used;
for (char ch : str)
{
used[static_cast<int>(ch)]++;
}
for (auto i : used)
{
node nd = {};
nd.c = i.first;
nd.t = i.second;
nd.fa = nd.lc = nd.rc = NULL;
q.push(nd);
}
make();
cout << q.top().t;
return 0;
}
本来想重写的,但是既然找到了,为什么不用呢?
这是最终版:
#include <map>
#include <queue>
#include <iostream>
using namespace std;
struct node
{
int t;
int c;
node* fa;
node* lc;
node* rc;
bool operator<(const node& other) const {
return t > other.t;
}
};
string str, code[1005];
priority_queue <node> q;
void make()
{
while (q.size() > 1)
{
node fst = q.top(); q.pop();
node sec = q.top(); q.pop();
node* nw = new node;
nw->t = fst.t + sec.t;
nw->c = -1;
nw->lc = new node(fst);
nw->rc = new node(sec);
nw->lc->fa = nw;
nw->rc->fa = nw;
q.push(*nw);
}
}
void dfs(node* u, string bit)
{
if (u -> lc == nullptr && u -> rc == nullptr)
{
code[u -> c] = bit;
}
if (u -> lc)dfs(u -> lc, bit + '0');
if (u -> rc)dfs(u -> rc, bit + '1');
}
int main()
{
int n = 0;
cin >> str;
string snt = str;
map <int, int> used;
for (char ch : str)
{
used[static_cast<int>(ch)]++;
}
for (auto i : used)
{
n++;
node nd = {};
nd.c = i.first;
nd.t = i.second;
nd.fa = nd.lc = nd.rc = NULL;
q.push(nd);
}
make();
node root = q.top();
dfs(&root, "");
for (int i = 1; i <= 256; i++)
{
if (code[i] != "")
{
cout << char(i) << " : " << code[i] << "\n";
}
}
for (char ch : str)
{
cout << code[static_cast<int>(ch)];
}
return 0;
}
太好了,以后就用哈夫曼编码发消息
原理:
- 先将输入的字符串按照出现次数存储;
- 每次取出最小的两个节点,合并权值;
- DFS 生成编码;
- 输出编码。