|
楼主 |
发表于 2022-3-29 09:06:21
|
显示全部楼层
#include<bits/stdc++.h>
using namespace std;
struct Node{
int val;
char ch;
int lson, rson;
// val 记录出现的频率
// ch 记录叶子结点对应的字符
// lson 和 rson 分别对应左右子树
Node(){}
Node(int val, char ch): val(val), ch(ch){
lson = rson = 0;
}
}no[1000];
int cnt;
class MyPriorityQueue{
int arr[1000], cnt, siz;
public:
int top(){
int ret = -1;
for(int i = 1; i <= cnt; i++){
if(arr[i] == -1) continue;
if(ret == -1 || no[ret].val > no[i].val){
ret = i;
}
}
return ret;
}
// 返回一个val值最小的结点编号
int pop(){
int t = top();
for(int i = 1; i <= cnt; i++){
if(arr[i] == t){
arr[i] = -1;
siz--;
}
}
}
// 删除pop出的结点
void push(int x){
arr[++cnt] = x;
siz++;
}
// 加入一个结点
int size(){
return siz;
}
// 返回优先队列里面的结点个数
}pq;
int num[256];
// 记录每种字符出现的次数
map<char, string> bm;
// 存字符对应的编码
void dfs(int u, string ans){
if(!u) return;
if(no[u].lson == 0 && no[u].rson == 0){
bm[no[u].ch] = ans;
return;
}
dfs(no[u].lson, ans + "0");
dfs(no[u].rson, ans + "1");
}
// 在哈夫曼树上递归,算出叶子节点对应的编码
int main(){
string s, t = "";
cin >> s;
for(auto ch : s) num[ch]++;
// 统计每种字符出现次数
for(int i = 0; i < 256; i++){
if(num[i]){
no[++cnt] = Node(num[i], i);
pq.push(cnt);
}
}
// 先将每个结点放进优先队列
if(pq.size() == 1){
no[++cnt].lson = pq.top(); pq.pop();
pq.push(cnt);
}
// 特殊处理只有一种字符的情况
while(pq.size() != 1){
cnt++;
no[cnt].lson = pq.top(); pq.pop();
no[cnt].rson = pq.top(); pq.pop();
no[cnt].val = no[no[cnt].lson].val + no[no[cnt].rson].val;
pq.push(cnt);
}
// 每次合并两个子树
dfs(pq.top(), "");
// 优先队列里面唯一的结点一定是哈夫曼树的根节点
for(auto P : bm){
cout << P.first << " : " << P.second << endl;
}
// 输出每种字符以及对应的编码 |
|