哈夫曼编/译码系统的设计与实现

来源:互联网 发布:pd11 for mac 破解版 编辑:程序博客网 时间:2024/06/05 16:19

问题描述

利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(解码)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站设计一个哈夫曼编译码系统。

基本要求

  1. 初始化(Initialzation)。从数据文件DataFile.data中读入字符及每个字符的权值,建立哈夫曼树HuffTree;
  2. 编码(EnCoding)。用已建好的哈夫曼树,对文件ToBeTran.data中的文本进行编码形成报文,将报文写在文件Code.txt中
  3. 译码(Decoding)。利用已建好的哈夫曼树,对文件CodeFile.data中的代码进行解码形成原文,结果存入文件Textfile.txt中
  4. 输出(Output)。输出DataFile.data中出现的字符以及各字符出现的频度(或概率);输出ToBeTran.data及其报文Code.txt;输出CodeFile.data及其原文Textfile.txt

大致过程

  1. 首先需要写好哈夫曼树的建立和编码过程
  2. 其次对于译码,则可以从文件中一次读取一个单词,然后挨个完成译码。分别输出到文件。
  3. 对于解码,一次读一个单词的哈夫曼码,依次和之前编好的哈夫曼码进行匹配,直到全部解码完成

    数据结构

哈夫曼树节点

typedef struct {    int weight;    int parent,lchild,rchild;}HufNode;

初始节点

typedef struct {    int weight;    char data;    char code[maxn];//需要被建树的信息}HufCode;

程序模块

(1) 初始化输入数据

void Init(HufCode h[])//初始化输入数据{    FILE *f1=fopen("DataFile.data","r");    for(int i=0;i<alphanumber;++i)        fscanf(f1,"%c%d ",&h[i].data,&h[i].weight);    fclose(f1);}

(2) 根据数据建立哈夫曼树及将编码保存

void HuffmanTree(HufCode *h2,HufNode *h1,int n){    char str[maxn];    int m=2*n-1;    for(int i=0;i<m;++i){        if(i<n)//前n个全部是叶子节点,            h1[i].weight=h2[i].weight;        else//后面的是还没建成的树            h1[i].weight==0;        h1[i].lchild=h1[i].parent=h1[i].rchild=0;    }    int s1,s2;    for(int i=n;i<m;++i){        select(h1,i,s1,s2);        h1[s1].parent=i;//建立二叉树        h1[s2].parent=i;        h1[i].lchild=s1;        h1[i].rchild=s2;        h1[i].weight=h1[s1].weight+h1[s2].weight;    }    str[n]='\0';    int l;    for(int i=0;i<n;++i){//从每个叶子节点开始倒序遍历        l=n-1;//倒序赋值字符串        for(int k=i,p=h1[k].parent;p;k=p,p=h1[k].parent){//沿着叶子回溯到根节点            if(k==h1[p].lchild)                str[l]='0';            else                str[l]='1';            l--;        }        strcpy(h2[i].code,str+l+1);       // printf("%c %s\n",h2[i].data,h2[i].code);    }}

(3) 根节点中选择两个最小的根

void select(HufNode *h,int k,int &s1,int &s2)//选择两个最小的值{    int i;    for(i=0; i<k && h[i].parent != 0; ++i);//选择一个父节点为0的根节点        s1 = i;    for(i=0; i<k; ++i){        if(h[i].parent==0 && h[i].weight<h[s1].weight)              s1 = i;    }    for(i=0; i<k; ++i){        if(h[i].parent==0 && i!=s1)            break;    }    s2 = i;    for(i=0; i<k; ++i){        if(h[i].parent==0 && i!=s1 && h[i].weight<h[s2].weight)            s2 = i;    }}

(4) 编码

void EnCodeing(HufCode hc[]){    FILE *f1=fopen("ToBeTran.data","r");    FILE *f2=fopen("Code.txt","w");    char str[maxn];    while(fscanf(f1,"%s",str)!=EOF)    {        int len=strlen(str);        for(int i=0;i<len;++i){            int x=str[i]-'a';            fprintf(f2,"%s",hc[x].code);        }        fprintf(f2," ");    }    fclose(f1);    fclose(f2);}

(5) 解码

int Search(HufCode hc[],char *str){    for(int i=0;i<alphanumber;++i)        if(strcmp(hc[i].code,str)==0)            return  i;    return -1;}void DeCodeing(HufCode hc[]){    FILE *f1=fopen("CodeFile.data","r");    FILE *f2=fopen("Textfile.txt","w");    char str[maxn];    while(fscanf(f1,"%s",str)!=EOF)    {        char a[maxn];        memset(a,'\0',sizeof(a));        int len=strlen(str),k=0;        for(int i=0;i<len;++i){            a[k]=str[i];            a[k+1]='\0';            int ans=Search(hc,a);            if(ans!=-1){                fprintf(f2,"%c",ans+'a');                k=0;                continue;            }            k++;        }        fprintf(f2," ");    }    fclose(f1);    fclose(f2);}

(6) 输出结果

void OutPut(){    FILE *infile=fopen("DataFile.data","r");    FILE *outfile=fopen("Code.txt","r");    int w;    char c;    printf("各个字母及其权值\n");    for(int i=0;i<alphanumber;++i){        fscanf(infile,"%c %d ",&c,&w);        printf("%c %d ",c,w);    }    infile=fopen("ToBeTran.data","r");    printf("\n\n待编码的内容:\n");    char str[maxn];    while(fscanf(infile,"%s",str)!=EOF)        printf("%s ",str);    printf("\n编码后结果:\n");    while(fscanf(outfile,"%s",str)!=EOF)        printf("%s ",str);    printf("\n\n待解码内容:\n");    infile=fopen("CodeFile.data","r");    while(fscanf(infile,"%s",str)!=EOF)        printf("%s ",str);    printf("\n解码结果:\n");    outfile=fopen("Textfile.txt","r");    while(fscanf(outfile,"%s",str)!=EOF)        printf("%s ",str);    printf("\n");    fclose(infile);    fclose(outfile);}

全部程序

#include<bits/stdc++.h>using namespace std;const int maxn=1000;const int alphanumber=26;typedef struct {    int weight;    int parent,lchild,rchild;}HufNode;//HuffmanTree的基本定义typedef struct {    int weight;    char data;    char code[maxn];//需要被建树的信息}HufCode;void Init(HufCode h[])//初始化输入数据{    FILE *f1=fopen("DataFile.data","r");    for(int i=0;i<alphanumber;++i)        fscanf(f1,"%c%d ",&h[i].data,&h[i].weight);    fclose(f1);}void select(HufNode *h,int k,int &s1,int &s2)//选择两个最小的值{    int i;    for(i=0; i<k && h[i].parent != 0; ++i);//选择一个父节点为0的根节点        s1 = i;    for(i=0; i<k; ++i){        if(h[i].parent==0 && h[i].weight<h[s1].weight)              s1 = i;    }    for(i=0; i<k; ++i){        if(h[i].parent==0 && i!=s1)            break;    }    s2 = i;    for(i=0; i<k; ++i){        if(h[i].parent==0 && i!=s1 && h[i].weight<h[s2].weight)            s2 = i;    }}void HuffmanTree(HufCode *h2,HufNode *h1,int n){    char str[maxn];    int m=2*n-1;    for(int i=0;i<m;++i){        if(i<n)//前n个全部是叶子节点,            h1[i].weight=h2[i].weight;        else//后面的是还没建成的树            h1[i].weight==0;        h1[i].lchild=h1[i].parent=h1[i].rchild=0;    }    int s1,s2;    for(int i=n;i<m;++i){        select(h1,i,s1,s2);        h1[s1].parent=i;//建立二叉树        h1[s2].parent=i;        h1[i].lchild=s1;        h1[i].rchild=s2;        h1[i].weight=h1[s1].weight+h1[s2].weight;    }    str[n]='\0';    int l;    for(int i=0;i<n;++i){//从每个叶子节点开始倒序遍历        l=n-1;//倒序赋值字符串        for(int k=i,p=h1[k].parent;p;k=p,p=h1[k].parent){//沿着叶子回溯到根节点            if(k==h1[p].lchild)                str[l]='0';            else                str[l]='1';            l--;        }        strcpy(h2[i].code,str+l+1);       // printf("%c %s\n",h2[i].data,h2[i].code);    }}void EnCodeing(HufCode hc[]){    FILE *f1=fopen("ToBeTran.data","r");    FILE *f2=fopen("Code.txt","w");    char str[maxn];    while(fscanf(f1,"%s",str)!=EOF)    {        int len=strlen(str);        for(int i=0;i<len;++i){            int x=str[i]-'a';            fprintf(f2,"%s",hc[x].code);        }        fprintf(f2," ");    }    fclose(f1);    fclose(f2);}int Search(HufCode hc[],char *str){    for(int i=0;i<alphanumber;++i)        if(strcmp(hc[i].code,str)==0)            return  i;    return -1;}void DeCodeing(HufCode hc[]){    FILE *f1=fopen("CodeFile.data","r");    FILE *f2=fopen("Textfile.txt","w");    char str[maxn];    while(fscanf(f1,"%s",str)!=EOF)    {        char a[maxn];        memset(a,'\0',sizeof(a));        int len=strlen(str),k=0;        for(int i=0;i<len;++i){            a[k]=str[i];            a[k+1]='\0';            int ans=Search(hc,a);            if(ans!=-1){                fprintf(f2,"%c",ans+'a');                k=0;                continue;            }            k++;        }        fprintf(f2," ");    }    fclose(f1);    fclose(f2);}void OutPut(){    FILE *infile=fopen("DataFile.data","r");    FILE *outfile=fopen("Code.txt","r");    int w;    char c;    printf("各个字母及其权值\n");    for(int i=0;i<alphanumber;++i){        fscanf(infile,"%c %d ",&c,&w);        printf("%c %d ",c,w);    }    infile=fopen("ToBeTran.data","r");    printf("\n\n待编码的内容:\n");    char str[maxn];    while(fscanf(infile,"%s",str)!=EOF)        printf("%s ",str);    printf("\n编码后结果:\n");    while(fscanf(outfile,"%s",str)!=EOF)        printf("%s ",str);    printf("\n\n待解码内容:\n");    infile=fopen("CodeFile.data","r");    while(fscanf(infile,"%s",str)!=EOF)        printf("%s ",str);    printf("\n解码结果:\n");    outfile=fopen("Textfile.txt","r");    while(fscanf(outfile,"%s",str)!=EOF)        printf("%s ",str);    printf("\n");    fclose(infile);    fclose(outfile);}int main(){    HufCode hc[maxn];    HufNode tree[maxn];    Init(hc);//初始化    HuffmanTree(hc,tree,alphanumber);//建树    EnCodeing(hc);//编码    DeCodeing(hc);//解码    OutPut();//输出结果    return 0;}
原创粉丝点击