数据结构哈夫曼压缩软件设计实验报告文档格式.docx
《数据结构哈夫曼压缩软件设计实验报告文档格式.docx》由会员分享,可在线阅读,更多相关《数据结构哈夫曼压缩软件设计实验报告文档格式.docx(41页珍藏版)》请在冰豆网上搜索。
![数据结构哈夫曼压缩软件设计实验报告文档格式.docx](https://file1.bdocx.com/fileroot1/2022-11/24/2e83399a-f260-436b-9d45-be558a6a737f/2e83399a-f260-436b-9d45-be558a6a737f1.gif)
4.3.2张颖设计实现17
4.3.3刘琪设计实现20
4.3.4张晓雨设计实现22
5测试与调试25
5.1个人测试(按组员分工)25
5.1.1王健测试25
5.1.2张颖测试26
5.1.3刘琪测试27
5.1.4张晓雨测试31
5.2组装与系统测试32
5.3系统运行32
6课题总结33
6.1课题评价33
6.2团队协作33
6.3下一步工作33
6.4个人设计小结(按组员分工)33
6.4.1王健设计小结33
6.4.2张颖设计小结34
6.4.3刘琪设计小结34
6.4.4张晓雨设计小结34
7附录A课题任务分工35
A-1课题程序设计分工35
A-2课题报告分工36
附录B课题设计文档(光盘)37
B-1源程序代码(*.H,*.CPP)37
B-2工程与可执行文件)37
附录C用户操作手册(可选)37
C.1运行环境说明37
C.2操作说明37
1课题概述
1.1课题任务
采用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。
利用哈夫曼编码对文本或图像进行数据压缩,设计数据压缩软件。
【设计要求】
(1)采用静态链表的二叉树等数据结构。
(5)其它完善性功能。
1.2课题原理
1.2.1哈夫曼树:
哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。
所谓树的带权路径长度,就是树中所有的叶子结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。
树的带权路径长度记为
,n个权值
构成一颗有n个叶结点的二叉树,相应的叶结点的路径长度为
。
可证明哈夫曼树的WPL是最小的。
1.2.2压缩软件:
压缩软件是利用算法将文件有损或无损地处理,以达到保留最多文件信息,而令文件体积变小的应用软件。
压缩软件一般同时具有解压缩的功能。
压缩软件的的基本原理是查找文件内的重复字节,并建立一个相同字节的"
词典"
文件,并用一个代码表示,比如在文件里有几处有一个相同的词"
中华人民共和国"
用一个代码表示并写入"
文件,这样就可以达到缩小文件的目的。
常见的压缩软件有WinRAR,好压(Haozip),WinZip,7-Zip,WinMount,Peazip等等。
1.2.3哈夫曼压缩:
哈夫曼压缩是个无损的压缩算法,一般用来压缩文本和程序文件。
哈夫曼压缩属于可变代码长度算法一族。
意思是个体符号(例如,文本文件中的字符)用一个特定长度的位序列替代。
因此,在文件中出现频率高的符号,使用短的位序列,而那些很少出现的符号,则用较长的位序列。
1.3相关知识
1.3.1二进制文件的创建、读取、写入操作
1.3.2数学统计
1.3.3哈夫曼树算法
1.3.4获取哈夫曼编码
1.3.5压缩文件相关信息
1.3.6C/C++语言的熟悉掌握,一定程度上掌握MFC
2需求分析
2.1课题调研
随着计算机技术的发展,人们对文件信息的需求量逐渐增大,不光对文件个数的使用量增加,单个文件的内存也增大到几个G,这种现象的产生,将导致计算机上内存的消耗过大,以及计算机对文件的操作变得十分困难。
2.2用户需求分析
经过调研,目前用户比较倾向的压缩工具的特点有:
使用方便、用户友好,在压缩率以及压缩速度方面表现出色。
在这个背景下,我们小组决定运用哈夫曼算法,设计一款符合大众要求的小压缩工具。
3方案设计
3.1总体功能设计
3.2数据结构设计
//压缩函数使用数据结构
typedefstructHTNode{
unsignedcharb;
/*thecharactor*/
longparent,lchild,rchild;
/*makeatree*/
charbits[256];
/*thehaffumancode*/
longcount;
/*thefrequency*/
}HTNode,*HuffmanTree;
//动态分配数组存储哈夫曼树t
//解压函数使用数据结构
structhead{
longparent,lch,rch;
}header[512],tmp;
3.3函数原型设计
voidSelect(HuffmanTreeHT,intx,int&
s1,int&
s2);
//HT[]数组1…x中选出能够建树结点中权值最小两个
voidCompress(char*filename,char*outputfile);
//压缩函数
voidDeCompress(char*filename,char*outputfile);
//解压函数
3.4主算法设计
压缩算法实现
解压算法实现
3.5用户界面设计
3.5.1主界面
3.5.2菜单界面
3.5.3压缩界面
3.5.4解压界面
3.5.5查找文件和寻找压缩路径界面
4方案实现
4.1开发环境与工具
硬件:
个人PC
软件:
VS2013
开发环境:
C++
4.2程序设计关键技术
二进制文件的读取、写入;
哈夫曼算法;
MFC实现图形界面。
4.3个人设计实现(按组员分工)
4.3.1王健设计实现
4.3.1.1实现部分——压缩
voidCompress(char*filename,char*outputfile){
/*前面省略其他人的部分*/
fseek(ifp,0,SEEK_SET);
fwrite(&
flength,sizeof(long),1,ofp);
//压缩文件前四个字节用于//存放原文件字节数
//fwrite(constvoid*buffer,size_tsize,size_tcount,FILE*stream);
/*fwrite这个函数以二进制形式对文件进行操作,不局限于文本文件
(1)buffer:
是一个指针,对fwrite来说,是要获取数据的地址;
(2)size:
要写入内容的单字节数;
(3)count:
要进行写入size字节的数据项的个数;
(4)stream:
目标文件指针;
(5)返回实际写入的数据项个数count。
*/fseek(ofp,8,SEEK_SET);
//ofp从第九个字节处开始写入压缩编码
buf[0]=0;
f=0;
pt1=8;
//用于记录写入压缩文件的字节数
while(!
feof(ifp)){
ch=fgetc(ifp);
f++;
for(i=0;
i<
n;
i++)
if(ch==HT[i].b)
break;
strcat(buf,HT[i].bits);
//字符串连接函数
j=strlen(buf);
ch=0;
while(j>
=8){//每满八位,存储至文件for(i=0;
8;
i++){
if(buf[i]=='
1'
)
ch=(ch<
<
1)|1;
//左移一位,用零补,并加一
else
ch=ch<
1;
//左移一位,用零补
}
ch,1,1,ofp);
pt1++;
strcpy(buf,buf+8);
//buf前八位被覆盖
if(f==flength)//所有哈夫曼编码都被读完
if(j>
0){//flength不是八的整数倍,用0补全strcat(buf,"
00000000"
);
fseek(ofp,4,SEEK_SET);
pt1,sizeof(long),1,ofp);
//第二个四字节存放哈夫曼树在//压缩文件的位置
fseek(ofp,pt1,SEEK_SET);
n,sizeof(long),1,ofp);
//pt1个字节后存放哈夫曼树结点//数
i++){//将哈夫曼编码信息存入压缩文件fwrite(&
(HT[i].b),1,1,ofp);
//单个字节存储一个叶子结点
ch=strlen(HT[i].bits);
//接着存储其哈夫曼编码数
j=strlen(HT[i].bits);
if(j%8!
=0){//每个叶子结点哈夫曼编码不足八位,左移,并补零for(f=j%8;
f<
f++)
strcat(HT[i].bits,"
0"
while(HT[i].bits[0]!
=0){
for(j=0;
j<
j++){
if(HT[i].bits[j]=='
strcpy(HT[i].bits,HT[i].bits+8);
//将哈夫曼编码信息存入压缩文件΄
}
fclose(ifp);
fclose(ofp);
}
4.3.1.2实现部分——MFC实现图形界面
//类
ClassCHuffmanDlg:
publicCDialog{}//主界面类
Classmenu:
publicCDialog{}//菜单界面类
Classcompress:
publicCDialog{}//压缩界面类
ClassDecompress:
publicCDialog{}//解压界面类
//主界面类中的函数成员
afx_msgvoidOnBnClickedOk();
//鼠标按下功能选项按钮
afx_msgvoidOnBnClickedCancel();
//鼠标按下退出
//菜单界面类中的函数成员
afx_msgvoidOnOk2();
//鼠标按下解压按钮
//鼠标按下压缩按钮
afx_msgvoidOnBnClickedButton1();
//鼠标按下取消按钮
//压缩界面类中的函数成员
afx_msgvoidOnButton1();
//鼠标按下查找1按钮(弹出文件查找界面)
afx_msgvoidOnBnClickedButton2();
//鼠标按下查找2按钮(弹出保存文//件路径界面)
afx_msgvoidOnEnChangeEdit3();
//压缩文件命名编辑框
afx_msgvoidOnBnClickedButton3();
//鼠标按下确定按钮
//解压界面类中的函数成员
afx_msgvoidOnButton1();
afx_msgvoidOnEnChangeEdit2();
afx_msgvoidOnBnClickedButton4();
4.3.2张颖设计实现
实现部分——解压
//解压功能,此设有调试函数
#include<
stdio.h>
string.h>
stdlib.h>
#ifndefHEAD2_H
#defineHEAD2_H
voidDeCompress(char*filename,char*outputfile){
charbuf[255],bx[255];
unsignedcharc;
longi,j,m,n,f,p,l;
longflength;
//flength文件中存储字节数
FILE*ifp,*ofp;
for(i=0;
i<
512;
++i)
header[i].count=0;
ifp=fopen(filename,"
rb"
if(ifp==NULL)
exit(0);
ofp=fopen(outputfile,"
wb"
if(ofp==NULL)
fread(&
flength,sizeof(long),1,ifp);
//读取前四个字节,//flength为原文件字节数
f,sizeof(long),1,ifp);
//f为压缩文件中哈夫曼树信息前//的字节数
fseek(ifp,f,SEEK_SET);
n,sizeof(long),1,ifp);
//读取哈夫曼树叶子结点数n
for(i=0;
i<
i++){//重建哈夫曼树
header[i].b,1,1,ifp);
//读取叶子字符
c,1,1,ifp);
//读取叶子哈夫曼编码长度
p=(long)c;
//单个叶子的哈夫曼编码长度
header[i].count=p;
header[i].bits[0]=0;
if(p%8>
0)
m=p/8+1;
else
m=p/8;
for(j=0;
j<
m;
j++){
//读取该叶子结点哈夫曼编码
f=c;
itoa(f,buf,2);
//将任意类型的数字转换为字符串,2进制编//码,存储在buf中
f=strlen(buf);
for(l=8;
l>
f;
l--)//不足八位用零补strcat(header[i].bits,"
strcat(header[i].bits,buf);
header[i].bits[p]=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);
//ifp开始指向原文件内容信息
m=0;
bx[0]=0;
while
(1){
while(strlen(bx)<
(unsignedint)p){
l--)
strcat(bx,"
strcat(bx,buf);
i++)
if(memcmp(header[i].bits,bx,header[i].count)==0)//比较内存区域header[i].bits和bx的前count个字节
strcpy(bx,bx+header[i].count);
c=header[i].b;
c,1,1,ofp);
m++;
if(m==flength)break;
return;
intmain(){
charfilename[100],outputfile[100];
intc;
charb;
printf("
\nHaffman文件压缩软件解压模块测试:
\n"
1解压\n"
2退出\n\n"
请输入序号选择功能:
"
scanf("
%d%c"
&
c,&
b);
if(c==1){
请输入要解压的文件名:
gets(filename);
);
请输入解压后的文件名:
gets(outputfile);
DeCompress(filename,outputfile);
return0;
4.3.3刘琪设计实现
//统计:
读入源文件,统计字符出现的次数(即统计权重),顺便根据权重进行从大到小的//排序(主要的话之后的操作会简单一些);
//动态分配数组存储哈夫曼树
typedefchar**HuffmanCode;
//动态分配数组存储哈夫曼编码表
//下面具体代码在head1.h的函数compress里
FILE*ifp,*ofp;
HTNodeHT[512];
unsignedcharch;
//无符号字符型,可以做数组下表
charbuf[512];
inti,j,f,n,m,s1,s2;
longpt1,flength;
//flength原文件字节个数,pt1压缩文件中哈夫曼//树信息前字节个数
HTNodetmp;
256;
++i)
HT[i].count=0;
ifp=fopen(filename,"
//原文件
if(ifp==NULL)
ofp=fopen(outputfile,"
//压缩文件
if(ofp==NULL)
flength=0;
ch,1,1,ifp);
HT[ch].count++;
flength++;
flength--;
//flength表示字节总数,feof判断,结尾重复一次,需要减一
HT[ch].count--;
//最后一个字节频率减一
512;
i++){//二次定义结点
if(HT[i].count!
=0)
HT[i].b=(unsignedchar)i;
HT[i].b=0;
//NULL
HT[i].parent=-1;
HT[i].lchild=HT[i].rchild=-1;
for(i=0;
i++){//排序,大在前,小在后
for(j=i+1;
if(HT[i].count<
HT[j].count){
tmp=HT[i];
HT[i]=HT[j];
HT[j]=tmp;
4.3.4张晓雨设计实现
设计实现——哈夫曼树构建、哈夫曼编码生成
//构建哈夫曼树功能,生成哈夫曼编码,设有调试函数
}HTNod