数据结构与程序设计专题实验报告:学号:班级:信息45班:学号:班级:信息45班:学号:班级:信息45班实验指导老师:峰实验地点:西一楼一层计算机中心机房实验结束日期:12月5日联系:一.实验任务:对于给定的源文档 SourceDoc.txt,1) 统计其中所有字符的频度(某字符的频度等于其出现的总次数除以总字符数),字符包括字母(区分大小写)、标点符号及格式控制符(空格、回车等)。
2) 按频度统计结果构建哈夫曼编码表。
3) 基于哈夫曼编码表进行编码,生成对应的二进制码流,并输出到文件 Encode.dat,完成信源的编码过程。
4) 根据生成的哈夫曼编码表,对二进制码流文件 Encode.dat 进行解码,把结果输出到文件 TargetDoc.txt,完成信源的解码过程。
5) 判断 TargetDoc.txt 与 SourceDoc.txt 容是否一致,以验证编解码系统的正确性。
二.实验容:1) 线性链表的构建以及排序;2) 哈夫曼树的构建;3) 基于哈夫曼码进行编码;4) 对二进制码进行解码;5)对生成文件与原文件进行比较;三.程序的算法描述四.程序运行结果:五.源程序代码:#include<stdio.h>#include<stdlib.h>#include<math.h>#include <string.h> typedef struct aa {char data;double rate;int count;struct aa *next;struct aa *pre;char haffmancode[120]; }NODE;NODE *creat(char b[]){ NODE *h, *p, *s,*death;int i;h=(NODE*)malloc(sizeof(NODE));p=(NODE*)malloc(sizeof(NODE)); h->next=p;h->pre=NULL;p->pre=h;p->next=NULL;p->data=b[0]; p->count=1.0;for(i=1;b[i]!='\0';i++){s=(NODE*)malloc(sizeof(NODE));s->data=b[i]; s->count=1.0;s->next=NULL; s->pre=p;p->next=s;p=s;}return h;}void fun(NODE* h,int amount){ NODE *p,*q,*death;for(p=h->next;p;p=p->next){for(q=p->next;q;){if(q->data==p->data){(p->count)++;if (q->next == NULL){q->pre->next = NULL;free(q);break;}else{ q->pre->next=q->next;q->next->pre=q->pre;death=q; q=q->next;free(death);}}else q=q->next;}(p->rate)=1.0*(p->count)/amount;//printf("%c:\t%d\t%f\n",p->data,p->count,p->rate); }puts("构建链表完成\n");}void outlink(NODE* h,int *n){//printf("%d",amount);NODE* p=(NODE*)malloc(sizeof(NODE)); NODE* s=(NODE*)malloc(sizeof(NODE));int i;char ch;double r;for(p=h->next;p;p=p->next){for(s=p->next;s;s=s->next){if(s->count > p->count){i=p->count;p->count=s->count;s->count=i;ch=p->data;p->data=s->data;s->data=ch;r=p->rate;p->rate=s->rate;s->rate=r;}}}p=h->next;while(p){//printf("%c:\t%d\t%f\n",p->data,p->count,p->rate); (*n)++;p=p->next;}puts("排序完成\n");}typedef struct{NODE body;int lchild,rchild,parent;struct Treenode *next;}HTNode, *Tree;typedef char **Huffmancode;void select(Tree &HT,int n,int & s1,int &s2){int i,j;for(i = 1;i <= n;i++)if(!HT[i].parent){s1 = i;break;}for(j = i+1;j <= n;j++)if(!HT[j].parent){s2 = j;break;}for(i = 1;i <= n;i++)if((HT[s1].body.rate>HT[i].body.rate)&&(!HT[i].parent)&&(s2!=i)) s1=i;for(j = 1;j <= n;j++)if((HT[s2].body.rate>HT[j].body.rate)&&(!HT[j].parent)&&(s1!=j)) s2=j;}void Huffmancoding(Tree &HT, Huffmancode &HC, int n,NODE *head,int *wei){HTNode *p;int m=2*n-1,i;int s1,s2;NODE *L=head->next;HT=(Tree)malloc((m+1)*sizeof(HTNode));for(p=HT+1,i=1;i<=n;i++,p++){p->body=*L;L=L->next;p->lchild=0; p->parent=0; p->rchild=0;}for(;i<=m;p++,i++){p->body.rate=0; p->lchild=0; p->parent=0; p->rchild=0;}for(i=n+1;i<=m;i++){select(HT,i-1,s1,s2);HT[s1].parent=i; HT[s2].parent=i; HT[i].lchild=s1;HT[i].rchild=s2; HT[i].body.rate=HT[s1].body.rate+HT[s2].body.rate;} for(i=n+1;i<=m;i++){if(HT[i].parent==0){*wei=i;}}HC=(Huffmancode)malloc((n+1)*sizeof(char *));char * temp=(char *)malloc(n*sizeof(char));temp[n-1]='\0';for(i=0;i<n;i++){int start=n-1;for(int f=HT[i].parent,h=i;f;h=f,f=HT[f].parent){if(HT[f].lchild==h){temp[--start]='0';}else{temp[--start]='1';}}//HC[i]=(char *)malloc((n-start)*sizeof(char));strcpy(HT[i].body.haffmancode,&temp[start]);}free(temp);FILE *fw;fw=fopen("Statistic.txt","wt");for(i=1;i<n;i++){fprintf(fw,"%c:\t%d\t%f\t%s\n",HT[i].body.data,HT[i].body.count,HT[i] .body.rate,HT[i].body.haffmancode);}puts("哈夫曼编码完成,Statistic.txt文件生成完毕\n");fclose(fw);}void putdat(NODE* h,FILE *fp,FILE *ft,FILE *fw,Tree &HT,int *wei,int *nc){char qq[10000]={0};int t[10000]={0};int i=0,j=0,n=0,last=*nc;rewind(fp);char pp[10000]={0};//strcpy(pp,"\0");NODE *L=h->next;while(L){i=0;while(i<last){if(L->data==HT[i].body.data)strcpy(L->haffmancode,HT[i].body.haffmancode);i++;}L=L->next;}char cp=fgetc(fp);while(cp!=EOF){L=h->next;while(cp!=L->data)L=L->next;strcat(pp,L->haffmancode);cp=fgetc(fp);}//printf("%s\n\n",pp);i=0;while(pp[i]!='\0'){n=0;while(n<15&&pp[i]!='\0'){if(pp[i]=='1'){t[j]=t[j]|1;}if(n!=14&&pp[i+1]!='\0'){t[j]=t[j]<<1;} n++;i++;}if(pp[i]=='\0'){t[j+1]=0;last=n;break;}j++;}//for(;t[n]!=0;n++);//itoa(t[0],string,2);printf("string=%s\n",string);fwrite(&t[0],sizeof(char),j-1,fw);i=0;j=0;while(t[j+1]!='\0'){n=14;while(n>=0){double a=pow(2,n);if((t[j]&(int)a)==(int)a){qq[i]='1';}else {qq[i]='0';}n--;i++;}j++;}n=last-1;while(n>=0){double a=pow(2,n);if((t[j]&(int)a)==(int)a)qq[i]='1';else qq[i]='0';n--;i++;}qq[i]='\0';//printf("%s",qq);int root=*wei;char c;i=0;while(qq[i]!='\0'){ c=qq[i];if(qq[i]=='0'){root=HT[root].lchild;}else{root=HT[root].rchild;}if(HT[root].rchild==0&&HT[root].lchild==0){ fprintf(ft,"%c",HT[root].body.data);root=*wei;}i++;}puts("解码完成,Target.txt文件生成\n"); }bool compare(FILE *fp,FILE *ft){rewind(fp);char ch1=fgetc(fp);char ch2=fgetc(ft);while(ch1!=EOF&&ch2!=EOF){if(ch1!=ch2)break;ch1=fgetc(fp);ch2=fgetc(ft);}return ch1==ch2&&ch1==EOF? true:false; }int main(){ FILE *fp;char ch;intt=0;char b[10000];if((fp=fopen("source.txt","rt"))==NULL) {printf("\ncan not open file");return 0;}ch=fgetc(fp);while(ch!=EOF){ch=fgetc(fp);b[cnt] = ch;t ++;}FILE *fw;fw=fopen("Encode.dat","wb");if(!fw){printf("NO SPACE %s\n");return 0;}int amount=strlen(b);int n=0,m=2*n-1,i;NODE *head;head=creat(b);fun(head,amount);outlink(head,&n);Tree HT;char **HC;float temp;int wei;HT=(Tree)malloc((m+1)*sizeof(HTNode));HC=(Huffmancode)malloc((n)*sizeof(char *)); Huffmancoding(HT,HC,n,head,&wei);FILE *ft;ft=fopen("Target.txt","wt");if(!ft){printf("NO SPACE FOR Target.txt");return 0;}putdat(head,fp,ft,fw,HT,&wei,&n);fclose(ft);fclose(fp);if(!ft){printf("NO SPACE FOR Target.txt");return 0;}fclose(ft);FILE *ftnew;ftnew=fopen("TargetDoc.txt","rt+");bool result=compare(fp,ftnew);if(result==true){puts("目标文件与原文件一致\n");}elseputs("目标文件与原文件不一致\n");fclose(ftnew);system("pause");return 0;}六.实验总结:从程序的编写来看,感觉这次自己真的学到了好多,特别是对程序的开发流程。