哈夫曼编码毕业课程设计报告参考模板.docx

上传人:b****6 文档编号:8483880 上传时间:2023-01-31 格式:DOCX 页数:39 大小:62.16KB
下载 相关 举报
哈夫曼编码毕业课程设计报告参考模板.docx_第1页
第1页 / 共39页
哈夫曼编码毕业课程设计报告参考模板.docx_第2页
第2页 / 共39页
哈夫曼编码毕业课程设计报告参考模板.docx_第3页
第3页 / 共39页
哈夫曼编码毕业课程设计报告参考模板.docx_第4页
第4页 / 共39页
哈夫曼编码毕业课程设计报告参考模板.docx_第5页
第5页 / 共39页
点击查看更多>>
下载资源
资源描述

哈夫曼编码毕业课程设计报告参考模板.docx

《哈夫曼编码毕业课程设计报告参考模板.docx》由会员分享,可在线阅读,更多相关《哈夫曼编码毕业课程设计报告参考模板.docx(39页珍藏版)》请在冰豆网上搜索。

哈夫曼编码毕业课程设计报告参考模板.docx

哈夫曼编码毕业课程设计报告参考模板

(此文档为word格式,下载后您可任意编辑修改!

 

数据结构课程设计报告

 

基于哈夫曼树的文件压缩/解压程序

 

专业班级:

信科

(2)班

姓名:

徐爱娟谢静

学号:

51

50

_31

一需求分析

1.课题要求(实现文件的压缩与解压并计算压缩率)

A.描述压缩基本符号的选择方法

B.运行时压缩原文件的规模应不小于5K

2.设计目标

A软件名称:

基于哈夫曼编码的文件压缩实用程序系统

B软件组成:

huffman.exe

C制作平台及相关调试工具:

WindowsXPsp3MicrosoftVisualC++6.0

D运行环境:

dos/win2K/win2003/winxp/

E性能特点:

1.软件由一个可执行文件组成

huffman.exe为dos系统应用程序,体积小,高效快捷,适用范围广。

2.对单字节(256叶子)进行哈夫曼编码,压缩率良好

3.使用二级缓冲压缩/解压技术,速度比一般算法高

4.可压缩最大体积为4G的文件,达到Fat32文件系统极限

5.文件索引体积比常规算法小50%

二 概要设计 

1.相关函数介绍

1.boolInitFromFile(stringfileadd)从文件中初始化哈夫曼树函数

2.voidHTCreat(HTNodeht[],intn)构造哈夫曼树函数

3.voidHCCreat(HTNodeht[],HCodehcd[],intn)构造哈夫曼编码函数

4.voidConvertFile(HCodehcd[],stringfileadd,stringfileadd2)压缩and写入文件函数

5.voidDecompressionFile(stringfileadd2,stringfileadd3)文件解压函数

6.stringCompression(stringfileadd)压缩函数

7.stringDecompression(stringfileadd2)解压函数

三详细设计

1压缩算法部分

A核心算法:

Huffman编码是一种可变长编码方式,是由美国数学家DavidHuffman创立的,是二叉树的一种特殊转化形式。

编码的原理是:

将使用次数多的代码转换成长度较短的代码,而使用次数少的可以使用较长的编码,并且保持编码的唯一可解性。

Huffman算法的最根本的原则是:

累计的(字符的统计数字*字符的编码长度)为最小,也就是权值(字符的统计数字*字符的编码长度)的和最小。

B哈夫曼树构造算法:

Huffman树是二叉树的一种特殊转化形式。

以下是构件Huffman树的例子:

比如有以下数据,ABFACGCAHGBBAACECDFGFAAEABBB先进行统计A(8)B(6)C(4)D

(1)E

(2)F(3)G(3)H

(1)括号里面的是统计次数

生成Huffman树:

每次取最小的那两个节点(node)合并成一个节点(node),并且将累计数值相加作为新的接点的累计数值,最顶层的是根节点(root)注:

列表中最小节点的是指包括合并了的节点在内的所有节点,已经合并的节点不在列表中

运算的过程如下:

1:

D+H

(2)

2:

DE+H(4)

3:

F+G(6)

4:

C+DEH(8)

5:

B+FG(12)

6:

A+CDEH(16)

7:

ACDEH+BFG(28)

那么转化为Huffman树就是

Huffman树层数

Root

┌┴┐

ACDEHBFG1

┌┴┐┌┴┐

CDEHABFG2

┌┴┐┌┴┐

DEHCFG3

┌┴┐

DHE4

┌┴┐

DH5

取左面是1右面是0则有。

注:

层数就是位数或者说是代码长度,权值=代码长度*该字的统计次数。

代码位数权值

A=10216

B=01212

C=110312

D=1111155

E=111048

F=00139

G=00026

H=1111055

可以看出Huffman代码是唯一可解的(uniquelydecodable),如果你读到110就一定是C,不会有任何一个编码是以110开始的。

如果不使用Huffman算法,而使用普通的编码,结果是什么呢?

Huffman树层数

Root

┌┴┐

ABCDEFGH1

┌┴┐┌┴┐

ABCDEFGH2

┌┴┐┌┴┐┌┴┐┌┴┐

ABCDEFGH3

取左面是1右面是0则有

代码位数权值

A=111324

B=110318

C=101312

D=10033

E=01136

F=01039

G=00139

H=00033

利用Huffman编码得到的权值累计是73,如果利用普通定长编码的话,则要用84字符长度。

从这个比较,可以看出,Huffman是怎么进行压缩的。

C哈夫曼编码结构及算法

编码:

将ABCDEFGH用Huffman树产生的编码对应着写到文件中,并且保留原始的Huffman树,主要是编码段的信息。

一般要编码256个元素的话需要511个单位来储存Huffman树,每个Huffman树都必须有以下的结构:

code,char,left,right,probability(出现次数),通常情况是利用一个数组结构。

因为在解码的时候只需要用到code,所以只需要记录每个元素的编码就可以了。

解码:

利用文件中保存的Huffman编码,一一对应,解读编码,把可变长编码转换为定长编码。

2.解压缩算法部分

A.基于字符匹配的解压算法

读出结点数就能知道哈夫曼树存入部分的总长,方便读出树哈夫曼树(子结点值和权值),就能由次些信息重新构造完整的哈夫曼树,和各结点的哈夫曼编码。

解压时,读取一个字节(8bit)用一个函数转换为8个字符(用一个数组记录,其元素只是一个0或一个1),然后按哈夫曼树从顶向下查找,如果到达叶子结点,就读出该叶子结点的值,放入缓冲区中,如果不是,则继续找,如此重复,直到缓冲区满了,就写入到解压文件中,再循环以上过程,直到处理完所有数据。

B.缓冲输入输出

和压缩时采用1M二级缓冲相同,如果的压缩时也采用此技术,也会有很大的速度优化,当然程序也变得更加复杂。

四用户使用说明

1.运行huffman.exe程序,出现下面的界面

2.选择相应的功能,输入正确文件路径,对文件进行压缩、解压。

五设计心得体会

通过这次课题实验的程序实践,我实在获益匪浅!

数据结构是本学期开展的一门学科,学习好这门学科是非常重要的,在以后的程序设计方面这门学科能给我们很大的帮助。

同时,学习这门学科也是艰辛的,因为它比较难懂,这不仅需要我们要发挥我们的聪明才志,还需要我们在不断的实践中领悟。

六附录

程序清单

在此,给出huffman.exe的程序清单。

#include

#include

#include

#include

usingnamespacestd;

structHTNode

{

chardata;//节点数据

intweight;//权值

intparent;//父亲

intleftchild;//左孩子

intrightchild;//右孩子

};

typedefchar*Code;

HTNode*ht;

Code*hcd;

intmaplist[256];//建立字符与哈夫曼编码的映射

intnodenum=0;//哈夫曼树结点数

intrearnum=0;//哈夫曼编码尾补码

inttextlen=0;//需压缩的文件长度

intcodelen=0;//压缩后的文件的哈夫曼编码总长度

intconstbufferlen=1024;//设置读取缓冲区长度

intclean();//清空节点及编码指针内容

voiddtobin(intnum,intbin[8]);//十进制变换成二进制

voidHTCreate(HTNodeht[],intn);//建立哈夫曼树

voidHCCreat(HTNodeht[],Codehcd[],intn);//提取哈夫曼编码

voidWriteFile(char*tmp);//写入文件

unsignedcharConvertBinary(char*tmp);//变换二进制文件

voidConvertFile(Codehcd[],stringfileadd,stringfileadd2);//压缩并解压文件

boolInitFromFile(stringfileadd);//初始化文件

voidDecompressionFile(stringfileadd2,stringfileadd3);//解压文件

stringCompression(stringfileadd);//压缩文件

stringDecompression(stringfileadd2);//解压文件子函数

///////////////十进制转二进制函数/////////////////

intclean()

{

delete[]ht;

delete[]hcd;

return1;

}

voiddtobin(intnum,intbin[8])

{

inti=0;

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

{

bin[i]=0;

}

i=0;

while(num>0)

{

bin[8-1-i]=num%2;

num=num/2;

i++;

}

}

//////////////////压缩和写入文件//////////////////

voidConvertFile(Codehcd[],stringfileadd,stringfileadd2)

{

fstreaminfile(fileadd.c_str(),ios:

:

in|ios:

:

binary);

fstreamoutfile(fileadd2.c_str(),ios:

:

out|ios:

:

binary);

if(!

infile)cout<<"openfilefail!

"<

if(!

outfile)cout<<"creatfilefail!

"<

//unsigned

charch;

/////////////写入哈夫曼树//////////////

ch=nodenum;

outfile.write(&ch,1);///写入结点数

ch=8;

outfile.write(&ch,1);///写入补位数(预写入)

codelen=0;

outfile.write((char*)&codelen,4);//写入压缩后的文件的哈夫曼编码总长度(预写入)

inth=0;

for(h=0;h

{

outfile.write((char*)&ht[h].data,sizeof(char));

outfile.write((char*)&ht[h].weight,sizeof(int));

}

chartmp[8];//设置缓冲区

charoutbuffer[bufferlen];//设置写入缓冲区

char*tmpcd;

inti=0,j,k,last=0;

charinbuffer[bufferlen];

intreadlen=0;

//infile.seekg(i,ios:

:

beg);

h=0;

do

{

infile.read(inbuffer,bufferlen);

readlen=infile.gcount();

tmpcd=hcd[maplist[(unsignedchar)inbuffer[i]]];

for(i=0;i

{

for(j=last;j<8&&*tmpcd!

='\0';j++)

{

tmp[j]=*tmpcd;

tmpcd++;

}

if(j==8&&*tmpcd=='\0')

{

last=0;

i++;

ch=ConvertBinary(tmp);

//cout<<':

'<<(unsignedint)ch<<'';

outbuffer[h]=ch;

h++;

codelen++;//压缩文件长度加一

if(h==bufferlen)

{

outfile.write(outbuffer,bufferlen);

h=0;

}

if(i

else

{

i=0;

break;

}

}

elseif(j<8&&*tmpcd=='\0')

{

last=j;

i++;

if(i

else

{i=0;

break;

}

/////继续循换////

}

elseif(j==8&&*tmpcd!

='\0')

{

last=0;

//WriteFile(tmp);

ch=ConvertBinary(tmp);

outbuffer[h]=ch;

h++;

codelen++;//压缩文件长度加一

if(h==bufferlen)

{

outfile.write(outbuffer,bufferlen);

h=0;

}

}

}

}

while(readlen==bufferlen);

if(j==8&&readlen

{

outfile.write(outbuffer,h);

}

elseif(j<8&&readlen

{

for(k=j;k<8;k++)

{

tmp[k]='0';

}

ch=ConvertBinary(tmp);

outbuffer[h]=ch;

h++;

outfile.write(outbuffer,h);

codelen++;//压缩文件长度加一

}

cout<

ch=8-j;

rearnum=8-j;

outfile.seekp(1,ios:

:

beg);

outfile.write(&ch,1);//写入真正的补位数

outfile.seekp(2,ios:

:

beg);

outfile.write((char*)&codelen,4);//写入真正的压缩后的文件的哈夫曼编码总长度长度

outfile.close();

infile.close();

}

//////////////构造哈夫曼树////////////

voidHTCreate(HTNodeht[],intn)

{

inti,k,lnode,rnode;

intmin1,min2;

for(i=0;i<2*n-1;i++)

{

ht[i].parent=ht[i].rightchild=ht[i].leftchild=-1;

}

for(i=n;i<2*n-1;i++)

{

min1=min2=;

lnode=rnode=-1;

for(k=0;k<=i-1;k++)

{

if(ht[k].parent==-1)

{

if(ht[k].weight

{

min2=min1;

min1=ht[k].weight;

rnode=lnode;

lnode=k;

}

elseif(ht[k].weight

{

min2=ht[k].weight;

rnode=k;

}

}

}

ht[lnode].parent=i;

ht[rnode].parent=i;

ht[i].weight=ht[lnode].weight+ht[rnode].weight;

ht[i].leftchild=lnode;

ht[i].rightchild=rnode;

}

}

///////////构造哈夫曼编码/////////////

voidHCCreat(HTNodeht[],Codehcd[],intn)

{

inti,p,c;

Codehc;

hc=newchar[n];

intstart,tmplen;

for(i=0;i

{

tmplen=0;

start=n-1;

hc[start]='\0';

c=i;

p=ht[i].parent;

while(p!

=-1)

{

if(ht[p].leftchild==c)//是左孩子结点

{

hc[--start]='0';

tmplen++;

}

else

{

hc[--start]='1';

tmplen++;

}

c=p;

p=ht[p].parent;

}

hcd[i]=newchar[n-start];

strcpy(hcd[i],&hc[start]);

}

delete[]hc;

}

voidWriteFile(char*tmp)

{

inti;

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

cout<

cout<<'';

tmp="";

}

unsignedcharConvertBinary(char*tmp)

{

charch=0;

inti;

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

{

ch=(unsignedchar)pow(2.0,8-i-1)*(tmp[i]-48)+ch;

}

returnch;

}

//////////////打开文件//////////////

boolInitFromFile(stringfileadd)

{

fstreaminfile(fileadd.c_str(),ios:

:

binary|ios:

:

in);

if(!

infile){cout<<"error!

"<

inttable[256];

inti,j;

intlen=0,num=0;

unsignedcharch;

for(i=0;i<256;i++){table[i]=0;maplist[i]=-1;}

intreadlen=0;

charbuffer[bufferlen];//设置读取缓冲区,加快读取速度

do

{

infile.read(buffer,bufferlen);

i=0;

readlen=infile.gcount();

while(i

{

ch=(unsignedchar)buffer[i];

table[ch]++;

len++;

i++;

}

}

while(readlen==bufferlen);

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

{

if(table[i]!

=0)num++;

}

ht=newHTNode[2*num-1];

hcd=newCode[num];

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

{

if(table[i]!

=0)

{

ht[j].data=i;

ht[j].weight=table[i];

maplist[i]=j;//建立字符与哈夫曼编码的映射

j++;

}

}

nodenum=num;

textlen=len;

infile.clear();

infile.close();

return1;

}

/////////////从文件解压////////////////////

voidDecompressionFile(stringfileadd2,stringfileadd3)

{

//cout<<"............解压并输出新文件过程:

"<

fstreaminfile(fileadd2.c_str(),ios:

:

in|ios:

:

binary);

fstreamoutfile(fileadd3.c_str(),ios:

:

out|ios:

:

binary);

cout<

/////////////////读出哈夫曼树的数据/////////////

inth=0;

charbuffer[bufferlen];//读入文件的缓冲区

charoutbuffer[bufferlen];//写入文件的缓冲区

infile.read(buffer,1);

nodenum=(unsignedchar)*buffer;//哈夫曼树结点数

if(nodenum==0)nodenum=256;

infile.read(buffer,1);

rearnum=(unsignedchar)*buffer;

infile.read((char*)&codelen,4);

//cout<<"读出哈夫曼树数据...."<

ht=newHTNode[2*nodenum-1];

hcd=newCode[nodenum];

//hcdlen=newint[nodenum];

for(h=0;h

{

infile.read(&ht[h].data,1);

infile.read((char*)&ht[h].weight,4);

}

//////构走哈夫曼树///////

HTCreate(ht,nodenum);

//////构造哈夫曼编码/////

HCCreat(ht,hcd,nodenum);

///////////////////////解压并输出解压文件////////////////////////

char*buffertmp=newchar;

intbin[8],j=0,i=0;

intcoderead=0;//记录以度的长度,用于判断何时达到文件最后一字节(用codelen比较)

intreadlen=0

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

当前位置:首页 > 经管营销 > 经济市场

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

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