赫夫曼树

问题 G 算法6-12:自底向上的赫夫曼编码

时间限制: 1 Sec   内存限制: 128 MB
[ 提交]

题目描述

在通讯领域,经常需要将需要传送的文字转换成由二进制字符组成的字符串。在实际应用中,由于总是希望被传送的内容总长尽可能的短,如果对每个字符设计长度不等的编码,且让内容中出现次数较多的字符采用尽可能短的编码,则整个内容的总长便可以减少。另外,需要保证任何一个字符的编码都不是另一个字符的编码前缀,这种编码成为前缀编码。
而赫夫曼编码就是一种二进制前缀编码,其从叶子到根(自底向上)逆向求出每个字符的算法可以表示如下:
在本题中,读入n个字符所对应的权值,生成赫夫曼编码,并依次输出计算出的每一个赫夫曼编码。

输入

输入的第一行包含一个正整数n,表示共有n个字符需要编码。其中n不超过100。 第二行中有n个用空格隔开的正整数,分别表示n个字符的权值。

输出

共n行,每行一个字符串,表示对应字符的赫夫曼编码。

样例输入

85 29 7 8 14 23 3 11

样例输出

01101011101111110000111010
注意要排序,权值小的两个树中,序号小的在左边
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<malloc.h>
#include<math.h>
typedef struct{
    //char data;
    int weight;
    int lchild;
    int rchild;
    int parent;
}htnode;
typedef struct{
    char code[15];
    int start;
}hcode;
htnode ht[200];
hcode hcd[100];
void createht(htnode ht[],int n){
    int m=2*n-1;
    int i,j;
    for(i=0;i<m;i++){
        ht[i].parent=ht[i].lchild=ht[i].rchild=-1;
    }
    int min1,min2;
    int lnode,rnode;
    for(i=n;i<m;i++){
        min1=min2=99999;
        lnode=rnode=-1;
        for(j=0;j<i;j++){
            if(ht[j].weight<min1&&ht[j].parent==-1){
                min1=ht[j].weight;
                lnode=j;
            }
        }
        ht[lnode].parent=i;
        for(j=0;j<i;j++){
            if(ht[j].weight<min2&&ht[j].parent==-1){
                min2=ht[j].weight;
                rnode=j;
            }
        }
        ht[rnode].parent=i;
        if(lnode>rnode){
            int node,min;
            min=min1;min1=min2;min2=min;
            node=lnode;lnode=rnode;rnode=node;
        }
        ht[i].lchild=lnode;
        ht[i].rchild=rnode;
        ht[i].weight=min1+min2;
        //ht[lnode].parent=i;
        //ht[rnode].parent=i;
        //ht[i].weight=ht[lnode].weight+ht[rnode].weight;
    }
}
void createhcd(htnode ht[],hcode hcd[],int n){
    int i,j,k;
    char s[15];
    int top=0;
    int lnode,rnode;
    for(i=0;i<n;i++){
        j=i;
        lnode=j;
        while(j!=-1){
            j=ht[j].parent;
            if(ht[j].lchild==lnode) s[top]='0';
            else s[top]='1';
            top++;
            lnode=j;
        }
        k=0;
        top--;
        while(top>0){
            top--;
            hcd[i].code[k]=s[top];
            k++;
        }
        puts(hcd[i].code);
        top=0;
    }
    /*for(i=0;i<n;i++){
        j=i;
        printf("%d ",j);
        while(j!=-1){
            j=ht[j].parent;
            printf("%d ",j);
        }
        printf("\n");
    }*/
}
int main(){
    int n,i;
    while(~scanf("%d",&n)){
        for(i=0;i<n;i++){
            //ht[i].data=i;
            scanf("%d",&ht[i].weight);
        }
        createht(ht,n);
        createhcd(ht,hcd,n);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值