Huffman编码对英文文本的压缩和解压缩中国地质大学计算机学院信息安全专业信息论实验报告#include #include #include <conio.h>struct head {ﻩunsigned char b; ﻩ ﻩﻩ //记录字符在数组中的位置ﻩlong count;ﻩ ﻩﻩ ﻩ //字符浮现频率(权值) ﻩlong parent,lch,rch; ﻩ ﻩ//定义哈夫曼树指针变量ﻩchar bits[256];ﻩﻩﻩﻩ //定义存储哈夫曼编码的数组 }header[512],tmp;void compress() {ﻩchar filename[255],outputfile[255],buf[512]; unsigned char c; ﻩlong n,m,i,j,f; ﻩ ﻩﻩ ﻩ //作计数或临时存储数据用 long min1,pt1,flength=0,length1,length2; //记录最小结点、文献长度ﻩdouble div;ﻩﻩ //计算压缩比用ﻩFILE *ifp,*ofp; ﻩﻩﻩ //分别为输入、输出文献指针ﻩprintf("\t请您输入需要压缩的文献(需要途径):"); gets(filename); ﻩifp=fopen(filename,"rb"); ﻩif(ifp==NULL){ﻩﻩprintf("\n\t文献打开失败!\n "); ﻩﻩsystem("pause"); ﻩ ﻩreturn; } printf("\t请您输入压缩后的文献名(如无途径则默觉得桌面文献):"); gets(outputfile); ﻩofp=fopen(outputfile,"wb"); if(ofp==NULL){ printf("\n\t压缩文献失败!\n "); ﻩ system("pause"); ﻩﻩreturn; } flength=0; ﻩwhile(!feof(ifp)){ ﻩfread(&c,1,1,ifp); header[c].count++;ﻩ ﻩﻩ //字符反复浮现频率+1 ﻩflength++; ﻩ ﻩ//字符浮现原文献长度+1ﻩ}ﻩflength--; ﻩlength1=flength; ﻩ ﻩ//原文献长度用作求压缩率的分母 header[c].count--; ﻩfor(i=0;i<512;i++){ﻩ if(header[i].count!=0) ﻩ header[i].b=(unsigned char)i; ﻩﻩﻩ ﻩ/*将每个哈夫曼码值及其相应的ASCII码ﻩﻩ ﻩ ﻩﻩﻩﻩ寄存在一维数组header[i]中,且编码表ﻩ ﻩﻩﻩﻩﻩ 中的下标和ASCII码满足顺序寄存关系*/ﻩ else ﻩﻩﻩheader[i].b=0; ﻩﻩheader[i].parent=-1;header[i].lch=header[i].rch=-1; //对结点进行初始化 } for(i=0;i<256;i++){ ﻩﻩ //按浮现权值从大到小排序 ﻩfor(j=i+1;j<256;j++){ﻩ if(header[i].countheader[j].count){ﻩﻩ pt1=j; ﻩﻩﻩﻩmin1=header[j].count; ﻩﻩﻩcontinue; ﻩ} ﻩ } header[i].count+=header[pt1].count; ﻩheader[i].rch=pt1; ﻩﻩheader[pt1].parent=i; ﻩ //哈夫曼无反复前缀编码ﻩ} for(i=0;i
下一种是'1',应当|1,成果00000001 ﻩﻩﻩ 同理4位都做完,应当是00000110,由于字节中的8位并没有 ﻩ所有用完,继续读下一种字符,根据编码表继续拼完剩余 ﻩﻩ 4位,如果字符的编码局限性4位,还要继续读一种字符,如果 ﻩ 字符编码超过4位,那么把剩余的位信息拼接到一种新的字节里*/ while(!feof(ifp)){ﻩ c=fgetc(ifp); f++; ﻩfor(i=0;i<n;i++){ﻩﻩﻩﻩﻩ//找到相应的header[i]ﻩ ﻩif(c==header[i].b) ﻩ break; ﻩ} strcat(buf,header[i].bits); ﻩﻩj=strlen(buf);ﻩ c=0; ﻩwhile(j>=8){ﻩ for(i=0;i<8;i++){ﻩﻩ if(buf[i]=='1') ﻩﻩ ﻩﻩc=(c<<1)|1;ﻩ ﻩ//添加最后一位为1 ﻩﻩelse ﻩ ﻩ c=c<<1;ﻩﻩﻩ //添加最后一位为0ﻩﻩﻩ} ﻩfwrite(&c,1,1,ofp); ﻩﻩpt1++; ﻩ strcpy(buf,buf+8); ﻩ ﻩj=strlen(buf); ﻩﻩ ﻩ ﻩ ﻩ ﻩ}ﻩﻩif(f==flength) ﻩ ﻩbreak; ﻩ} if(j>0){ ﻩﻩ ﻩﻩ //最后不满八位的buf解决 ﻩstrcat(buf,"00000000"); ﻩ //buf后加八位0 for(i=0;i<8;i++){ ﻩﻩ//逐位输入八位前的二进制符 if(buf[i]=='1') ﻩﻩﻩc=(c<<1)|1; ﻩ else ﻩﻩﻩc=c<<1; }ﻩﻩfwrite(&c,1,1,ofp); ﻩﻩpt1++; } fseek(ofp,4,SEEK_SET); ﻩﻩﻩﻩ//指针回到输出文献头部背面四位 fwrite(&pt1,sizeof(long),1,ofp); ﻩ//pt1记录了输出文献中的字符个数,涉及了最后的'/0' fseek(ofp,pt1,SEEK_SET); ﻩfwrite(&n,sizeof(long),1,ofp);ﻩﻩﻩﻩ//n记录了权值不为0的header[]数量 for(i=0;i