用哈夫曼树实现压缩解压.docx
- 文档编号:11279688
- 上传时间:2023-02-26
- 格式:DOCX
- 页数:22
- 大小:235.79KB
用哈夫曼树实现压缩解压.docx
《用哈夫曼树实现压缩解压.docx》由会员分享,可在线阅读,更多相关《用哈夫曼树实现压缩解压.docx(22页珍藏版)》请在冰豆网上搜索。
用哈夫曼树实现压缩解压
用哈夫曼树实现压缩解压
程序是用VC++6.0编译完成的,可以完成对任意文件的压缩解压(为方便寻找,压缩出的文件与待压缩文件在同一文件夹中),但压缩文件夹还不可以,另外该程序还能打印出压缩时所建立的哈夫曼树及哈夫曼编码。
源代码如下:
#include
#include
#include
#include
typedefstructnode
{
longw;
shortp,l,r;
}htnode,*htnp;
typedefstructhuffman_code
{
unsignedcharlen;
unsignedchar*codestr;
}hufcode;
typedefchar**huffmancode;
intinitial_files(char*source_filename,FILE**inp,char*obj_filename,FILE**outp);
char*create_filename(char*source_filename,char*obj_filename);
intcompress(char*source_filename,char*obj_filename);
longfrequency_data(FILE*in,longfre[]);
intsearch_set(htnpht,intn,int*s1,int*s2);
intcreate_hftree(longw[],intn,htnodeht[]);
intencode_hftree(htnphtp,intn,hufcodehc[]);
unsignedcharchars_to_bits(constunsignedcharchars[8]);
intwrite_compress_file(FILE*in,FILE*out,htnpht,hufcodehc[],char*source_filename,longsource_filesize);
intdecompress(char*source_filename,char*obj_filename);
voidget_mini_huffmantree(FILE*in,shortmini_ht[][2]);
intwrite_decompress_file(FILE*in,FILE*out,shortmini_ht[][2],longbits_pos,longobj_filesize);
intd_initial_files(char*source_filename,FILE**inp,char*obj_filename,FILE**outp);
main()
{
ints;
charfilename[10];
system("color3F");
printf("***************************************\n");
printf("*菜单:
*\n");
printf("*1.——————压缩——————*\n");
printf("*2.—————-解压缩—————-*\n");
printf("*0.——————退出——————*\n");
printf("***************************************\n");
scanf("%d",&s);
while(s!
=0)
{
getchar();
switch(s)
{
case1:
puts("请输入待压缩文件路径:
");
gets(filename);
compress(filename,NULL);
break;
case2:
puts("请输入待解压文件路径:
");
gets(filename);
decompress(filename,NULL);
break;
default:
printf("指令错误!
请重新输入指令:
\n");
}
puts("");
printf("***************************************\n");
printf("*菜单:
*\n");
printf("*1.——————压缩——————*\n");
printf("*2.—————-解压缩—————-*\n");
printf("*0.——————退出——————*\n");
printf("***************************************\n");
scanf("%d",&s);
}
}
intinitial_files(char*source_filename,FILE**inp,char*obj_filename,FILE**outp)
{
if(fopen(source_filename,"rb")==NULL)
{
return-1;
}
if(obj_filename==NULL)
{
if((obj_filename=(char*)malloc(256*sizeof(char)))==NULL)
{
return-1;
}
create_filename(source_filename,obj_filename);
}
if(strcmp(source_filename,obj_filename)==0)
{
return-1;
}
printf("待压缩文件:
%s,压缩文件:
%s\n",source_filename,obj_filename);
if((*outp=fopen(obj_filename,"wb"))==NULL)
{
return-1;
}
if((*inp=fopen(source_filename,"rb"))==NULL)
{
return-1;
}
free(obj_filename);
return0;
}
char*create_filename(char*source_filename,char*obj_filename)
{
char*temp;
if((temp=strrchr(source_filename,'.'))==NULL)
{
strcpy(obj_filename,source_filename);
strcat(obj_filename,".zip");
}
else
{
strncpy(obj_filename,source_filename,temp-source_filename);
obj_filename[temp-source_filename]='\0';
strcat(obj_filename,".zip");
}
returnobj_filename;
}
intcompress(char*source_filename,char*obj_filename)
{
FILE*in,*out;
charch;
interror_code,i,j;
floatcompress_rate;
hufcodehc[256];
htnodeht[256*2-1];
longfrequency[256],source_filesize,obj_filesize=0;
error_code=initial_files(source_filename,&in,obj_filename,&out);
if(error_code!
=0)
{
puts("文件打开失败!
请重新输入文件路径:
");
returnerror_code;
}
source_filesize=frequency_data(in,frequency);
printf("文件大小%ld字节\n",source_filesize);
error_code=create_hftree(frequency,256,ht);
if(error_code!
=0)
{
puts("建立哈夫曼树失败!
");
returnerror_code;
}
error_code=encode_hftree(ht,256,hc);
if(error_code!
=0)
{
puts("建立哈夫曼编码失败!
");
returnerror_code;
}
for(i=0;i<256;i++)
obj_filesize+=frequency[i]*hc[i].len;
obj_filesize=obj_filesize%8==0?
obj_filesize/8:
obj_filesize/8+1;
for(i=0;i<256-1;i++)
obj_filesize+=2*sizeof(short);
obj_filesize+=strlen(source_filename)+1;
obj_filesize+=sizeof(long);
obj_filesize+=sizeof(unsignedint);
compress_rate=(float)obj_filesize/source_filesize;
printf("压缩文件大小:
%ld字节,压缩比例:
%.2lf%%\n",obj_filesize,compress_rate*100);
error_code=write_compress_file(in,out,ht,hc,source_filename,source_filesize);
if(error_code!
=0)
{
puts("写入文件失败!
");
returnerror_code;
}
puts("压缩完成!
");
puts("");
puts("是否打印该文件中字符对应的huffman树及编码?
");
puts("PleaseinputYORN");
do{
scanf("%s",&ch);
switch(ch)
{
case'Y':
puts("以下是哈夫曼树:
");
for(i=256;i<256*2-2;i++)
{
if(ht[i].w>0)
printf("%-10d%-10d%-10d%-10d%-10d\n",i,ht[i].w,ht[i].p,ht[i].l,ht[i].r);
}
puts("以下是哈夫曼编码:
");
for(i=0;i<256;i++)
{
if(frequency[i]==0)
i++;
else
{
printf("%d\t",frequency[i]);
for(j=0;j printf("%d",hc[i].codestr[j]); printf("\n"); } } break; case'N': break; default: printf("指令错误! 请重新输入指令: \n"); } }while(ch! ='Y'&&ch! ='N'); fclose(in); fclose(out); for(i=0;i<256;i++) { free(hc[i].codestr); } return0; } longfrequency_data(FILE*in,longfrequency[]) { inti,read_len; unsignedcharbuf[256]; longfilesize; for(i=0;i<256;i++) { frequency[i]=0; } fseek(in,0L,SEEK_SET); read_len=256; while(read_len==256) { read_len=fread(buf,1,256,in); for(i=0;i { frequency[*(buf+i)]++; } } for(i=0,filesize=0;i<256;i++) { filesize+=frequency[i]; } returnfilesize; } intsearch_set(htnpht,intn,int*s1,int*s2) { inti,x; longminValue=1000000,min=0; for(x=0;x { if(ht[x].p==-1)break; } for(i=0;i { if(ht[i].p==-1&&ht[i].w { minValue=ht[i].w; min=i; } } *s1=min; minValue=1000000,min=0; for(i=0;i { if(ht[i].p==-1&&ht[i].w =*s1) { minValue=ht[i].w; min=i; } } *s2=min; return1; } intcreate_hftree(longw[],intn,htnodeht[]) { intm,i,s1,s2; if(n<1)return-1; m=2*n-1; if(ht==NULL)return-1; for(i=0;i { ht[i].w=w[i]; ht[i].p=ht[i].l=ht[i].r=-1; } for(;i { ht[i].w=ht[i].p=ht[i].l=ht[i].r=-1; } for(i=n;i { search_set(ht,i,&s1,&s2); ht[s1].p=ht[s2].p=i; ht[i].l=s1; ht[i].r=s2; ht[i].w=ht[s1].w+ht[s2].w; } return0; } intencode_hftree(htnphtp,intn,hufcodehc[]) { inti,j,p,codelen; unsignedchar*code=(unsignedchar*)malloc(n*sizeof(unsignedchar)); if(code==NULL)return-1; for(i=0;i { for(p=i,codelen=0;p! =2*n-2;p=htp[p].p,codelen++) { code[codelen]=(htp[htp[p].p].l==p? 0: 1); } if((hc[i].codestr=(unsignedchar*)malloc((codelen)*sizeof(unsignedchar)))==NULL) { return-1; } hc[i].len=codelen; for(j=0;j { hc[i].codestr[j]=code[codelen-j-1]; } } free(code); return0; } unsignedcharchars_to_bits(constunsignedcharchars[8]) { inti; unsignedcharbits=0; bits|=chars[0]; for(i=1;i<8;++i) { bits<<=1; bits|=chars[i]; } returnbits; } intwrite_compress_file(FILE*in,FILE*out,htnpht,hufcodehc[],char*source_filename,longsource_filesize) { unsignedinti,read_counter,write_counter,zip_head=0xFFFFFFFF; unsignedcharwrite_char_counter,code_char_counter,copy_char_counter, read_buf[256],write_buf[256],write_chars[8],filename_size=strlen(source_filename); hufcode*cur_hufcode; fseek(in,0L,SEEK_SET); fseek(out,0L,SEEK_SET); fwrite(&zip_head,sizeof(unsignedint),1,out); fwrite(&filename_size,sizeof(unsignedchar),1,out); fwrite(source_filename,sizeof(char),filename_size,out); fwrite(&source_filesize,sizeof(long),1,out); for(i=256;i<256*2-1;i++) { fwrite(&(ht[i].l),sizeof(ht[i].l),1,out); fwrite(&(ht[i].r),sizeof(ht[i].r),1,out); } write_counter=write_char_counter=0; read_counter=256; while(read_counter==256) { read_counter=fread(read_buf,1,256,in); for(i=0;i { cur_hufcode=&hc[read_buf[i]]; code_char_counter=0; while(code_char_counter! =cur_hufcode->len) { copy_char_counter=(8-write_char_counter>cur_hufcode->len-code_char_counter? cur_hufcode->len-code_char_counter: 8-write_char_counter); memcpy(write_chars+write_char_counter,cur_hufcode->codestr+code_char_counter,copy_char_counter); write_char_counter+=copy_char_counter; code_char_counter+=copy_char_counter; if(write_char_counter==8) { write_char_counter=0; write_buf[write_counter++]=chars_to_bits(write_chars); if(write_counter==256) { fwrite(write_buf,1,256,out); write_counter=0; } } } } } fwrite(write_buf,1,write_counter,out); if(write_char_counter! =0) { write_char_counter=chars_to_bits(write_chars); fwrite(&write_char_counter,1,1,out); } return0; } voidget_mini_huffmantree(FILE*in,shortmini_ht[][2]) { inti; for(i=0;i<256;i++) { mini_ht[i][0]=mini_ht[i][1]=-1; } fread(mini_ht[i],sizeof(short),2*(256-1),in); } intwrite_decompress_file(FILE*in,FILE*out,shortmini_ht[][2],longbits_pos,longobj_filesize) { longcur_size; unsignedcharread_buf[256],write_buf[256],convert_bit; unsignedintread_counter,write_counter,cur_pos; fseek(in,bits_pos,SEEK_SET); fseek(out,0L,SEEK_SET); read_counter=256-1; cur_size=write_counter=0; cur_pos=256*2-2; while(cur_size! =obj_filesize) { if(++read_counter==256) { fread(read_buf,1,256,in); read_counter=0; } for(convert_bit=128;convert_bit! =0;convert_bit>>=1) { cur_pos=((read_buf[read_counter]&convert_bit)==0? mini_ht[cur_pos][0]: mini_ht[cur_pos
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 用哈夫曼树 实现 压缩 解压