1003 entropy encoder

1003 Problem D

An entropy encoder is a data encoding method that achieves lossless data compression by encoding a message with “wasted” or “extra” information removed.

题意:对于一串字符,让使用频率高的二进制表示尽可能小,最终使得表示这串字符的二进制数最少。

思路:对于英文字母的编码就是求最优树,哈夫曼树每次让权值最小的树结合,得到新的节点,再利用新得到的权值,去计算下一个最小权值,最终让所有权值结合成一棵树,即得到最优树,以此来编码。

感想:权值的记录,以及左右兄弟的组合是问题关键,处理好此处,问题自然可解。

#include<iostream>

#include<string.h>

#include<algorithm>

using namespace std;

struct str{

    int l,r,c;

}tree[64];

int f[60];

int k;

string s;

void hefuman(int n,int p){

     if(f[n]==0) return ;

     if(n<=26) k+=f[n]*p;

     else{

       hefuman(tree[n].l,++p);

       hefuman(tree[n].r,p);

     }

}

int main(){

   int i,j,left,right;

   while(cin>>s){

       if(s=="END") break;

       int len=s.length();

       for(i=0;i<=60;i++) tree[i].c=-1;

       memset(f,0,sizeof(f));

       for(i=0;i<len;i++){       //统计字符个数

           if(s[i]=='_') f[26]++;

           else  f[s[i]-'A']++;

       }

       int node=26;

       while(1){

           int min=1000;

           for(i=0;i<=node;i++){

                if(tree[i].c==-1){

                   if(min>f[i]&&f[i]){

                        min=f[i];

                        left=i;

                    }

                }

           }

           min=1000;

           for(j=0;j<=node;j++){

                if(tree[j].c==-1){

                    if(min>f[j]&&j!=left&&f[j]){

                        min=f[j];

                        right=j;

                    }

                }

           }

           if(min==1000) break;

           f[++node]=f[left]+f[right];

           tree[node].l=left;

           tree[node].r=right;

           tree[node].c=-1;

           tree[left].c=node;

           tree[right].c=node;

       }

       k=0;

       if(node==26)  k=len;

       else hefuman(node,0);

       len*=8;

       printf("%d %d %.1f\n",len,k,len*1.0/k);

    }

   return 0;

 

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值