英文文件的压缩和解压缩-数据结构与算法课程设计报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
合肥学院
计算机科学与技术系
课程设计报告
2009~2010学年第二学期
课程数据结构与算法
课程设计名称英文文件的压缩和解压缩
学生姓名李洋
学号**********
专业班级08计科(2)
指导教师王昆仑
2010年6月7日
题目:英文文件的压缩和解压缩
1、问题分析和任务定义
采用哈夫曼编码思想实现文件的压缩和解压缩功能,并提供压缩前后的占用空间之比。要求:(1)压缩原文件的规模应不小于5K。(2)提供解压缩后文件与原文件的相同性比较功能,对于一篇文章,首先要打开一篇英文文章,统计该文章中每个字符出现的次数,然后以它们作为权值,对每一个字符进行编码,注意编码表设计及其数据结构,编码完成后再对其编码进行译码。
压缩过程就是以读的方式打开原来的英文文件A.txt,把其中出现的所有字符在文中出项的频率作为权值建立哈弗曼编码。以写的方式打开一个新的文件,把它作为英文文件压缩后的文本文件,在扫描英文文本文件的所有字符,把其经过一定的转换后存C.txt中。在扫描C.txt这个文件里的字符把其转换为二进制文件,在把二进制还原为初始的字符。存入D.txt中。
任务定义是⑴通过独立解决某个课程设计问题,在数据结构的逻辑特性和物理表示、数据结构的选择应用、算法的设计及其实现等方面加深对课程基本内容的理解和综合运用。
⑵深刻理解、牢固掌握数据结构和算法设计技术,提高分析和解决实际问题的能力。⑶在程序设计方法以及上机操作等基本技能和科学作风方面进行比较系统和严格的训练。
2、数据结构的选择和概要设计
此程序选择的存储结构为顺序存储结构,而使用的哈弗曼树是二叉树的一种特殊结构,可以首先把叶子节点按顺序存放在存储结构中,可以不用任何附加信息就直接寻得其左右孩子节点和父节点,方便建立哈弗曼树。
对于英文文章的压缩和解压缩只要定义生成哈弗曼树和哈弗曼编码的数据类型即可。即struct head
{
unsigned char b;
long count;
long parent,lch,rch;
char bits[256];
}
header[512],tmp;
其中b是存放英文文章中的各个字符,count存放每个字符对应的权值,也就是每个字符在一篇文章中出现的次数,parent,lch,rch是某叶子节点的父节点,和左右孩子节点,bits[]存放各自字符的哈弗曼编码。tmp则是在生成哈弗曼编码时需要寻找最小权和次小权来作为哈弗曼的树的头两个叶子节点,把它们的和作为根节点,加入到之前的字符编码中去,另外删除最小权和次小权,继续以这种方法生成哈弗曼编码,当到最后一个节点时结束,哈弗曼树生成完毕。
而后就是对文章进行压缩。
Fseek()函数把文件的指针调到ifp待读文件的开始端,与此同时,在把读取的字符经过处理写入ifp文件中,c=fgetc()读取,如果c==header[i].b,即buf中存放的二进制转化为字符与字符中的字符相同,则记录于c.txt中,并把相同的部分给删除。如此往复,在继续读取由字符的哈弗曼编码所构成的顺序表中的8位,转化为整数,在强制转化为字符型变量,写入c.txt,另外注意的是,当最后的由哈弗曼所构成的二进制文档的字符读取到最后的时候,如果不够8位,的话,则在末尾补零,不然就会出现错误。while(header[i].bits[0]!=0) {
c=0;
for(j=0;j<8;j++)
{
if(header[i].bits[j]=='1') c=(c<<1)|1;
else c=c<<1;
}
文章压缩成功后,就需要对文档文档进行解压缩,先读取c.txt中的字符文档,是一个一个字符的读取,然后再把读取的一个字符先强制转化为整数,这是根据ASCII码来转化的,最后在将整数转化为二进制编码,是8位的编码,并把这编码存入buf中,在不断读取不断存储,在此过程,用字符中的编码与以读取中的编码进行比较,即if(memcmp(header[i].bits,bx,header[i].count)==0) break;
}if判断语句来判断,如果相等的话,也就是memcmp()函数的值取零,那么就记录这个编码所对应的字符值,即c=header【i】. b,并且写入D.txt中,即fwrite(&c,1,1,ofp);,不断重复这一过程,知道C.txt中的字符都读取完毕,那么存入D.txt的文档也就结束,是源文件一致的英文文件。
3、详细设计和编码
首先,要完成此程序,首先就要建立哈弗曼树,来建立哈弗曼编码,采用顺序表存储结构,
即struct head
{
unsigned char b;
long count;
long parent,lch,rch;
char bits[256];
}
header[512],tmp;
首先定义文件指针ifp,ifp=fopen(“A。txt”),定义flength=0;统计这篇文章的所有的字符的长度,然后在用feof()读取全文信息,用fread()函数一个一个读取字符,header[c].count
记录的是每个字符的出现的频率,然后初始化数组,加入header[i].count不为0,即某个字符出现在文中,用ascii码统计header[i].count的数值,如果不为0,那就说明此字符在文中又出现,那么就把它赋值给header[i].b,用强制类型转换。然后把它的左右孩子和父节点都赋为-1,即为空。
然后寻找最小权和次小权,for(i=n;i 其次,要实现文件的压缩过程,就要从文本中读入一个字符,如果读入的是第i个字符,则把第i个字符的编码写在buf的结尾,buf【0】=0;用于存放所有的字符的哈弗曼编码,即是一连串的二进制编码,当buf的长度大于等于8的时候,把前八位的编码强制转换为整数,之后在把这个整数强制转换为字符,把字符串写入压缩文件,最后把buf中已经转换为整数的那8为编码去除,继续读入哈弗曼编码。当buf中最后的字符串小于8位时,转换为字符写入压缩文件,在写入压缩文件之后要注意把英文的字符以及其的编码一起写入文件。 最后,要实现的是解压缩过程,解压缩之前必须依靠字符的权值重新进行哈弗曼编码,首先定义一个字符串bx,当bx的长度小于p时,从C.txt中读入一个字符,把字符转换为整数,把整数在转换为二进制码的字符串buf,统计buf中的长度,当小于8位时,补o,然后把字符串buf接着bx末尾。然后在把bx的部分编码与字符编码比较,若相同,去掉相同的编码,并把程序写入解压后文件。 4、上机调试 问题1:在文件中一个字符只是占去一个字节,给字符编码后,其编码要如何存入压缩文件才能应道压缩的作用。 解决:若直接存储,编码只可以用字符串,这样存储空间不仅没有减少反而增大了,所以必须把多个编码存在一个字节中,一字符的形式写入文件。 即:多个编码->一个八位二进制编码->ascii码->字符(写入到C.txt) 问题2:生成了压缩文件,可以实现文件的压缩,但不能实现解压. 原因是:在解压的过程中,吧从压缩文件中读取的字符转化为整数在转化为二进制编码时没有给编码补零。 在开始写程序,一开始在就觉得自己会把各种细节都会考虑到,做了准备,但是在具体实现时却发现真的不是那么回事,是自己没有充分考虑问题。不知道怎么解压和解压缩。 5、测试结果及其分析 运行程序,进入主菜单选择页面,有四个选项,1。压缩文档,2。解压缩文档,3、输出压缩后的文档,4。退出。选择第一个时首先输出每个字符以及对应的权值和对应的哈弗曼编码。而后在输出压缩比,最后生成讲压缩后的文档存放在C.txt中,第二个是实现解压缩功能,将解压缩的文档存放在D.txt中,第三个选项是读取D.txt中的文章,在屏幕中显示。最后一个选项退出程序。