Huffman编码对英文文本的压缩和解压缩Word格式文档下载.doc
《Huffman编码对英文文本的压缩和解压缩Word格式文档下载.doc》由会员分享,可在线阅读,更多相关《Huffman编码对英文文本的压缩和解压缩Word格式文档下载.doc(17页珍藏版)》请在冰豆网上搜索。
longmin1,pt1,flength=0,length1,length2;
//记录最小结点、文件长度
doublediv;
//计算压缩比用
FILE*ifp,*ofp;
//分别为输入、输出文件指针
printf("
\t请您输入需要压缩的文件(需要路径):
"
);
gets(filename);
ifp=fopen(filename,"
rb"
if(ifp==NULL){
printf("
\n\t文件打开失败!
\n"
system("
pause"
return;
}
\t请您输入压缩后的文件名(如无路径则默认为桌面文件):
gets(outputfile);
ofp=fopen(outputfile,"
wb"
if(ofp==NULL){
\n\t压缩文件失败!
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=(unsignedchar)i;
/*将每个哈夫曼码值及其对应的ASCII码
存放在一维数组header[i]中,且编码表
中的下标和ASCII码满足顺序存放关系*/
else
header[i].b=0;
header[i].parent=-1;
header[i].lch=header[i].rch=-1;
//对结点进行初始化
}
256;
i++){ //按出现权值从大到小排序
for(j=i+1;
j<
j++){
if(header[i].count<
header[j].count){
tmp=header[i];
header[i]=header[j];
header[j]=tmp;
}
}
i++) //找到第一个空的header结点
if(header[i].count==0)
break;
n=i;
m=2*n-1;
for(i=n;
m;
min1=999999999;
//预设的最大权值,即结点出现的最大次数
for(j=0;
i;
if(header[j].parent!
=-1)
continue;
/*parent!
=-1说明该结点已存在哈夫曼
树中,跳出循环重新选择新结点*/
if(min1>
pt1=j;
min1=header[j].count;
}
header[i].count=header[pt1].count;
header[pt1].parent=i;
header[i].lch=pt1;
header[i].count+=header[pt1].count;
header[i].rch=pt1;
//哈夫曼无重复前缀编码
n;
f=i;
header[i].bits[0]=0;
//根结点编码0
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
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识别编码第一个'
,那么将其左移一位,
看起来没什么变化。
下一个是'
,应该|1,结果00000001
同理4位都做完,应该是00000110,由于字节中的8位并没有
全部用完,继续读下一个字符,根据编码表继续拼完剩下
4位,如果字符的编码不足4位,还要继续读一个字符,如果
字符编码超过4位,那么把剩下的位信息拼接到一个新的字节里*/
c=fgetc(ifp);
f++;
for(i=0;
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;
8;
if(buf[i]=='
)
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)
if(j>
0){ //最后不满八位的buf处理
strcat(buf,"
00000000"
//buf后加八位0
i++){ //逐位输入八位前的二进制符
if(buf[i]=='
c=(c<
else
c=c<
fwrite(&
pt1++;
fseek(ofp,4,SEEK_SET);
//指针回到输出文件头部后面四位
pt1,sizeof(long),1,ofp);
//pt1统计了输出文件中的字符个数,包括了最后的'
/0'
fseek(ofp,pt1,SEEK_SET);
n,sizeof(long),1,ofp);
//n统计了权值不为0的header[]数量
(header[i].b),1,1,ofp);
//依次写入每个叶子结点的b、长度和内容
c=strlen(header[i].bits);
j=strlen(header[i].bits);
if(j%8!
=0){ //若存储的位数不是8的倍数,则补0
for(f=j%8;
f<
f++)
strcat(header[i].bits,"
while(header[i].bits[0]!
=0){ /*字符的有效存储不超过8位,则对
有效位数左移实现两字符编码的连接,
可理解为前缀编码也被压缩过*/
c=0;
for(j=0;
if(header[i].bits[j]=='
)
strcpy(header[i].bits,header[i].bits+8);
//以上与上面连接字符一段可相同理解
length2=pt1--;
div=((double)length1-(double)length2)/(double)length1;
//计算文件的压缩率
fclose(ifp);
fclose(ofp);
\n\t压缩文件成功!
\n"
\t压缩率为%f%%