数据结构哈夫曼压缩软件设计实验报告正文终稿.docx

上传人:b****3 文档编号:4596548 上传时间:2022-12-07 格式:DOCX 页数:41 大小:827.71KB
下载 相关 举报
数据结构哈夫曼压缩软件设计实验报告正文终稿.docx_第1页
第1页 / 共41页
数据结构哈夫曼压缩软件设计实验报告正文终稿.docx_第2页
第2页 / 共41页
数据结构哈夫曼压缩软件设计实验报告正文终稿.docx_第3页
第3页 / 共41页
数据结构哈夫曼压缩软件设计实验报告正文终稿.docx_第4页
第4页 / 共41页
数据结构哈夫曼压缩软件设计实验报告正文终稿.docx_第5页
第5页 / 共41页
点击查看更多>>
下载资源
资源描述

数据结构哈夫曼压缩软件设计实验报告正文终稿.docx

《数据结构哈夫曼压缩软件设计实验报告正文终稿.docx》由会员分享,可在线阅读,更多相关《数据结构哈夫曼压缩软件设计实验报告正文终稿.docx(41页珍藏版)》请在冰豆网上搜索。

数据结构哈夫曼压缩软件设计实验报告正文终稿.docx

数据结构哈夫曼压缩软件设计实验报告正文终稿

东北大学信息科学与工程学院

数据结构课程设计报告

题目哈夫曼压缩软件设计

课题组长王健

课题组成员张颖刘琪张晓雨

专业名称计算机科学与技术

班级计1307

指导教师杨雷

2015年1月

 

课程设计任务书

题目:

哈夫曼压缩软件设计

问题描述:

采用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。

利用哈夫曼编码的数据压缩技术,设计文本格式的压缩软件或位图格式的压缩软件。

设计要求:

设计基于哈夫曼编码的压缩软件。

(1)采用静态链表的二叉树等数据结构的类实现。

(2)创建哈夫曼树。

(3)哈夫曼编码和译码。

(4)源码、编码和压缩后的信息均以文件形式保存。

(5)软件时间和空间性能分析。

(6)基于哈夫曼编码的位图压缩软件设计(可选)。

            

指导教师签字:

年  月  日

1课题概述4

1.1课题任务4

1.2课题原理4

1.3相关知识4

2需求分析5

2.1课题调研5

2.2用户需求分析5

3方案设计5

3.1总体功能设计5

3.2数据结构设计6

3.3函数原型设计6

3.4主算法设计7

3.5用户界面设计9

4方案实现12

4.1开发环境与工具12

4.2程序设计关键技术12

4.3个人设计实现(按组员分工)

4.3.1王健设计实现12

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)采用静态链表的二叉树等数据结构。

(2)创建哈夫曼树。

(3)哈夫曼编码和译码。

(4)源码、编码和压缩后的信息均以文件形式保存。

(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{

unsignedcharb;/*thecharactor*/

longcount;/*thefrequency*/

longparent,lch,rch;/*makeatree*/

charbits[256];/*thehaffumancode*/

}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

if(ch==HT[i].b)

break;

strcat(buf,HT[i].bits);//字符串连接函数

j=strlen(buf);

ch=0;

while(j>=8){//每满八位,存储至文件for(i=0;i<8;i++){

if(buf[i]=='1')

ch=(ch<<1)|1;//左移一位,用零补,并加一

else

ch=ch<<1;//左移一位,用零补

}

fwrite(&ch,1,1,ofp);

pt1++;

strcpy(buf,buf+8);//buf前八位被覆盖

j=strlen(buf);

}

if(f==flength)//所有哈夫曼编码都被读完

break;

}

if(j>0){//flength不是八的整数倍,用0补全strcat(buf,"00000000");

for(i=0;i<8;i++){

if(buf[i]=='1')

ch=(ch<<1)|1;

else

ch=ch<<1;

}

fwrite(&ch,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);//pt1个字节后存放哈夫曼树结点//数

for(i=0;i

ch=strlen(HT[i].bits);

fwrite(&ch,1,1,ofp);//接着存储其哈夫曼编码数

j=strlen(HT[i].bits);

if(j%8!

=0){//每个叶子结点哈夫曼编码不足八位,左移,并补零for(f=j%8;f<8;f++)

strcat(HT[i].bits,"0");

}

while(HT[i].bits[0]!

=0){

ch=0;

for(j=0;j<8;j++){

if(HT[i].bits[j]=='1')

ch=(ch<<1)|1;

else

ch=ch<<1;

}

strcpy(HT[i].bits,HT[i].bits+8);

fwrite(&ch,1,1,ofp);//将哈夫曼编码信息存入压缩文件΄

}

}

fclose(ifp);

fclose(ofp);

}

4.3.1.2实现部分——MFC实现图形界面

//类

ClassCHuffmanDlg:

publicCDialog{}//主界面类

Classmenu:

publicCDialog{}//菜单界面类

Classcompress:

publicCDialog{}//压缩界面类

ClassDecompress:

publicCDialog{}//解压界面类

//主界面类中的函数成员

afx_msgvoidOnBnClickedOk();//鼠标按下功能选项按钮

afx_msgvoidOnBnClickedCancel();//鼠标按下退出

