HDU_1053 Entropy

  这道题目的长度很吓人,其实就是一道很裸的Hufuman编码问题,一般的《数据结构》书上都有,不说了,上代码:

 

#include <stdio.h>
#include
<string.h>
#define N 128
#define inf 0x7fffffff
struct node
{
int val; //权值
int left, right, parent;
}p[
1000];
int f[N]; //存放每个字母权值
int len[N]; //统计编码的长度

void hufuman(int n)
{
int i, min1, min2, pos1, pos2, flag;
for(i =0; i < n; i++)
{
p[i].val
= f[i];
p[i].parent
=-1;
p[i].left
=-1;
p[i].right
=-1;
}
while(1) //构建Hufuman树
{
int mark1 =0, mark2 =0;
min1
= min2 = inf;
for(i =0; i < n; i++) //每次取最小和第二小的元素
{
if(p[i].parent ==-1&& p[i].val < min1)
{
if(min1 != min2)
{
min2
= min1;
pos2
= pos1;
mark2
=1;
}
min1
= p[i].val;
pos1
= i;
mark1
=1;
}
elseif(p[i].parent ==-1&& p[i].val < min2)
{
min2
= p[i].val;
pos2
= i;
mark2
=1;
}
}
if(mark1 ==0|| mark2 ==0) //如果没有则跳出,表示已经建好Hufuman树
break;
p[n].val
= min1 + min2;
p[pos1].parent
= n;
p[pos2].parent
= n;
p[n].left
= pos1;
p[n].right
= pos2;
p[n].parent
=-1;
n
++;
}
for(i =0; i < n; i++)
{
if(p[i].right !=-1|| p[i].left !=-1) //如果不是原有的元素,而是后来构建出来的,则说明编码长度已经统计完
break;
flag
= i;
len[i]
=1;
while(p[flag].parent !=-1)
{
len[i]
++; //统计编码长度(这地方没有必要得出Hufuman编码,这道题用不到)
flag = p[flag].parent; //跳到i的父节点,继续查找
}
}
return;
}
int main()
{
char str[N];
int data[N], i;
while(gets(str) != NULL)
{
if(!strcmp(str, "END")) break;

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

for(i =0; i < strlen(str); i++)
data[(
int)str[i]]++; //求出每个字母的权值

int num =0;
for(i =0; i <128; i++)
{
if(data[i] !=0)
{
f[num
++] = data[i]; //给每个字母编号num,并将权值存到f[]
}
}
if(num ==1)
{
printf(
"%d %d 8.0\n",strlen(str)*8, f[0]);
continue;
}
hufuman(num);
int sum =0;
for(i =0; i < num; i++)
{
if(len[i] !=1)
sum
+= (len[i]-1)*f[i]; //编码总长度 = sum(每个字母所对应的编码长度 * 字母出现的次数)
}
printf(
"%d %d %.1f\n", strlen(str)*8,sum, strlen(str)*8/(float)sum);
}
return0;
}
posted @ 2011-08-08 09:55  AC_Von  阅读(258)  评论(0编辑  收藏  举报