数据结构课程设计哈夫曼压缩文件Word下载.docx
- 文档编号:21256031
- 上传时间:2023-01-28
- 格式:DOCX
- 页数:10
- 大小:18.93KB
数据结构课程设计哈夫曼压缩文件Word下载.docx
《数据结构课程设计哈夫曼压缩文件Word下载.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计哈夫曼压缩文件Word下载.docx(10页珍藏版)》请在冰豆网上搜索。
定义函数voidcompress()/*压缩文件*/
{
在函数compress内定义变量;
读取被压缩文件;
建立并打开目标文件;
逐字节读入,并进行累加计数,得到各个字节在文件中的出现频率;
利用哈夫曼算法构造出字节对应的哈夫曼树;
将压缩后的数据写入目标文件,并保存;
}
定义函数uncompress()/*解压文件*/
{
在函数uncompress内定义变量;
读取需解压文件;
建立并打开目标文件;
对哈夫曼树进行遍历实现解压;
将解压后的数据写入目标文件,并保存;
定义主函数intmain()
输入A,压缩文件,调用函数compress;
输入B,解压文件,调用函数uncompress;
}
二.详细设计
1、文件的字节频率统计
字节共有256个,从0~255,可定义长度为256的频率数组来记录每个字节的出现频率。
将文件以二进制方式打开,逐字节读入,并进行累加计数,就可以得到各个字节在文件中的出现频率。
for(i=0;
i<
512;
i++)
if(header[i].count!
=0)header[i].b=(unsignedchar)i;
elseheader[i].b=0;
header[i].parent=-1;
header[i].lch=header[i].rch=-1;
for(i=0;
256;
for(j=i+1;
j<
j++)
if(header[i].count<
header[j].count)
tmp=header[i];
header[i]=header[j];
header[j]=tmp;
2、哈夫曼树的构造
利用哈夫曼算法就可以构造出字节对应的哈夫曼树了。
for(i=n;
m;
min1=999999999;
for(j=0;
i;
if(header[j].parent!
=-1)continue;
if(min1>
pt1=j;
min1=header[j].count;
continue;
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;
while(header[f].parent!
=-1)
j=f;
f=header[f].parent;
if(header[f].lch==j)
j=strlen(header[i].bits);
memmove(header[i].bits+1,header[i].bits,j+1);
header[i].bits[0]='
0'
;
else
memmove(header[i].bits+1,header[i].bits,j+1);
1'
3、压缩文件的格式
将原文件逐字节用哈夫曼编码重新编码,并写入到目标文件中就可以得到压缩文件。
但为了对压缩文件进行解码,需要将所用的哈夫曼树也一并保存到压缩文件中。
因此,压缩文件中应该由两个部分组成,前一部分为编码头,存储哈夫曼树,后一部分才是压缩编码。
4、压缩编码
用哈夫曼编码对原文件进行换码,由于哈夫曼编码是变长位编码,因此压缩文件应当是位流文件,而不是字节流文件。
但是文件操作是以字节为最小读写单位的,因此必须在内存中完成位流到字节流的转换工作。
可以用一个整型变量作为位流缓冲区,将字节的对应哈夫曼编码逐位追加到位流缓冲区中,当位流缓冲区满一个字节时,再将一个字节写入目标文件中。
注意:
结尾字节可能填不满,在压缩文件中要设法标志出来。
while(j>
=8)
8;
if(buf[i]=='
)c=(c<
<
1)|1;
elsec=c<
1;
fwrite(&
c,1,1,ofp);
pt1++;
strcpy(buf,buf+8);
j=strlen(buf);
if(f==flength)break;
if(j>
0)
strcat(buf,"
00000000"
);
fseek(ofp,4,SEEK_SET);
pt1,sizeof(long),1,ofp);
fseek(ofp,pt1,SEEK_SET);
n,sizeof(long),1,ofp);
(header[i].b),1,1,ofp);
c=strlen(header[i].bits);
j=strlen(header[i].bits);
if(j%8!
=0)
for(f=j%8;
f<
f++)
strcat(header[i].bits,"
0"
5、编码头的格式
编码头是压缩中的额外开销,因此不宜过大,否则将抵消压缩所减少的空间。
基于字节的哈夫曼树有256个叶结点(256个字符),因此整个哈夫曼树共有511个结点。
若采用静态三叉链结构表示,每个结点中有父结点下标、左子下标和右子下标三个数据项,每个数据项至少需要2个字节来表示(一个字节只能表示0~255),因此整个哈夫曼树共需3*2*511=3066个字节的空间。
但实际上,只要规定了左子和右子的排列规则(例如,可以约定在构造哈夫曼树,合并两棵子树时,下标较小的结点为左子,下标较大的结点为右子),左子下标和右子下标是可以不存储的,在每个结点中只存储父结点下标就可以了,这样,整棵哈夫曼树就只要2*511=1022个字节的空间。
进一步分析会发现,父结点下标的取值范围是256~510,因为叶结点是不可能作为父结点的。
因此,如果对各结点的父结点下标作平移,平移到0~254,就只需要一个字节就可以存储了,这样,整棵哈夫曼树就只要511个字节的空间就可以存储了。
综上所述,可以将压缩后的511个字节的哈夫曼树作为编码头存到压缩文件中,在编码头中再加上一个字节,用来存贮压缩编码的结尾字节中的有效位数。
这样,编码头共需512个字。
7、解压过程
解压时,先从压缩文件中读取编码头,还原哈夫曼树;
再从压缩文件中逐字节读入压缩编码,并逐位扫描,进行解码,每解出一个字节,将其写入解压缩文件中。
for(j=0;
fread(&
c,1,1,ifp);
f=c;
itoa(f,buf,2);
f=strlen(buf);
for(l=8;
l>
f;
l--)
strcat(header[i].bits,buf);
header[i].bits[p]=0;
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;
三.测试报告
*测试计划:
为验证程序效果,对如下几个文件进行压缩和解压缩:
三个txt文件,分别为1KB.9KB.43KB,及一个JPG文件为4.27MB。
并对压缩和解压缩效果进行分析。
*试验结果及结论:
如下表,对几个文件压缩和解压的结果:
原文件
压缩后
解压后
1
Txt文件(1KB)
Huf文件(1KB)
2
Txt文件(9KB)
Huf文件(8KB)
3
Txt文件(43KB)
Huf文件(36KB)
4
JPG文件(4.27MB)
Huf文件(4.241KB)
*##无法解压##*
结论:
这个程序的基本缺陷是:
1.慢位流实现
2.相当慢的解码(比编码慢)另一方面,
这个程序有几个优点:
1.哈夫曼树以一个紧密的形式每个符号要求12位(对于8位的符号)的方式存储;
2.编码相当容易理解,哈夫曼编码在数据有噪音的情况下非常好,这中情况下大多数基于字典方式的编码器都有问题。
解码的时候,从上到下遍历树,为压缩的流选择从左/右分支,每次碰到一个叶子节点的时候,就可以将对应的字节写到解压输出流中,然后再从根开始遍历。
但压缩后所得的新文件的压缩效果往往不是非常明显,原因在于源文件中出现各种字符的频率分布均匀,换句话说当源文件中某个字符或某些字符出现频率较高时,利用哈夫曼算法压缩源文件后所得新文件的压缩效果会很明显。
四.总结
做的程序思维条理必须严密,在做程序时语言必须规范,在做完一个程序后需认真检查并补充不足之处。
最后要仔细总结,积累经验。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 课程设计 哈夫曼 压缩文件