POJ 1521 Entropy(哈夫曼编码)

这道题题意挺长的,其实就是哈夫曼编码和普通8位编码对内存占用情况的比较。使用哈夫曼编码就是让出现频率高的字母占用的内存尽可能的少,就是一个贪心的思想。貌似之前还没有做过哈夫曼树相关的题目,一开始的想法出了一些问题,没有想清楚哈夫曼树的实现,以为不建树也能直接求出来,不过看来是不行的……这样的话求解思路就很简单了:先统计所有字符出现的次数,根据出现次数建立哈夫曼树,每次贪心的取出两个最小的节点合并成一个新节点直到合并成一个点,当然,还要特判一下只有一种字符的情况,然后从上向下递归求解即可。
#include <iostream>
#include <cstdio>
#include <string.h>
#include <map>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
map<char,int> appear;
char str[10005];
int num[105];
struct Node    //哈夫曼树中的节点
{
    int value,pos,ls,rs;   //当前节点的值,在数组中的位置,左右儿子的下标
    Node()
    {
        value=0,pos=0,ls=0,rs=0;
    }
}huffman[10000];
bool operator <(const Node &a,const Node &b)   //重载运算符建立最小堆
{
    return a.value>b.value;
}
int ans;
void dfs(int pos,int deep)
{
    if(!huffman[pos].ls)   //如果是叶子节点则更新答案
    {
        ans+=deep*huffman[pos].value;    //当前字符出现次数乘以字段宽度
        return;
    }
    dfs(huffman[pos].ls,deep+1);    //递归左儿子
    dfs(huffman[pos].rs,deep+1);   //递归右儿子
}
int main()
{
    //freopen("input.txt","r",stdin);
    while(scanf("%s",str)!=EOF)
    {
        if(strcmp(str,"END")==0)
            break;
        appear.clear();
        ans=0;
        priority_queue<Node> q;
        memset(num,0,sizeof(num));
        memset(huffman,0,sizeof(huffman));
        int count=0;
        int len=strlen(str);
        for(int i=0; i<len; i++)
        {
            if(!appear[str[i]])  //如果当前字母没有出现过,则给它标号并把出现次数设为1
            {
                count++;
                appear[str[i]]=count;
                num[count]=1;
            }
            else    //已经出现过了就直接加吧
            {
                num[appear[str[i]]]++;
            }
        }
        for(int i=1; i<=count; i++)   //把所有节点都放到堆里
        {
            Node temp;
            temp.pos=i;
            temp.value=num[i];
            huffman[i]=temp;    //他们也都是哈夫曼树的叶子节点,先放进去
            q.push(temp);
        }
        if(q.size()==1)   //特判只有一种字母的情况
            ans=num[1];
        while(q.size()>1)    //合并这些节点直到只剩一个
        {
            Node a=q.top();
            q.pop();
            Node b=q.top();
            q.pop();
            Node temp;
            temp.value=a.value+b.value;
            temp.ls=a.pos;
            temp.rs=b.pos;
            temp.pos=++count;
            huffman[count]=temp;
            q.push(temp);
        }
        dfs(q.top().pos,0);   //更新答案
        printf("%d %d %.1lf\n",len*8,ans,len*8./ans);
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值