霍夫曼编码对英文文本的压缩和解压缩Word格式.docx
- 文档编号:6727138
- 上传时间:2023-05-07
- 格式:DOCX
- 页数:13
- 大小:18.64KB
霍夫曼编码对英文文本的压缩和解压缩Word格式.docx
《霍夫曼编码对英文文本的压缩和解压缩Word格式.docx》由会员分享,可在线阅读,更多相关《霍夫曼编码对英文文本的压缩和解压缩Word格式.docx(13页珍藏版)》请在冰点文库上搜索。
);
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%%\n\n"
div*100);
return;
}
voiduncompress(){
charfilename[255],outputfile[255],buf[255],bx[255];
longi,j,m,n,f,p,l;
longflength;
\t请您输入需要解压缩的文件(如无路径则默认为桌面文件):
\t请您输入解压缩后的文件名:
\n\t解压缩文件失败!
fread(&
flength,sizeof(long),1,ifp);
//读入文件长度flength
f,sizeof(long),1,ifp);
//读入header数组的存储地址
fseek(ifp,f,SEEK_SET);
n,sizeof(long),1,ifp);
//读入header数组中元素的个数
i++){//读入header数组
header[i].b,1,1,ifp);
p=(long)c;
header[i].count=p;
if(p%8>
0)
m=p/8+1;
m=p/8;
fread(&
f=c;
itoa(f,buf,2);
/*此处借鉴网络程序,包括itoa()函数
itoa()函数的作用为,把int型的f
化为二进制数,再变成char型存入buf*/
f=strlen(buf);
for(l=8;
l>
f;
l--){//在单字节内对相应位置补0
strcat(header[i].bits,buf);
header[i].bits[p]=0;
i++){//按Huffman编码从小到大排序
if(strlen(header[i].bits)>
strlen(header[j].bits)){
p=strlen(header[n-1].bits);
fseek(ifp,8,SEEK_SET);
m=0;
bx[0]=0;
while
(1){//对文件其余部分,即真正的文件部分解压缩
while(strlen(bx)<
(unsignedint)p){
l--){
strcat(bx,"
strcat(bx,buf);
i++){//依次比对Huffman前缀编码
if(memcmp(header[i].bits,bx,header[i].count)==0)/*此函数也为网络借鉴,memcmp函数此处的作用
是比较bx的相应位是否与header[i].bits相同,
若前header[i].count均相同,则返回0*/
strcpy(bx,bx+header[i].count);
c=header[i].b;
m++;
//m用来统计解压缩后文件的长度
if(m==flength)//检验是否与源文件长度匹配
break;
\n\t解压缩文件成功!
if(m==flength)
\t解压缩文件与原文件相同!
\n\n"
else
\t解压缩文件与原文件不同!
intmain(){
intc;
while
(1){
\tHuffman前缀编码压缩&解压缩BYPB09000816俞映洲\n"
\t1.压缩2.解压缩0.退出\n"
do{//对用户输入进行容错处理
printf("
\n\t*请选择相应功能编号(0-2):
c=getch();
%c\n"
c);
if(c!
='
&
&
c!
2'
){
printf("
\t请检查您的输入在0~2之间!
请再输入一遍!
}while(c!
if(c=='
)//调用压缩子函数
compress();
elseif(c=='
uncompress();
//调用解压缩子函数
else{
exit(0);
return0;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 霍夫曼 编码 英文 文本 压缩 和解