您的位置:首页 > 其它

哈夫曼编码与解码

2015-09-19 14:48 134 查看

哈夫曼编码与译码

时间限制(普通/Java) : 1000 MS/ 3000 MS 运行内存限制 : 65536 KByte

总提交 : 520 测试通过 : 188


比赛描述
已知电文包括的字符集为{A,C,I,M,N,P,T,U},输入对应权值,对字符集合进行哈夫曼编码,完成电文的哈夫曼编码与译码工作。

输入

共三行:

第一行为对应字符集{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;

}

因为写的比较匆忙,代码质量并没有保障,不过已经通过了测试。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: