当前位置:文档之家› 河北工业大学-数据结构实验报告-基于哈夫曼编码的通信系统的设计与实现

河北工业大学-数据结构实验报告-基于哈夫曼编码的通信系统的设计与实现

基于哈夫曼编码的通信系统的设计与实现一、实验目的(1)掌握二叉树的存储结构及其相关操作。

(2)掌握构造哈夫曼树的基本思想,及其编码/译码过程。

二、实验内容利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。

但是,这要求在发送端通过一个编码系统对待传输数据预先编码,在接收端将传来的数据进行译码。

对于双工信道,每端都需要一个完整的编/译码系统。

试为这样的信息收发站设计一个基于哈夫曼编码的通信系统。

一个完整的系统应具有以下功能1)初始化处理:建立通信系统(1)建立有100句中文的信息集合,每个句子称为一条信息。

(2)输入编码参数:①从终端输入编码字符集大小n,字符编码长度m(设n为4,m为8);②从终端输入编码字符(设为A,B,C,D);(3)生成每条信息的字符编码,构造字符编码集合;(4)计算每个字符编码集合中出现的概率;(5)根据字符概率构造哈夫曼树,求出每个字符的二进制编码。

2)发送端信息编码(1)用户从信息集合中选择一条信息,找到该信息对应的字符编码;(2)根据该信息的字符编码,哈夫曼树求出的每个字符的二进制编码,构造出该信息的二进制编码,记录二进制比编码。

3)接受端信息译码(1)根据得到的信息的二进制编码,利用哈夫曼树求出每个字符的二进制编码还原出信息的字符编码;(2)根据信息的字符编码,找到对应的信息。

