5Huffman压缩模拟程序的设计任务书0.docx
- 文档编号:27020643
- 上传时间:2023-06-25
- 格式:DOCX
- 页数:25
- 大小:216.37KB
5Huffman压缩模拟程序的设计任务书0.docx
《5Huffman压缩模拟程序的设计任务书0.docx》由会员分享,可在线阅读,更多相关《5Huffman压缩模拟程序的设计任务书0.docx(25页珍藏版)》请在冰豆网上搜索。
5Huffman压缩模拟程序的设计任务书0
重庆科技学院
《数据结构》课程设计报告
学院:
_电气与信息工程学院_专业班级:
计科2012-01,02,05
学生姓名:
学号:
设计地点(单位)___计算机基础自主学习中心____________
设计题目:
__Huffman压缩模拟程序的设计__________
完成日期:
2013年7月12日
指导教师评语:
_________________________________
____________________________________________________________________________________________________________________________________________________________________________________________________________
_
成绩(五级记分制):
________________
指导教师(签字):
________________
重庆科技学院
课程设计任务书
设计题目:
Huffman压缩模拟程序的设计
学生姓名
课程名称
数据结构课程设计
专业班级
计科2012-01,02,05
地点
计算机基础自主学习中心
起止时间
2013.7.1-2013.7.12
设计内容及要求
利用Huffman编码原理可以实现对数据的无损压缩,设计一个模拟Huffman压缩的程序。
程序功能主要分为压缩和解压缩两部分,压缩:
读入待压缩的文本文件;统计分析文本文件中各字符的出现频度,以频度作为构造Huffman树的权值;根据各字符出现的不同频度构造Huffman树,然后规定每种字符的Huffman编码;再次读入待压缩的文本文件,然后根据各字符的Huffman编码逐一替代,将得到新的压缩文件。
并计算压缩率;解压缩:
读入压缩文件,将其看作字符流,根据Huffman树,对其进行解压缩得到原文件。
说明:
不考虑非英文字符。
计算压缩率时,原文件中每个字符看成是8位二进制ASCII码。
例如:
原文“AAABBCADA”进行Huffman压缩后得“111010100010011”,压缩率是15/(9×8)=20.8%。
设计
参数
测试数据要求:
自行设计一个能说明压缩效果和过程的实例,待压缩的文本文件字符不能少于1000个。
进度
要求
2013.7.1完成任务的讲解、并接受课程设计任务,选定课程设计的题目
2013.7.2了解任务的算法、并画出算法的程序流程图,对任务的关键技术进行验证、并确定解决办法
2013.7.3-2013.7.5程序设计及编码,上机调试
2013.7.8对程序进行调试,设计测试用例进行测试
2013.7.9整理课程设计的过程、并进行总结,完善程序功能
2013.7.10编写课程设计报告初稿
2013.7.11完善课程设计报告、并准备答辨
2013.7.12提交课程设计报告和程序,进行答辨
参考资料
1.严蔚敏吴伟民,数据结构,清华大学出版社,2007.3
2.程杰,大话数据结构,清华大学出版社,2011.6
3.(美)StephenPrata,CPrimerPlus中文版(第五版),人民邮电出版社,2005.2
其它
说明
1.本表应在每次实施前一周由负责教师填写二份,学院审批后交学院教务办备案,一份由负责教师留用。
2.若填写内容较多可另纸附后。
3.一题多名学生共用的,在设计内容、参数、要求等方面应有所区别。
系主任:
易军指导教师:
熊茜/张亚军
摘要
随着多媒体技术的迅速发展,压缩技术也快速的发展起来。
Huffman高效率的压缩编码,其压缩程序很高,目前在很多领域已经开始广泛应用,具有良好的市场前景。
这次课程设计运用的Huffman高效率编码,对文件进行压缩,再对文件进行解压。
实现了对数据的压缩及解压,并且可以运用在软件上面。
效果高效很实用。
关键字:
软件高效模块
1设计内容与要求
1.1设计内容
利用Huffman编码原理可以实现对数据的无损压缩,设计一个模拟Huffman压缩的程序。
1.2设计要求
程序功能主要分为压缩和解压缩两部分,压缩:
读入待压缩的文本文件;统计分析文本文件中各字符的出现频度,以频度作为构造Huffman树的权值;根据各字符出现的不同频度构造Huffman树,然后规定每种字符的Huffman编码;再次读入待压缩的文本文件,然后根据各字符的Huffman编码逐一替代,将得到新的压缩文件。
并计算压缩率;解压缩:
读入压缩文件,将其看作字符流,根据Huffman树,对其进行解压缩得到原文件。
2需求分析
2.1系统实现的目标
在当今社会,如何采用有效的数据压缩技术来节省数据文件的储存空间和计算机网络的传送时间已越来越引起人们的重视。
哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术
2.2系统实现方案
哈夫曼编码的应用很广泛,利用哈夫曼求得的用于通信的二进制编码称为哈夫曼编码。
树中从根到每个叶子都有一条路径,对路径上的各分支约定:
指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为和各个对应字符的编码,这就是哈夫曼编码。
3系统设计
3.1总体功能的实现
本程序设计包括2个模块:
主程序和子程序模块。
在主页面可以清楚的了解系统的实现功能,在控制台的菜单页面,根据需要,可以根据提示进行选择,选择后可以进行相应的操作。
如图3.1总体功能。
图3.1主页面图
3.2总体流程图
根据对Huffman功能分析,设计得到该系统的总体功能图如图3.2.
图3.2总体功能图
4系统实现
4.1构造哈夫曼树
图4.1
4.2哈夫曼编码
图4.2
5系统实现
5.1主要代码实现
5.11主调函数
intmain()
{
intc;
while
(1)//菜单工具栏
{
printf("\t______________________________________________\n");
printf("\n");
printf("\t*压缩、解压缩小工具*\n");
printf("\t_____________________________________________\n");
printf("\t___________________________________________\n");
printf("\t||\n");
printf("\t|1.压缩|\n");
printf("\t|2.解压缩|\n");
printf("\t|0.退出|\n");
printf("\t|_______________________________________________|\n");
printf("\n");
printf("\t说明:
(1)采用哈夫曼编码\n");
printf("\t
(2)适用于字符型文本文件\n");
printf("\n");
do//对用户输入进行容错处理
{
printf("\n\t*请选择相应功能(0-2):
");
c=getchar();//getchar();书写错误
printf("%c\n",c);
if(c!
='0'&&c!
='1'&&c!
='2')
{
printf("\t@_@请检查您输入的数字在0~2之间!
\n");
printf("\t请再输入一遍!
\n");
}
}while(c!
='0'&&c!
='1'&&c!
='2');
if(c=='1')compress();//调用压缩子函数
elseif(c=='2')uncompress();//调用解压缩子函数
else
{
printf("\t欢迎您再次使用该工具^_^\n");
exit(0);//退出该工具
}
system("pause");//任意键继续
system("cls");//清屏
}
return0;
}
5.12压缩文件时的代码
voidcompress()
{
charbuf[512];
unsignedcharc;
longi,j,m,n,f;
longmin1,pt1,flength,length1,length2;
doublediv;
FILE*ifp,*ofp;
printf("进行需要压缩的文件:
\n");
ifp=fopen("a.txt","r");
if(ifp==NULL)
{
printf("\n\t文件打开失败!
\n\n");
return;
}
printf("\t记录压缩后的文件:
");
ofp=fopen("b.hub","wb");
if(ofp==NULL)
{
printf("\n\t压缩文件失败!
\n\n");
return;
}
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码满足顺序存放关系*/
elseheader[i].b=0;
header[i].parent=-1;header[i].lchild=header[i].rchild=-1;//对结点进行初始化
}
for(i=0;i<256;i++)//根据频率(权值)大小,对结点进行排序,选择较小的结点进树
{
for(j=i+1;j<256;j++)
{
if(header[i].count { tmp=header[i]; header[i]=header[j]; header[j]=tmp; } } } for(i=0;i<256;i++)if(header[i].count==0)break; n=i;//外部叶子结点数为n个时,内部结点数为n-1,整个哈夫曼树的需要的结点数为2*n-1. m=2*n-1; for(i=n;i { min1=999999999;//预设的最大权值,即结点出现的最大次数 for(j=0;j { if(header[j].parent! =-1)continue; //parent! =-1说明该结点已存在哈夫曼树中,跳出循环重新选择新结点*/ if(min1>header[j].count) { pt1=j; min1=header[j].count; continue; } } header[i].count=header[pt1].count; header[pt1].parent=i;//依据parent域值(结点层数)确定树中结点之间的关系 header[i].lchild=pt1;//计算左分支权值大小 min1=999999999; for(j=0;j { if(header[j].parent! =-1)continue; if(min1>header[j].count) { pt1=j; min1=header[j].count; continue; } } header[i].count+=header[pt1].count; header[i].rchild=pt1;//计算右分支权值大小 header[pt1].parent=i; } for(i=0;i { f=i; header[i].bits[0]=0;//根结点编码0 while(header[f].parent! =-1) { j=f; f=header[f].parent; if(header[f].lchild==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 { j=strlen(header[i].bits); memmove(header[i].bits+1,header[i].bits,j+1); header[i].bits[0]='1'; } } } fseek(ifp,0,SEEK_SET);//从文件开始位置向前移动0字节,即定位到文件开始位置 fwrite(&flength,sizeof(int),1,ofp); /*用来将数据写入文件流中,参数flength指向欲写入的数据地址, 总共写入的字符数以参数size*int来决定,返回实际写入的int数目1*/ fseek(ofp,8,SEEK_SET); buf[0]=0;//定义缓冲区,它的二进制表示00000000 f=0; pt1=8; while(! feof(ifp)) { c=fgetc(ifp); f++; for(i=0;i { if(c==header[i].b)break; } strcat(buf,header[i].bits); j=strlen(buf); c=0; while(j>=8)//对哈夫曼编码位操作进行压缩存储 { for(i=0;i<8;i++) { if(buf[i]=='1')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"); for(i=0;i<8;i++) { if(buf[i]=='1')c=(c<<1)|1; elsec=c<<1; } fwrite(&c,1,1,ofp); pt1++; } fseek(ofp,4,SEEK_SET); fwrite(&pt1,sizeof(long),1,ofp); fseek(ofp,pt1,SEEK_SET); fwrite(&n,sizeof(long),1,ofp); for(i=0;i { fwrite(&(header[i].b),1,1,ofp); c=strlen(header[i].bits); fwrite(&c,1,1,ofp); j=strlen(header[i].bits); if(j%8! =0)//若存储的位数不是8的倍数,则补0 { for(f=j%8;f<8;f++) strcat(header[i].bits,"0"); } while(header[i].bits[0]! =0) { c=0; for(j=0;j<8;j++)//字符的有效存储不超过8位,则对有效位数左移实现两字符编码的连接 { if(header[i].bits[j]=='1')c=(c<<1)|1;//|1不改变原位置上的"0""1"值 elsec=c<<1; } strcpy(header[i].bits,header[i].bits+8);//把字符的编码按原先存储顺序连接 fwrite(&c,1,1,ofp); } } length2=pt1--; div=((double)length1-(double)length2)/(double)length1;//计算文件的压缩率 fclose(ifp); fclose(ofp); printf("\n\t压缩文件成功! \n"); printf("\t压缩率为%f%%\n\n",div*100); return; } 5.13解压文件时的代码 voiduncompress() { charfilename[255],outputfile[255],buf[255],bx[255]; unsignedcharc; longi,j,m,n,f,p,l; longflength; FILE*ifp=fopen("b.hub","r"),*ofp; printf("\t请进行需要解压缩的文件: "); //gets(filename); if(ifp==NULL) { printf("\n\t文件打开失败! \n"); return; } printf("\t请您输入解压缩后的文件名: "); gets(outputfile); ofp=fopen("c.txt","w"); if(ofp==NULL) { printf("\n\t解压缩文件失败! \n"); return; } fread(&flength,sizeof(long),1,ifp);//读取原文件长度,对文件进行定位 fread(&f,sizeof(long),1,ifp); fseek(ifp,f,SEEK_SET); fread(&n,sizeof(long),1,ifp); for(i=0;i { fread(&header[i].b,1,1,ifp); fread(&c,1,1,ifp); p=(long)c;//读取原文件字符的权值 header[i].count=p; header[i].bits[0]=0; if(p%8>0)m=p/8+1; elsem=p/8; for(j=0;j { fread(&c,1,1,ifp); f=c; itoa(f,buf,2);//将f转换为二进制表示的字符串 f=strlen(buf); for(l=8;l>f;l--) { strcat(header[i].bits,"0"); } strcat(header[i].bits,buf); } header[i].bits[p]=0; } for(i=0;i { for(j=i+1;j { if(strlen(header[i].bits)>strlen(header[j].bits)) { tmp=header[i]; header[i]=header[j]; header[j]=tmp; } } } p=strlen(header[n-1].bits); fseek(ifp,8,SEEK_SET); m=0; bx[0]=0; while (1)//通过哈夫曼编码的长短,依次解码,从原来的位存储还原到字节存储 { while(strlen(bx)<(unsignedint)p) { fread(&c,1,1,ifp); f=c; itoa(f,buf,2); f=strlen(buf); for(l=8;l>f;l--)//在单字节内对相应位置补0 { strcat(bx,"0"); } strcat(bx,buf); } for(i=0;i { if(memcmp(header[i].bits,bx,header[i].count)==0)break; } strcpy(bx,bx+header[i].count);/*从压缩文件中的按位存储还原到按字节存储字符, 字符位置不改变*/ c=header[i].b; fwrite(&c,1,1,ofp); m++;//统计解压缩后文件的长度 if(m==flength)break;//flength是原文件长度 } fclose(ifp); fclose(ofp); printf("\n\t解压缩文件成功! \n"); if(m==flength)//对解压缩后文件和原文件相同性比较进行判断(根据文件大小) printf("\t解压缩文件与原文件相同! \n\n"); elseprintf("\t解压缩文件与原文件不同! \n\n"); return; } 5.2测试结果 进入主页面,如图5.1 图5.1 压缩文件,如图5.2 图5.2 解压文件,如图5.3 如图5.3 6总结 通过2周的课程设计使我对哈夫曼树以及哈夫曼编码有了更深的认识更加面白哈夫曼编码在信息技术中的重要性和地位。 许多的错误然我明白了一个道理——细心是非常重要的。 同时,对于编程者而言,思路清晰是相当重要的。 通过这次课程设计,我看清了自己的编程功底和动手能力还不如人意,这主要是平时实践太少的缘故。 在这个程序中,还有许多地方值得完善,希望以后做得更好。 7致谢 在这次课程设计中,非常感谢老师和同学们的帮助,再次感谢他们,在我找不出错误的时候,帮助我去改正。 参考文献 1.严蔚敏吴伟民,数据结构,清华大学出版社,2007.3 2.程杰,大话数据结构,清华大学出版社,2011.6 3.(美)StephenPra
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Huffman 压缩 模拟 程序 设计 任务书