//菜单界面类中的函数成员

afx_msgvoidOnOk2();//鼠标按下解压按钮

afx_msgvoidOnBnClickedOk();//鼠标按下压缩按钮

afx_msgvoidOnBnClickedButton1();//鼠标按下取消按钮

//压缩界面类中的函数成员

afx_msgvoidOnButton1();//鼠标按下查找1按钮(弹出文件查找界面)

afx_msgvoidOnBnClickedButton2();//鼠标按下查找2按钮(弹出保存文//件路径界面)

afx_msgvoidOnEnChangeEdit3();//压缩文件命名编辑框

afx_msgvoidOnBnClickedButton3();//鼠标按下取消按钮

afx_msgvoidOnBnClickedOk();//鼠标按下确定按钮

//解压界面类中的函数成员

afx_msgvoidOnButton1();//鼠标按下查找1按钮(弹出文件查找界面)

afx_msgvoidOnBnClickedButton2();//鼠标按下取消按钮

afx_msgvoidOnEnChangeEdit2();//鼠标按下取消按钮

afx_msgvoidOnBnClickedOk();//鼠标按下确定按钮

afx_msgvoidOnBnClickedButton4();//鼠标按下查找2按钮(弹出保存文//件路径界面)

4.3.2张颖设计实现

实现部分——解压

//解压功能,此设有调试函数

#include

#include

#include

#ifndefHEAD2_H

#defineHEAD2_H

structhead{

unsignedcharb;/*thecharactor*/

longcount;/*thefrequency*/

longparent,lch,rch;/*makeatree*/

charbits[256];/*thehaffumancode*/

}header[512],tmp;

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)

exit(0);

fread(&flength,sizeof(long),1,ifp);//读取前四个字节,//flength为原文件字节数

fread(&f,sizeof(long),1,ifp);//f为压缩文件中哈夫曼树信息前//的字节数

fseek(ifp,f,SEEK_SET);

fread(&n,sizeof(long),1,ifp);//读取哈夫曼树叶子结点数n

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;

else

m=p/8;

for(j=0;j

fread(&c,1,1,ifp);//读取该叶子结点哈夫曼编码

f=c;

itoa(f,buf,2);//将任意类型的数字转换为字符串,2进制编//码,存储在buf中

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);//ifp开始指向原文件内容信息

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--)

strcat(bx,"0");

strcat(bx,buf);

}

for(i=0;i

if(memcmp(header[i].bits,bx,header[i].count)==0)//比较内存区域header[i].bits和bx的前count个字节

break;

strcpy(bx,bx+header[i].count);

c=header[i].b;

fwrite(&c,1,1,ofp);

m++;

if(m==flength)break;

}

fclose(ifp);

fclose(ofp);

return;

}

intmain(){

charfilename[100],outputfile[100];

intc;

charb;

printf("\nHaffman文件压缩软件解压模块测试:

\n");

printf("1解压\n");

printf("2退出\n\n");

printf("请输入序号选择功能:

");

scanf("%d%c",&c,&b);

if(c==1){

printf("请输入要解压的文件名:

");

gets(filename);

printf("\n");

printf("请输入解压后的文件名:

");

gets(outputfile);

DeCompress(filename,outputfile);

}

else

return0;

}

4.3.3刘琪设计实现

//统计:

读入源文件,统计字符出现的次数(即统计权重),顺便根据权重进行从大到小的//排序(主要的话之后的操作会简单一些);

typedefstructHTNode{

unsignedcharb;/*thecharactor*/

longparent,lchild,rchild;/*makeatree*/

charbits[256];/*thehaffumancode*/

longcount;/*thefrequency*/

}HTNode,*HuffmanTree;//动态分配数组存储哈夫曼树

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;

for(i=0;i<256;++i)

HT[i].count=0;

ifp=fopen(filename,"rb");//原文件

if(ifp==NULL)

exit(0);

ofp=fopen(outputfile,"wb");//压缩文件

if(ofp==NULL)

exit(0);

flength=0;

while(!

feof(ifp)){

fread(&ch,1,1,ifp);

HT[ch].count++;

flength++;

}

flength--;//flength表示字节总数,feof判断,结尾重复一次,需要减一

HT[ch].count--;//最后一个字节频率减一

for(i=0;i<512;i++){//二次定义结点

if(HT[i].count!

=0)

HT[i].b=(unsignedchar)i;

else

HT[i].b=0;//NULL

HT[i].parent=-1;

HT[i].lchild=HT[i].rchild=-1;

}

for(i=0;i<256;i++){//排序,大在前,小在后

for(j=i+1;j<256;j++){

if(HT[i].count

tmp=HT[i];

HT[i]=HT[j];

HT[j]=tmp;

}

}

}

 

4.3.4张晓雨设计实现

设计实现——哈夫曼树构建、哈夫曼编码生成

//构建哈夫曼树功能,生成哈夫曼编码,设有调试函数

#include

#include

#include

typedefstructHTNode{

unsignedcharb;/*thecharactor*/

longparent,lchild,rchild;/*makeatree*/

charbits[256];/*thehaffumancode*/

longcount;/*thefrequency*/

}HTNode,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 教学研究 > 教学案例设计

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1