三、源程序代码#include<stdio.h>#include<malloc.h>#include<stdlib.h>char *codechar;int ncodechar,lcodechar;int *arraychar[100];char *temp;float *proba;char pass[50];int passl;struct node{float pro;int num;struct node* p;struct node* lc;struct node* rc;char *res;int length;}*hc;char message[100][20]={{"人之初"}, {"性本善"}, {"性相近"}, {"习相远"}, {"苟不教"}, {"性乃迁"},{"教之道"}, {"贵以专"}, {"昔孟母"}, {"择邻处"}, {"子不学"}, {"断机杼"},{"窦燕山"}, {"有义方"}, {"教五子"}, {"名俱扬"}, {"养不教"}, {"父之过"},{"教不严"}, {"师之惰"}, {"子不学"}, {"非所宜"}, {"幼不学"}, {"老何为"},{"玉不琢"}, {"不成器"}, {"人不学"}, {"不知义"}, {"为人子"}, {"方少时"},{"亲师友"}, {"习礼仪"}, {"香九龄"}, {"能温席"}, {"孝于亲"}, {"所当执"},{"融四岁"}, {"能让梨"}, {"弟于长"}, {"宜先知"}, {"首孝弟"}, {"次见闻"},{"知某数"}, {"识某文"}, {"一而十"}, {"十而百"}, {"百而千"}, {"千而万"},{"三才者"}, {"天地人"}, {"三光者"}, {"日月星"}, {"三纲者"}, {"君臣义"},{"父子亲"}, {"夫妇顺"}, {"曰春夏"}, {"曰秋冬"}, {"此四时"}, {"运不穷"},{"曰南北"}, {"曰西东"}, {"此四方"}, {"应乎中"}, {"曰水火"}, {"木金土"},{"此五行"}, {"本乎数"}, {"曰仁义"}, {"礼智信"}, {"此五常"}, {"不容紊"},{"稻粱菽"}, {"麦黍稷"}, {"此六谷"}, {"人所食"}, {"马牛羊"}, {"鸡犬豕"},{"此六畜"}, {"人所饲"}, {"曰喜怒"}, {"曰哀惧"}, {"爱恶欲"}, {"七情具"},{"匏土革"}, {"木石金"}, {"丝与竹"}, {"乃八音"}, {"高曾祖"}, {"父而身"},{"身而子"}, {"子而孙"}, {"自子孙"}, {"至玄曾"}, {"乃九族"}, {"人之伦"},{"父子恩"}, {"夫妇从"}, {"兄则友"}, {"弟则恭"}} ;int zifushengcheng();int probability();int huffman();int Exchange(struct node *a,struct node *b);int Exchangenum(int *a,int *b);int Exchangepoint(struct node **a,struct node ** b);int produce(struct node *a,int *b);int sent();int receive();int main(){int i;char t;printf("初始化通讯系统:\n请输入编码字符集大小n,字符编码长度m(以n m格式来输入):\n");scanf("%d %d",&ncodechar,&lcodechar);codechar=(char *)malloc(sizeof(char)*ncodechar);proba=(float *)malloc(sizeof(float)*ncodechar);for(i=0;i<ncodechar;i++){proba[i]=0;}for(i=0;i<100;i++){arraychar[i]=(int *)malloc(sizeof(int )*lcodechar);}hc=(struct node*)malloc(sizeof(struct node)*(ncodechar*2-1));temp=(char *)malloc(sizeof(char)*(ncodechar));printf("请输入编码字符(以A B C D的格式来输入):\n");for(i=0;i<ncodechar;i++){scanf("%c",&t);if(t=='\n'||t==' '){i--;continue;}codechar[i]=t;}zifushengcheng();probability();huffman();sent();receive();return 1;}int sent(){int i,j,k,x;printf("\n--------------------------------发送方------------------------------------\n");for(i=0;i<100;i++){printf("%d:",i+1);for(j=0;j<20;j++){printf("%c",message[i][j]);}printf(" 相应的字符编码:");for(k=0;k<lcodechar;k++){printf("%c",codechar[arraychar[i][k]]);}printf("\n");}printf("请从以上100条信息中选择发送的信息,输入你的信息号:");scanf("%d",&x);printf("你选择发送的信息是:");for(j=0;j<20;j++){printf("%c",message[x-1][j]);}printf("\n相应的字符编码是:");for(i=0;i<lcodechar;i++){printf("%c",codechar[arraychar[x-1][i]]);}printf("\n根据哈夫曼树得到的哈夫曼编码是:");for(i=0;i<lcodechar;i++){for(j=0;j<ncodechar*2-1;j++){if(arraychar[x-1][i]==hc[j].num){for(k=0;k<hc[j].length;k++){printf("%c",hc[j].res[k]);pass[passl]=hc[j].res[k];passl++;}}}}return 1;}int receive(){int i,j,k=0,m;int *get=(int *)malloc(sizeof(int)*lcodechar);printf("\n--------------------------------接收方------------------------------------\n接收到的哈夫曼编码是:");for(i=0;i<passl;i++){printf("%c",pass[i]);}i=0;while(i!=lcodechar){for(j=0;(j<ncodechar*2-1);j++){for(m=0;m<hc[j].length;m++,k++){if(hc[j].res[m]!=pass[k]){break;}}if(m==hc[j].length){get[i]=hc[j].num;i++;break;}k=k-m;}}printf("\n根据哈夫曼树转换出的字符编码为:\n");for(i=0;i<lcodechar;i++){printf("%c",codechar[get[i]]);}for(i=0;i<100;i++){for(j=0;j<lcodechar;j++){if(get[j]!=arraychar[i][j])break;}if(j==lcodechar){printf("\n字符编码转换后得到的信息是:\n");for(k=0;k<20;k++){printf("%c",message[i][k]);}break;}}printf("\n接收结束,谢谢使用!");return 1;}int zifushengcheng(){int i,j=0,k=0,yushu,x;int *b[100];for(i=0;i<100;i++){b[i]=(int *)malloc(sizeof(int)*lcodechar);for(j=0;j<lcodechar;j++){b[i][j]=0;}for(i=0;i<100;i++){x=i;do{yushu=x%ncodechar;x=(int)(x/ncodechar);b[i][j]=yushu;j++;}while(x!=0);for(j=ncodechar-1;j>=0;j--,k++){arraychar[i][k]=b[i][j];}j=0;k=0;}for(i=0;i<100;i++){for(j=ncodechar;j<lcodechar;j++){arraychar[i][j]=rand()%ncodechar;}}/*for(i=0;i<100;i++){for(j=0;j<lcodechar;j++){printf("%d ",arraychar[i][j]);}printf(" ");for(j=0;j<lcodechar;j++){printf("%c",codechar[arraychar[i][j]]);}printf("\n");}*/return 1;}int probability(){for(i=0;i<100;i++){for(j=0;j<lcodechar;j++){for(k=0;k<ncodechar;k++){if(arraychar[i][j]==k){proba[k]++;}}}}printf("随机生成的字符编码概率:\n");for(i=0;i<ncodechar;i++){proba[i]=proba[i]/(100*lcodechar);printf("%c:%f ",codechar[i],proba[i]);}return 1;}int huffman(){int i,j,k,l=0;for(i=0;i<(ncodechar*2-1);i++){hc[i].lc=NULL;hc[i].rc=NULL;hc[i].p=NULL;hc[i].num=i;if(i<ncodechar){hc[i].pro=proba[i];continue;}hc[i].pro=0;}for(i=0;i<ncodechar-1;i++){for(j=i*2;j<(ncodechar+i);j++){for(k=j+1;k<(ncodechar+i);k++){if(hc[k].pro<hc[j].pro&&hc[k].pro!=0){Exchange(&hc[k],&hc[j]);}}}hc[i+ncodechar].pro=hc[i*2].pro+hc[i*2+1].pro;hc[i+ncodechar].lc=&hc[i*2];hc[i+ncodechar].rc=&hc[i*2+1];hc[i*2].p=&hc[i+ncodechar];hc[i*2+1].p=&hc[i+ncodechar];}printf("\n构造的哈夫曼树:");for(i=0;i<ncodechar*2-1;i++){printf("\nchar:%c num:%d pro:%f",codechar[hc[i].num],hc[i].num,hc[i].pro);printf(" lc:");if(hc[i].lc==NULL){printf(" ");}else{printf("%d,",hc[i].lc->num);}printf(" rc:");if(hc[i].rc==NULL){printf(" ");}else{printf("%d,",hc[i].rc->num);}printf(" p:");if(hc[i].p==NULL){printf(" ");}else{printf("%d,",hc[i].p->num);}}produce(&hc[ncodechar*2-2],&l);printf("\n生成的哈夫曼编码是:");for(i=0;i<ncodechar*2-1;i++){printf("\nchar:%c num:%d length:%d code:",codechar[hc[i].num],hc[i].num,hc[i].length);for(j=0;j<hc[i].length;j++){printf("%c",hc[i].res[j]);}}return 1;}int produce(struct node*a,int *b){int i;a->length=(*b);a->res=(char *)malloc(sizeof(char)*(*b));for(i=0;i<(*b);i++){a->res[i]=temp[i];}if(a->lc!=NULL&&a->rc!=NULL){temp[(*b)]='0';(*b)++;produce((a->lc),b);temp[(*b)]='1';(*b)++;produce((a->rc),b);}(*b)--;return 1;}int Exchange(struct node*a,struct node*b){float t;t=a->pro;a->pro=b->pro;b->pro=t;Exchangenum(&a->num,&b->num);Exchangepoint(&a->p,&b->p);Exchangepoint(&a->lc,&b->lc);Exchangepoint(&a->rc,&b->rc);return 1;}int Exchangepoint(struct node **a,struct node ** b) {struct node *t;t=*a;*a=*b;*b=t;return 1;}int Exchangenum(int *a,int *b){int t;t=*a;*a=*b;*b=t;return 1;}参考至《百度文库》四、结果分析本次实验是学习编程以来接触的最大程序,参考了较多相关源文件,对c语的函数引用有了更深刻的了解,初步掌握了二叉树的存储结构及其相关操作。

相关主题