对26个英文字母进行huffman编码

来源:互联网 发布:excel中找出相同数据 编辑:程序博客网 时间:2024/05/16 00:50
<ol><li class="alt"><span><span class="comment">1、建立哈夫曼树</span> </span></li><li><span><span class="comment">2、从每个叶结点回溯到root的路径,并记录路径,则为哈夫曼编码</span> </span></li><li class="alt"><span><span class="comment">3、查表方式获得每个字符的哈夫曼编码</span> </span></li></ol>
#include <stdio.h>#include <stdlib.h>#include <string.h>///----------------------定义结点数据---------------#define leave 26#define node (26*2-1)typedef struct nodee{    char character;    float weight;    int lson;    int rson;    int par;}Node,*pnode;typedef struct code{    int hufcode[leave];///叶节点最长编码位数应该为树的最长路径 ,储存编码结果    int sta;  ///编码起始位(相对编码数组)    char Char; ///编码的字符值}Code,*pcode;///----------------------构造哈夫曼树----------------void huffman(Node ht[],float wt[]){    int i,j,x1,x2;    float min1,min2;///初始化结点数组ht  ,即对huffman树进行初始化    for(i=0;i<node;i++)    {        ht[i].par=-1;        ht[i].lson=-1;        ht[i].rson=-1;        if(i<leave)        {            ht[i].weight=wt[i];            ht[i].character=i+65;///A-Z的ASCii码        }        else        {            ht[i].weight=0;            ht[i].character='?';///生成的中间结点字符值标记为'?'        }    }///控制n-1次结点的结合(若有n个叶结点)    for(i=1;i<leave;i++)    {        min1=min2=100;///min1、min2记录当前最小、次小权值        x1=x2=0; ///x1、x2记录当前最小次小权值结点的位置(数组标号)        for(j=0;j<leave-1+i;j++) ///在[0-j]范围内找最小次小权值结点        {            if(ht[j].par==-1 && ht[j].weight<min1)///parent元素的判断是为了排除已结合过的结点,结合过的结点parent有正值            {                min2=min1;///当前结点权值小于最小值,所以当前结点变成最小权值结点,原最小结点变成原来的次小结点                x2=x1;                min1=ht[j].weight;                x1=j;            }            else            {                if(ht[j].par==-1 && ht[j].weight<min2) ///当前结点权值大于最小值,小于次小值,则取代次小结点                {                    min2=ht[j].weight;                    x2=j;                }            }        }        ///将找到的最小、次小权值结点结合成树,为其父结点赋值,可见该哈夫曼树的根节点应该是ht数组最后一个结点ht[node-1]        ht[x1].par=leave-1+i;        ht[x2].par=leave-1+i;        ht[leave-1+i].weight=ht[x1].weight+ht[x2].weight;        ht[leave-1+i].lson=x1;        ht[leave-1+i].rson=x2;    }}///--------------------获取并保存每个叶节点的哈夫曼编码供解码时查询--------------------------void codeht(Node ht[],Code hc[]){    int i,j,d,p;    Code x;///依次每个叶结点(在哈夫曼结点数组的最前面的空间中)寻找双亲直到root,记录路径,路径就是哈夫曼编码    for(i=0;i<leave;i++)///从每个字母都向上找寻根节点,使得整个树完整的编码    {        x.Char=ht[i].character;        x.sta=leave-1;///默认编码起点为编码数组最后一位        d=i;        p=ht[i].par;        while(1)        {            if(ht[p].lson == d)                x.hufcode[x.sta]=0;///默认编码为左0右1            else if(ht[p].rson==d)                x.hufcode[x.sta]=1;            else               printf("ERROR!!");            d=p;            p=ht[d].par;///继续向着根延伸编码            if(p==-1)break;///到了26个字母以外停止,ht[i]为root结点退出循环,说明已经回溯到了根结点            x.sta--;        }        for(j=x.sta;j<leave;j++)        {            hc[i].hufcode[j]=x.hufcode[j];        }        hc[i].sta=x.sta;        hc[i].Char=x.Char;    }}///--------------------输出每个字符的的哈夫曼编码------------------------void printcode(Code hc[]){    int i,j;    for(i=0;i<leave;i++)    {        printf("字母%c的huffman编码为:",hc[i].Char);        for(j=hc[i].sta;j<leave;j++)        {            printf("%d",hc[i].hufcode[j]);        }        printf("\n");    }}///-----------------------查询字符的编码---------------------------void findcode(Code hc[]){    int i,j;    char x;    printf("请输入一个大写英文字母:");    while(scanf("%c",&x)!=EOF)    {        getchar();        for(i=0;i<leave;i++)        {            if(x==hc[i].Char)            {                printf("字符%c的huffman编码为:",x);                for(j=hc[i].sta;j<leave;j++)                {                    printf("%d",hc[i].hufcode[j]);                }                printf("\n");            }        }        printf("请输入一个大写英文字母:");    }}///---------------------主函数-----------------------int main(){    Node huftree[node];///存放所有结点数据    Code hcode[leave];///存放所有的编码结果    ///存放叶结点权值    float wt[leave]={0.0856,0.0139,0.0297,0.0378,0.1304,0.0289,0.0199,0.0528,0.0627,0.0013,0.0042,0.0339,0.0249,0.0707,0.0797,0.0199,0.0012,0.0677,0.0607,0.1045,0.0249,0.0092,0.0149,0.0017,0.0199,0.0008};    huffman(huftree,wt);    codeht(huftree,hcode);    printcode(hcode);///调用可以输出所有的字母编码    findcode(hcode);    return 0;}

0 0
原创粉丝点击