哈夫曼编码与解码

哈夫曼编码与译码

时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 520            测试通过 : 188

比赛描述

已知电文包括的字符集为{ACIMNPTU},输入对应权值,对字符集合进行哈夫曼编码,完成电文的哈夫曼编码与译码工作。

输入

共三行:

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

因为写的比较匆忙,代码质量并没有保障,不过已经通过了测试。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值