HDU1053 Entropy(huffman编码)

///题目的大致意思是给你一个大写字母和下滑线组成的字符串,先计算出字符串在内存中实际占用的字节数,每个char占用8个字节

///然后通过huffman编码后字符串所占的字节数,两者相除即可


#include <cstdio>

#include <cstring>
#include <queue>
using namespace std;
#define MAX 50010///题目为给出字符串的长度,所以此处分配的尽量大一点
char s[MAX];
int len;
int v[256];///压缩
int ans;
struct node
{
    int num;
    int cnt;
    int lchild;
    int rchild;
    friend bool operator<(node a,node b);
}tree[MAX*2];
bool operator<(node a,node b)
{
    return a.cnt>b.cnt;/// cnt越小优先权越大
}
priority_queue<node> q;
void dfs(int root,int h);
int built_tree();
int main()
{
    while(scanf("%s",s)==1&&strcmp(s,"END")!=0)
    {
        len=strlen(s);
        memset(v,0,sizeof(v));
        for(int i=0; i<len; i++)
        {
            int tmp=(int)s[i];
            v[tmp]+=1;
        }
        int root=built_tree();
        ans=0;
        if(root!=0)/// 临界情况:只有一钟字符时的情况。当时做这道题目是未考虑这种情况,导致wrong answer
        {
            dfs(root,0);
            ans/=2;
        }
        else
        ans=tree[0].cnt;
        printf("%d %d %.1f\n",len*8,ans,(double)len*8/ans);
    }
    return 0;
}
int built_tree()建立huffman树
{
    while(!q.empty())
        q.pop();
    int pos=0;
    for(int i=0; i<255; i++)
        if(v[i]!=0)
        {
            tree[pos].num= pos;///此处应该理清关系
            tree[pos].cnt= v[i];
            tree[pos].lchild=-1;
            tree[pos].rchild=-1;
            q.push(tree[pos]);
            pos++;
        }
    while(!q.empty()) ///此处大忌,当时多加了一个;导致死循环,debug时超级郁闷
    {
        node t1=q.top();
        q.pop();
        if(q.empty())
            return t1.num;
        node t2=q.top();
        q.pop();
        tree[pos].num=pos;
        tree[pos].cnt=t1.cnt+t2.cnt;
        tree[pos].lchild=t1.num;
        tree[pos].rchild=t2.num;
        if(q.empty())
            return pos;
        q.push(tree[pos]);
        pos++;
    }
}
void dfs(int root,int h)///通过深搜找到每个子节点的深度即编码长度,累加求和
{
    if(tree[root].lchild==-1)
        ans+=(tree[root].cnt*h);
    else
        dfs(tree[root].lchild,h+1);
    if(tree[root].rchild==-1)
        ans+=(tree[root].cnt*h);
    else
        dfs(tree[root].rchild,h+1);

}


总结:1、临界情况需要仔细考虑

    2、细节问题while()

    3、熟悉优先队列的使用方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值