数据结构实验之二叉树六:哈夫曼编码
Time Limit: 1000MS
Memory Limit: 65536KB
Problem Description
字符的编码方式有多种,除了大家熟悉的ASCII编码,哈夫曼编码(Huffman Coding)也是一种编码方式,它是可变字长编码。该方法完全依据字符出现概率来构造出平均长度最短的编码,称之为最优编码。哈夫曼编码常被用于数据文件压缩中,其压缩率通常在20%~90%之间。你的任务是对从键盘输入的一个字符串求出它的ASCII编码长度和哈夫曼编码长度的比值。
Input
输入数据有多组,每组数据一行,表示要编码的字符串。
Output
对应字符的
ASCII
编码长度
la
,
huffman
编码长度
lh
和
la/lh
的值
(
保留一位小数
)
,数据之间以空格间隔。
Example Input
AAAAABCD THE_CAT_IN_THE_HAT
Example Output
64 13 4.9 144 51 2.8
Hint
Author
xam
哈夫曼做法(也可用堆和动规,类似合并果子)
#include <stdio.h>
#include <string.h>
#define Max 110
struct node
{
char data;
int weight;
int parent;
int l,r;
}L[Max];
int main()
{
char a[100],c;
int len,i,j,m,N,M,p1,p2,num;
int s1,s2;
while(scanf("%s",a) != EOF) //读入字符串
{
m = 1;
len = strlen(a);
for(i = 0;i <len;i++)
{
for(j = 0;j < m;j++)
{
if(a[i] == L[j].data)
{
L[j].weight++;
break;
}
}
if(j == m)
{
L[j].data = a[i]; //给儿子和父母赋初值
L[j].weight = 1;
L[j].l = L[j].r = 0;
L[i].parent = 0;
m++;
}
}
N = m-1; //叶子数
M = 2*m-3; //森林中树的数
for(i = N+1;i<=M;i++) //建立哈夫曼树
{
p1=p2=0; //最小权值的树的编号
s1=s2=2000; //最小权值
for(j =1;j<=i-1;j++)
{
if(L[j].parent == 0)
{
if(L[j].weight<s1)
{
s2=s1;
s1=L[j].weight;
p2=p1;
p1=j;
}
else if(L[j].weight<s2)
{
s2=L[j].weight;
p2=j;
}
}
}
L[p1].parent = i;
L[p2].parent = i;
L[i].l = p1;
L[i].r = p2;
L[i].weight = L[p1].weight + L[p2].weight;
}
num = 0; //计算哈夫曼编码长度
for(i = 0;i < len;i++)
{
for(j = 1;j <=N;j++)
{
if(a[i] == L[j].data)
{
while(L[j].parent != 0)
{
num++;
j = L[j].parent;
}
}
}
}
printf("%d %d %.1lf\n",8*len,num,(double)(8*len)/num); //输出结果
for(i = 1;i < M;i++) //还原数据,否则影响下次计算
{
L[i].data = ' '; //data不可能为‘ ’,所以赋值为‘ ’
L[i].l = L[i].r = 0;
L[i].parent = 0;
}
}
return 0;
}
哈夫曼做法(也可用堆和动规,类似合并果子)
#include <stdio.h>
#include <string.h>
#define Max 110
struct node
{
char data;
int weight;
int parent;
int l,r;
}L[Max];
int main()
{
char a[100],c;
int len,i,j,m,N,M,p1,p2,num;
int s1,s2;
while(scanf("%s",a) != EOF) //读入字符串
{
m = 1;
len = strlen(a);
for(i = 0;i <len;i++)
{
for(j = 0;j < m;j++)
{
if(a[i] == L[j].data)
{
L[j].weight++;
break;
}
}
if(j == m)
{
L[j].data = a[i]; //给儿子和父母赋初值
L[j].weight = 1;
L[j].l = L[j].r = 0;
L[i].parent = 0;
m++;
}
}
N = m-1; //叶子数
M = 2*m-3; //森林中树的数
for(i = N+1;i<=M;i++) //建立哈夫曼树
{
p1=p2=0; //最小权值的树的编号
s1=s2=2000; //最小权值
for(j =1;j<=i-1;j++)
{
if(L[j].parent == 0)
{
if(L[j].weight<s1)
{
s2=s1;
s1=L[j].weight;
p2=p1;
p1=j;
}
else if(L[j].weight<s2)
{
s2=L[j].weight;
p2=j;
}
}
}
L[p1].parent = i;
L[p2].parent = i;
L[i].l = p1;
L[i].r = p2;
L[i].weight = L[p1].weight + L[p2].weight;
}
num = 0; //计算哈夫曼编码长度
for(i = 0;i < len;i++)
{
for(j = 1;j <=N;j++)
{
if(a[i] == L[j].data)
{
while(L[j].parent != 0)
{
num++;
j = L[j].parent;
}
}
}
}
printf("%d %d %.1lf\n",8*len,num,(double)(8*len)/num); //输出结果
for(i = 1;i < M;i++) //还原数据,否则影响下次计算
{
L[i].data = ' '; //data不可能为‘ ’,所以赋值为‘ ’
L[i].l = L[i].r = 0;
L[i].parent = 0;
}
}
return 0;
}