哈夫曼编码与译码
时间限制(普通/Java) : 1000 MS/ 3000 MS 运行内存限制 : 65536 KByte总提交 : 520 测试通过 : 188
比赛描述
输入
共三行:
第一行为对应字符集{A,C,I,M,N,P,T,U}的权值
第二行为一段字符串表示的电文(长度不超过1000);
第三行为一段电文的哈夫曼编码。
输出
共十行:
前八行为各字符的编码;
第九行是与第二行输入对应的哈夫曼编码;
第十行是与第三行输入对应的电文。
样例输入
1 2 3 4 5 6 7 8
NUPTICPCACM
1111011111100
样例输出
A: 11110
C: 11111
I: 1110
M: 100
N: 101
P: 110
T: 00
U: 01
1010111000111011111110111111111011111100
ACM
来源:http://acm.njupt.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1022
有关哈夫曼编码的有关研究和讲解资料很多,我这儿就不多说了,这道题时南邮ACM网站上的一道题,我把源码拿出来就OK了。
#include<stdio.h>
int c[8][10] = {0}; //保存每个字符的哈夫曼编码
int temp[10] = {0};
int k = 0;
char s[8] = {'A','C','I','M','N','P','T','U'};
typedef struct node Node;
struct node
{
int head; //根节点
Node *r; //右子树
Node *l; //左子树
int flag;
int xb; //下标
};
//判断哈夫曼树是否建成
int isOK(Node *q,int l)
{
int temp = 1,i;
for (i = 0;i < l-1;i++)
{
if (q[i].flag == 1)
{
temp = 0;
break;
}
}
return temp;
}
//增加一个节点
void AddNode(Node *queue,int *l)
{
int i;
Node *m1=&queue[(*l)-1],*m2=&queue[(*l)-1];
int min1=10000, min2=10000;
for (i = 0;i < (*l);i++)
{
if (queue[i].flag == 1 && min1 > queue[i].head)
{
min1 = queue[i].head;
m1 = &queue[i];
}
}
m1->flag = 0;
for (i = 0;i < (*l);i++)
{
if (queue[i].flag == 1 && min2 >= queue[i].head)
{
min2 = queue[i].head;
m2 = &queue[i];
}
}
m2->flag = 0;
queue[*l].head = min1 + min2;
queue[*l].flag = 1;
queue[*l].r = m1;
queue[*l].l = m2;
queue[*l].xb = *l;
(*l) ++;
}
void BuildHuffman(Node queue[],int q[], int len)
{
int i;
//初始化
for (i = 0;i < len;i++)
{
queue[i].head = q[i];
queue[i].xb = i;
}
while (1)
{
if (isOK(queue,len)) //判断哈夫曼树是否建成
break;
AddNode(queue,&len); //增加节点
}
}
void code(int h)
{
int j;
for (j = 0;j < k;j++)
{
c[h][j] = temp[j];
}
}
//深度优先搜索哈夫曼树,并保存每个字符对应的哈夫曼编码
void DFS(Node *h)
{
if ((*h).r != NULL)
{
temp[k] = 0;
k++;
DFS((*h).r);
k--;
}
if ((*h).l != NULL)
{
temp[k] = 1;
k++;
DFS((*h).l);
k--;
}
if ((*h).r == NULL || (*h).l == NULL)
{
code(h->xb);
return;
}
return;
}
//打印出字符对应的二进制编码
void printcode(int c[])
{
int i;
for (i = 0;i < 5;i++)
{
if (c[i] == -1)
break;
printf ("%d",c[i]);
}
}
int decode2(int code[],int len,Node *head)
{
int i = 0;
Node *p = head;
for (i = 0;i < len;i++)
{
if (code[i] == 0)
{
p = p->r;
}
if (code[i] == 1)
{
p = p->l;
}
if (p->r == NULL)
{
printf ("%c",s[p->xb]);
p = head;
}
}
}
int main()
{
int i, j;
Node queue[100];
int q[8] = {1,2,3,4,5,6,7,8};
char str[1000];
int code[2000];
char tempcode[2000];
int len=0;
int lenoftree = 0;
//输入权值
for (i = 0;i < 8;i++)
scanf ("%d",&q[i]);
//初始化
for (i = 0;i < 100;i++)
{
queue[i].xb = -1;
queue[i].r = NULL;
queue[i].l = NULL;
queue[i].flag = 1;
}
//构建哈夫曼树
BuildHuffman(queue,q,8);
//初始化
for (i = 0;i < 8;i++)
for (j = 0;j < 10;j++)
c[i][j] = -1;
for (i = 0;i < 100 && queue[i].xb != -1;i++);
lenoftree = i-1;
DFS(&queue[lenoftree]);
//输出每个字符对应的编码
for (i = 0;i < 8;i++)
{
printf ("%c: ",s[i]);
for (j = 0;j < 5;j++)
{
if (c[i][j] != -1)
printf ("%d",c[i][j]);
}
printf ("\n");
}
scanf ("%s",str);
scanf ("%s",tempcode);
for (len = 0;len < 2000 && tempcode[len] != 0;len++)
{
code[len] = tempcode[len]-48;
}
for (i = 0;str[i] != 0;i++)
{
for (j = 0;j < 8;j++)
{
if (str[i] == s[j])
{
printcode(c[j]);
break;
}
}
}
printf ("\n");
// decode(code,len);
decode2(code,len,&queue[lenoftree]);
return 0;
}