赫夫曼编译码器实验报告

来源:互联网 发布:肥皂水灌肠的浓度算法 编辑:程序博客网 时间:2024/06/11 01:07
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#define MAX 100#define MAXVALUE 10000typedef struct{    char ch;    int weight,flag;    int parent,lchild,rchild;}HTNode;typedef struct{    char ch;    int bit[MAX];    int start,weight;}Code;typedef struct{    char ch;    char bit[MAX];    int weight;}Coding;void HaffmanCoding1(int weight[],char ch[],int n,HTNode haffTree[]){    /**    生成哈夫曼树的函数1    */    int i,j,m1,m2,x1,x2;    for (i=0;i<2*n-1;i++){       if(i<n){           haffTree[i].weight=weight[i];           haffTree[i].ch=ch[i];       }       else haffTree[i].weight=0;       haffTree[i].parent=-1;       haffTree[i].flag=0;       haffTree[i].lchild=-1;       haffTree[i].rchild=-1;    }    for (i=0;i<n-1;i++){       m1=m2=MAXVALUE;       x1=x2=0;       for (j=0;j<n+i;j++){           if (haffTree[j].weight<m1&&haffTree[j].flag==0){              m2=m1;              x2=x1;              m1=haffTree[j].weight;              x1=j;           }           else if(haffTree[j].weight<m2 && haffTree[j].flag==0){              m2=haffTree[j].weight;              x2=j;           }       }       haffTree[x1].parent= n + i;       haffTree[x2].parent = n + i;       haffTree[x1].flag = 1;       haffTree[x2].flag = 1;       haffTree[n+i].weight = haffTree[x1].weight + haffTree[x2].weight;       haffTree[n+i].lchild = x1;       haffTree[n+i].rchild = x2;    }    /**    把哈弗曼树存储到huffman.txt中。    */    FILE *fp;    fp=fopen("huffman.txt","w+");    printf("%d\n",n);    fprintf(fp,"%d\n",n);    for (i=0;i<n;i++)       fprintf(fp,"%c %d %d %d\n",haffTree[i].ch,haffTree[i].parent,haffTree[i].lchild,haffTree[i].rchild);    for (i=n;i<2*n-1;i++)       fprintf(fp,"%d %d %d\n",haffTree[i].parent,haffTree[i].lchild,haffTree[i].rchild);    fclose(fp);}void HaffmanCoding2(HTNode haffTree[],int n,Code haffCode[]){    /**    生成哈夫曼树的函数2    */    Code *cd=( Code *) malloc (sizeof (Code));    int i,j,child,parent;    for (i=0; i<n; i++){       cd->start=n-1;       cd->weight=haffTree[i].weight;       cd->ch=haffTree[i].ch;       child=i;       parent=haffTree[child].parent;       while (parent !=-1){           if (haffTree[parent].lchild==child)              cd->bit[cd->start]=0;           else              cd->bit[cd->start]=1;           cd->start--;           child =parent;           parent=haffTree[child].parent;       }       for (j=cd->start+1; j<n; j++)           haffCode[i].bit[j]=cd->bit[j];       haffCode [i].start = cd->start+1;       haffCode [i].weight=cd->weight;       haffCode [i].ch=cd->ch;    }}void Initialization(int weight[],char ch[]){    /**    构造n个字符的赫夫曼编码HC    */    FILE *fp;    int i,j,n;    char ch1,wj[15];    printf("系统正在初始化。。。\n请输入字符集大小n:\n");    scanf("%d",&n);    HTNode *myHaffTree=(HTNode *)malloc(sizeof (HTNode)*(2*n+1));    Code *myHaffCode =(Code *)malloc (sizeof (Code)*n);    for (i=0;i<n;i++){        printf("请输入字符和权值:\n");        getchar();        ch[i] = getchar();        scanf("%d",&weight[i]);    }    HaffmanCoding1(weight,ch,n,myHaffTree);    HaffmanCoding2(myHaffTree,n,myHaffCode);    fp=fopen("hfmTree.txt","w+");    for (i=0;i<n;i++){       printf("%c %d ",myHaffCode[i].ch,myHaffCode[i].weight);       fprintf(fp,"%c %d ",myHaffCode[i].ch,myHaffCode[i].weight);        for ( j=myHaffCode[i].start; j<n; j++){           printf("%d",myHaffCode[i].bit[j]);           fprintf(fp,"%d",myHaffCode[i].bit[j]);       }            fprintf(fp,"\n");       printf("\n");    }    fclose(fp);    printf("初始化成功!\n");}void Encoding(){    /**    利用以建好的哈弗曼树(如不存在,从文件hfmTree中读)    输入正文进行编码,然后将结果存入文件CodeFile中    */    FILE *fp,*fp1,*fp2;    char zf[500];    fp=fopen("hfmTree.txt","r");    Coding ch[100];    char c;    int i=0;    while (feof(fp)==0){           fscanf(fp,"%s %d %s",&ch[i].ch,&ch[i].weight,&ch[i].bit);            i++;    }    fclose(fp);    printf("现在进行编码操作。。。\n请输入字符串:\n");    scanf("%s",zf);    char ch1[20],ch2[20];    int j;    fp2=fopen("CodeFile.txt","w+");    int len,k;    len=strlen(zf);    for (k=0; k<len; k++)        for (j=0; j<i; j++)            if (ch[j].ch==zf[k]){                fprintf(fp2,"%s",ch[j].bit);                printf("%s",ch[j].bit);            }    printf("\n");    fclose(fp2);    printf("编码完成!已将结果存入CodeFile.txt中.\n\n");}void Decoding(){    /**    利用已建好的哈弗曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。    */    FILE *fp,*fp1;    fp=fopen("huffman.txt","r");    int i,n;    fscanf(fp,"%d",&n);    HTNode *myHaffTree=(HTNode *)malloc(sizeof (HTNode)*(2*n+1));    for (i=0;i<n;i++)        fscanf(fp,"%s %d %d %d\n",&myHaffTree[i].ch,&myHaffTree[i].parent,&myHaffTree[i].lchild,&myHaffTree[i].rchild);    for (i=n;i<2*n-1;i++)       fscanf(fp,"%d %d %d\n",&myHaffTree[i].parent,&myHaffTree[i].lchild,&myHaffTree[i].rchild);    fclose(fp);    fp=fopen("CodeFile.txt","r");    fp1=fopen("TextFile.txt","w+");    char ch;    i=2*n-2;    while (!feof(fp)){        fscanf(fp,"%c",&ch);       if (ch=='0') i=myHaffTree[i].lchild;       if (ch=='1') i=myHaffTree[i].rchild;       if (i<n){           printf("%c",myHaffTree[i].ch);            fprintf(fp1,"%c",myHaffTree[i].ch);           i=2*n-2;       }    }    printf("\n");    fprintf(fp1,"\n");    fclose(fp);    fclose(fp1);    printf("译码过程完成!已将结果存入TextFile.txt中.\n\n");}void Print(){    /**    将文件CodeFile以紧凑格式显示在终端上,每行50个代码    同时将此字符形式的编码文件写入文件CodePrin中。    */    FILE *fp1,*fp2;    fp1=fopen("CodeFile.txt","r");    fp2=fopen("CodePrin.txt","w+");    int count=0;    char ch;    while (!feof(fp1)){        fscanf(fp1,"%c",&ch);       printf("%c",ch);       fprintf(fp2,"%c",ch);       count++;       if (count==50){           printf("\n");           fprintf(fp2,"\n");            count=0;       }    }    printf("\n");    fprintf(fp2,"\n");    fclose(fp1);    fclose(fp2);    printf("打印代码过程完成!已将结果存入CodePrin.txt中.\n\n");}void PrintTree(HTNode *huf,int n,int p,FILE *fp){    /**    打印哈弗曼树函数    树是横向显示的,叶子节点显示字符,非叶子节点显示'@'    */    int i;    if (n==-1)  return;    PrintTree(huf,huf[n].rchild,p+1,fp);    for (i=0;i<p;i++){        printf("   ");        fprintf(fp,"   ");    }    if (p>=0&&huf[n].rchild==-1){       printf("---");       printf("%c\n",huf[n].ch);       fprintf(fp,"---%c\n",huf[n].ch);    }    else{       printf("@\n");       fprintf(fp,"@\n");    }    PrintTree(huf,huf[n].lchild,p+1,fp);}void Treeprinting(){     /**    将已在内存中的哈弗曼树以直观的方式(树或凹入表形式)显示在终端上    同时将次字符形式的哈弗曼树写入文件TreePrint中。    */    FILE *fp;    fp=fopen("huffman.txt","r");    int i,n;    fscanf(fp,"%d",&n);    HTNode *myHaffTree=(HTNode *)malloc(sizeof (HTNode)*(2*n+1));    for (i=0;i<n;i++)       fscanf(fp,"%s %d %d %d\n",&myHaffTree[i].ch,&myHaffTree[i].parent,&myHaffTree[i].lchild,&myHaffTree[i].rchild);    for (i=n;i<2*n-1;i++)       fscanf(fp,"%d %d %d\n",&myHaffTree[i].parent,&myHaffTree[i].lchild,&myHaffTree[i].rchild);    fclose(fp);    fp=fopen("TreePrint.txt","w+");    PrintTree(myHaffTree,2*n-2,0,fp);    fclose(fp);    printf("打印哈夫曼树过程完成!同时已将结果存入TreePrint中.\n\n");}void Menuprint(){    printf("*******************************************************************************\n");    printf("*****                                                                     *****\n");    printf("*****                                                                     *****\n");    printf("*****                       欢迎使用哈夫曼编/译码器                      *****\n");    printf("*****                                                                     *****\n");    printf("*****                                                                     *****\n");    printf("***** E.编码   D.译码   P.印代码文件   T.印哈夫曼树   Q.退出  *****\n");    printf("*****                                                                     *****\n");    printf("*******************************************************************************\n");}int main(){    int i,j,n=4;    int weight[100];    char ch[100],cha;    Menuprint();    Initialization(weight,ch);    while (1){      printf("请输入要执行的操作:\nE.编码   D.译码   P.印代码文件   T.印哈夫曼树   Q.退出\n");       printf("请输入要执行的操作:\n");       scanf("%s",&cha);       if (cha=='Q')    break;       switch (cha){       case 'E':    Encoding();     break;       case 'D':    Decoding();     break;       case 'P':    Print();        break;       case 'T':    Treeprinting(); break;       }    }    return 0;}

0 0
原创粉丝点击