Hnust 1071 赫夫曼编码

问题 J: 赫夫曼编码

时间限制: 1 Sec  内存限制: 128 MB
提交: 15  解决: 6
[ 提交][ 状态][ 讨论版]

题目描述

赫夫曼编码能够产生最短的报文。以报文“ABCDABCDABCABDABAA”为例,A编为0,B对应10,C对应110,D对应111,整体的报文长度为35位二进制。相比于定长的ASCII码,压缩比达到了18*8/35=4.1。

输入

输入有一系列的字符串组成,每个字符串占据一行。字符串仅包含大写字母和下划线。字符串“END” 表示处理结束,不应对其处理。

输出

对每一个字符串,输出其ASCII编码的比特位长度,赫夫曼编码的比特位长度,以及二者之比,精确到小数点后一位。

样例输入

ABCDABCDABCABDABAA
AAAAAAAAAAAAAAAAAA
END

样例输出

144 35 4.11
44 18 8.0
 
  
  
#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
  
struct Node{ 
    int v; 
    int hash; 
    int a; 
    int parent; 
}num[200]; 
  
int fcmp(const void *a,const void *b) 
{ 
    return ((struct Node *)a)->v-((struct Node *)b)->v; 
} 
  
int fcmp2(const void *a,const void *b) 
{ 
    return ((struct Node *)a)->a-((struct Node *)b)->a; 
} 
char c[1000001]; 
  
int main(void) 
{ 
    int count,i,d1,d2,ok; 
    while(scanf("%s",c)) 
    { 
        if(strcmp(c,"END")==0) 
            break; 
        d1=strlen(c)*8; 
        count=0; 
        for(i=0;i<200;i++) 
        { 
            num[i].v=0; 
            num[i].hash=0; 
            num[i].parent=-1; 
            num[i].a=i; 
        } 
        for(i=0;c[i];i++) 
        { 
            if(c[i]!='_') 
            { 
                num[c[i]-'A'].v++; 
            } 
            else
                num[26].v++; 
        } 
        int tmp1,tmp2,flag; 
        count=26; 
        ok=0; 
        while(1) 
        { 
            flag=0; 
            qsort(num,count+1,sizeof(num[0]),fcmp); 
            for(i=0;i<=count;i++) 
            { 
                if(!num[i].hash && num[i].v!=0) 
                { 
                    num[i].hash=1; 
                    tmp1=i; 
                    i++; 
                    break; 
                } 
            } 
            while(i<=count) 
            { 
                if(!num[i].hash && num[i].v!=0) 
                { 
                    ok=1; 
                    num[i].hash=1; 
                    tmp2=i; 
                    i++; 
                    flag=1; 
                    break; 
                } 
                i++; 
            } 
            if(!flag) 
                break; 
            num[tmp1].parent=count+1; 
            num[tmp2].parent=count+1; 
            count++; 
            num[count].parent=-1; 
            num[count].v=num[tmp1].v+num[tmp2].v; 
            num[count].a=count; 
        } 
        if(ok==0) 
        { 
            for(i=0;i<=26;i++) 
            { 
                if(num[i].v) 
                    d2=num[i].v; 
            } 
        } 
        else
        { 
            qsort(num,count+1,sizeof(num[0]),fcmp2); 
            num[count].parent=-1; 
            int len,tmp; 
            d2=0; 
            for(i=0;i<=26;i++) 
            { 
                tmp=i; 
                len=0; 
                while(num[tmp].parent!=-1) 
                { 
                    tmp=num[tmp].parent; 
                    len++; 
                } 
                d2+=len*num[i].v; 
            } 
        } 
        printf("%d %d %.1lf\n",d1,d2,(double)d1/(double)d2); 
    } 
    return 0; 
} 
/************************************************************** 
    Problem: 1071 
    Language: C++ 
    Result: Accepted 
    Time:0 ms 
    Memory:1784 kb 
****************************************************************/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值