logo资料库

Huffman编码对英文文本的压缩和解压缩.doc

第1页 / 共17页
第2页 / 共17页
第3页 / 共17页
第4页 / 共17页
第5页 / 共17页
第6页 / 共17页
第7页 / 共17页
第8页 / 共17页
资料共17页,剩余部分请下载后查看
Huffman 编码对英文文本的压缩和解压缩 中国地质大学计算机学院信息安全专业 信息论实验报告 #include #include #include 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; /* 将 每 个 哈 夫 曼 码 值 及 其 对 应 的 存放在一维数组 header[i]中,且编码 中的下标和 ASCII 码满足顺序存放关 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].count
header[i]=header[j]; header[j]=tmp; } } } for(i=0;i<256;i++) //找到第一个空的 header 结点 if(header[i].count==0) break; n=i; m=2*n-1; for(i=n;iheader[j].count){ pt1=j; min1=header[j].count; continue;
} } header[i].count=header[pt1].count; header[pt1].parent=i; header[i].lch=pt1; min1=999999999; for(j=0;jheader[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
while(header[f].parent!=-1){ j=f; f=header[f].parent; if(header[f].lch==j){ //置左分支编码 0 j=strlen(header[i].bits); memmove(header[i].bits+1,header[i].bits,j+1); //依次存储连接"0""1"编码,此处语句为网络借鉴 header[i].bits[0]='0'; } else{ //置右分支编码 1 j=strlen(header[i].bits); memmove(header[i].bits+1,header[i].bits,j+1); header[i].bits[0]='1'; } } } fseek(ifp,0,SEEK_SET); //从文件开始位置向前移动 0 字节,即 定位到文件开始位置 fwrite(&flength,sizeof(int),1,ofp); /*用来将数据写入文件流 中,参数 flength 指向欲写入的数据地址,总共写入的字符数 以参数 size*int 来决定,返回实际写入的 int 数目*/
fseek(ofp,8,SEEK_SET); buf[0]=0; //定义缓冲区,它的二进制表示 00000000 f=0; pt1=8; /* 假 设 原 文 件 第 一 个 字 符 是 "A" , 8 位 2 进 制 为 01000001, 位并没有 下 如果 编码后为 0110 识别编码第一个'0',那么将其左移一位, 看起来没什么变化。下一个是'1',应该|1,结果 00000001 同理 4 位都做完,应该是 00000110,由于字节中的 8 全部用完,继续读下一个字符,根据编码表继续拼完剩 4 位,如果字符的编码不足 4 位,还要继续读一个字符, 字符编码超过 4 位,那么把剩下的位信息拼接到一个新 的字节里*/ while(!feof(ifp)){ c=fgetc(ifp); f++; for(i=0;i
} 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++){ //逐位输入八位前的二进制符
分享到:
收藏