用赫夫曼编码完成文件全资料压缩Word格式文档下载.docx

上传人:b****4 文档编号:18505907 上传时间:2022-12-18 格式:DOCX 页数:20 大小:264.90KB
下载 相关 举报
用赫夫曼编码完成文件全资料压缩Word格式文档下载.docx_第1页
第1页 / 共20页
用赫夫曼编码完成文件全资料压缩Word格式文档下载.docx_第2页
第2页 / 共20页
用赫夫曼编码完成文件全资料压缩Word格式文档下载.docx_第3页
第3页 / 共20页
用赫夫曼编码完成文件全资料压缩Word格式文档下载.docx_第4页
第4页 / 共20页
用赫夫曼编码完成文件全资料压缩Word格式文档下载.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

用赫夫曼编码完成文件全资料压缩Word格式文档下载.docx

《用赫夫曼编码完成文件全资料压缩Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《用赫夫曼编码完成文件全资料压缩Word格式文档下载.docx(20页珍藏版)》请在冰豆网上搜索。

用赫夫曼编码完成文件全资料压缩Word格式文档下载.docx

数据对象D:

是具有一样特性的元素的集合。

数据关系R:

假设D为空集,如此称为空二叉树;

假设D仅含一个数据元素,如此R为空集,否如此R 

{H}, 

H是如下二元关系:

1〕在D中存在唯一的称为根的数据元素root,它在关系H下无前驱;

2〕 

假设D 

– 

{root} 

≠ 

Φ,如此存在D 

的一个划分Dl 

Dr 

,Dl∩Dr 

=Φ;

3〕 

假设Dl≠Φ,如此Dl 

中存在惟一的数据元素x,<

root, 

xl>

∈ 

H,且存在Dl 

上的关系Hl 

<

H;

假设Dr 

Φ,如此Dr 

中存在惟一的数据元素xr 

,<

xr>

H,且存在Dr 

上的关系Hr 

4〕〔Dl,{ 

Hl、}〕是一棵符合本定义的二叉树,称为根root的左子树,〔Dr,{ 

Hr、}〕是一棵符合本定义的二叉树,称为根root的右子树。

根本操作P:

InitBitree(&

T);

构造空二叉树。

CreateBitree(&

二叉树存在。

按输入格式构造二叉树。

Value(T, 

e);

二叉树存在,e是T中某个结点。

返回结点e的值。

Assign(&

T, 

&

e, 

value);

结点e赋值为value 

Parent(T, 

假设e是T的非根结点,如此返回它的双亲,否如此返回“空〞。

LeftChild(T, 

返回e的左孩子。

假设e无左孩子,如此返回“空〞。

RightChild(T, 

返回e的右孩子。

假设e无右孩子,如此返回“空〞。

}ADTBinaryTree

3.赫夫曼树和赫夫曼编码的存储表示:

typedefstruct{

chardata;

intweight;

intparent,lchild,rchild;

}HTNode,*HuffmanTree;

//动态分配数组存储赫夫曼树

typedefchar**HuffmanCode;

//动态分配数组存储赫夫曼编码。

4.函数的调用关系图:

main()->

pressFile()->

HuffmanCoding()->

Select()

->

WriteFile()->

CoToCh()

->

DepressFile()->

ChToCo(ame);

translation()

三、调试分析

1.文件中字符数目可能非常大,不能用一个整的数组来存,所以需要从文件中一个字符一个字符来读取处理。

2.为解决文件中字符出现的不确定性,用数组character[256]来记录相应ASCII的字符出现次数,统计完后,将出现次数非零的字符存在数组v[]中,并将它们的权值存在数组w[]中。

3.在将赫夫曼编码翻译为字符中,translation〔〕中函数的变量ch,在运算中应该变它的对应的值,即为,传参应为char&

ch,而不应为charch。

4.将哈夫曼八位一组转为十进制时,01串中个数不一定为8的倍数,先遍历文件,统计01串中元素个数,将该个数除以8的余数拿出来,放入压缩文件的第一位,在依次将等于余数个数的01字符直接放入压缩文件,之后的01串为8的整数倍。

5.读取压缩后的乱码是,可能读出负数,假设读出负数,让这个负数加上256再转化为2进制的01串。

四、测试结果

1.

如图,4为余数。

压缩率:

125%

可见,当文件中元素个数小于8时,压缩文件反而会增大。

2.

7/30

3.

9/30。

4.

压缩率接近百分之五十。

总和2、3、4可见,可见,一样大小的文件,其中元素分布越集中,压缩率越大。

5.

五、附录

源程序文件清单:

#defineMAXWEIGHT2147483647

#defineMAXASCII255

#defineMAXNAME100

#include<

stdio.h>

stdlib.h>

string.h>

memory.h>

chardata;

intweight;

intparent,lchild,rchild;

voidSelect(HuffmanTreeHT,intindex,int&

s1,int&

s2)

{//从序号为1~index的结点中选出两个最小的且没有双亲的结点。

intw1,w2,t,i;

s1=0;

s2=0;

w1=MAXWEIGHT;

w2=MAXWEIGHT;

for(i=1;

i<

=index;

i++)

{

if(HT[i].parent==0)

{

if(HT[i].weight<

w1)

{

s2=s1;

w2=w1;

s1=i;

w1=HT[i].weight;

}

elseif(HT[i].weight<

w2)

s2=i;

w2=HT[i].weight;

}

}

}

intHuffmanCoding(HuffmanTree&

HT,HuffmanCode&

HC,char*v,int*w,intn)

{//v存放需要编码的n个字符,w存放对应的权值,

//构造赫夫曼树,并求出n个字符的赫夫曼编码。

if(n==0)

{//没有合法字符时

printf("

没有需要编码的字符!

"

);

return-1;

}

if(n==1)

{//只有一个合法字符时

HC=(HuffmanCode)malloc((n+1)*sizeof(char*));

HC[1]=(char*)malloc(3*sizeof(char));

HC[1][0]=*v;

HC[1][1]='

0'

;

HC[1][2]=0;

HT=(HuffmanTree)malloc(2*sizeof(HTNode));

HT[1].parent=0;

HT[1].lchild=0;

HT[1].rchild=0;

HT[1].weight=*w;

HT[1].data=*v;

return0;

ints1,s2,m,i;

m=2*n-1;

HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));

HuffmanTreep;

HT->

weight=m;

for(p=HT+1,i=1;

=n;

i++,p++,w++,v++)

p->

weight=*w;

lchild=0;

rchild=0;

parent=0;

data=*v;

for(;

=m;

i++,p++)

weight=0;

for(i=n+1;

{//在HT[1..i-1]选择parent为0而且weight最小的

//两个结点且weight最小的两个结点,其序号分别

//为s1和s2

Select(HT,i-1,s1,s2);

HT[s1].parent=i;

HT[s2].parent=i;

HT[i].lchild=s1;

HT[i].rchild=s2;

HT[i].weight=HT[s1].weight+HT[s2].weight;

//---从叶子到根逆向求每个字符的霍夫曼编码---

char*cd;

intstart,c,f;

HC=(HuffmanCode)malloc((n+1)*sizeof(char*));

cd=(char*)malloc(n*sizeof(char));

cd[n-1]=0;

start=n-1;

for(c=i,f=HT[i].parent;

f!

=0;

c=f,f=HT[f].parent)

if(HT[f].lchild==c)cd[--start]='

elsecd[--start]='

1'

HC[i]=(char*)malloc((n-start+1)*sizeof(char));

strcpy(HC[i]+1,&

cd[start]);

HC[i][0]=v[i-1-n];

free(cd);

return1;

voidtranslation(FILE*fp1,FILE*fp2,char&

ch,HuffmanTreeHT,inti,intf)

{//逐字翻译压缩文件中的赫夫曼编码

if(HT[i].lchild==0&

HT[i].rchild==0)

{//假设为叶子结点,如此成功翻译一个字符,将它输入到解压文件中

fputc(HT[i].data,fp2);

if(f==0)ch=fgetc(fp1);

return;

if(ch=='

{//假设为0,如此探索左孩子

f=1;

ch=fgetc(fp1);

translation(fp1,fp2,ch,HT,HT[i].lchild,f);

elseif(ch=='

{//假设为1,如此探索左孩子

translation(fp1,fp2,ch,HT,HT[i].rchild,f);

}

voidCoToCh(charame[])

{

FILE*fp1,*fp2;

charDName[MAXNAME]={0},ch;

//存放压缩后的文件名

intBin[7]={0},asc;

//八个01一组放入Bin串;

二进制对应的ASCII值

inti,j,num=0,r;

printf("

请输入你希望得到的压缩后的文件名:

gets(DName);

fp1=fopen(ame,"

rb"

fp2=fopen(DName,"

wb"

while(!

feof(fp1))//计算0,1的数量

{

num++;

num--;

rewind(fp1);

r=num%8;

//八个一组多余出来的01

fputc(r+'

fp2);

//将多出来的数量的值放在压缩文件第一位

for(j=1;

j<

=r;

j++)

{//后面r位原封不动的将01复制进来

fputc(ch,fp2);

feof(fp1))

i=0;

asc=0;

memset(Bin,0,sizeof(Bin));

while(!

feof(fp1)&

=7)

ch=fgetc(fp1);

Bin[i]=ch-'

i++;

}

if(feof(fp1))break;

for(j=0;

=i-1;

asc=asc*2+Bin[j];

fputc(asc,fp2);

fclose(fp1);

fclose(fp2);

压缩后的文件名为:

puts(DName);

voidWriteFile(HuffmanCodeHC,charFName[],intk,charv[])

{//将被压缩的文件容写入另一个文件

charame[MAXNAME]={0},ch;

strcpy(ame,"

CP"

strcpy(ame+2,FName);

//哈夫曼编码文件命名为"

'

CP'

+原文件名"

fp1=fopen(FName,"

fp2=fopen(ame,"

while

(1)

inti;

for(inti=0;

=k-1;

if(ch==v[i])

fputs(HC[i+1]+1,fp2);

//将赫夫曼编码写入哈夫曼编码文件

CoToCh(ame);

voidpressFile(HuffmanTree&

HC,int&

k)

{//读取文件中的字符,构造哈夫曼曼树,得到每个字符的哈夫曼编码

FILE*fp;

intflag;

charch,v[MAXASCII+1],FName[MAXNAME];

//v存放出现的字符

intcharacter[MAXASCII+1]={0};

//统计每种字符出现的次数

intw[MAXASCII+1];

//w放字符的权值

请键入要运行的操作编号:

\n1.压缩已有的文件\n2.建立新文件,输入容并进展压缩\n"

scanf("

%d"

&

flag);

//选择操作

getchar();

if(flag==1)

请键入需要压缩的文件名:

gets(FName);

fp=fopen(FName,"

r"

elseif(flag==2)

请键入文件容:

\n"

w"

while(ch!

='

\n'

scanf("

%c"

ch);

fputc(ch,fp);

fclose(fp);

else

警告:

无此操作项!

{//逐个读取文件中的字符,数组character对应字符位置上+1

ch=fgetc(fp);

if(feof(fp))break;

character[ch]++;

for(inti=0;

=MAXASCII-1;

{//假设某字符在在文件中出现,如此把它放入v,并把权值计入一样序号的w

if(character[i]!

=0)

v[k]=i;

w[k++]=character[i];

文件中出现的字符与它们的权值:

%c-%d;

v[i],w[i]);

HuffmanCoding(HT,HC,v,w,k);

fclose(fp);

上述字符对应的哈夫曼编码:

for(inti=1;

=k;

puts(HC[i]);

WriteFile(HC,FName,k,v);

voidChToCo(charDName[],charame[])

intr,i,j,Bin[7]={0},asc;

charch;

fp1=fopen(DName,"

RCP"

strcpy(ame+3,DName);

r=fgetc(fp1)-'

asc=(int)ch;

if(asc<

0)asc+=256;

for(i=7;

i>

i--)

Bin[i]=asc%2;

asc=asc/2;

for(i=0;

=7;

fputc(Bin[i]+'

voidDepressFile(HuffmanTreeHT,intk)

{//解压函数

charDName[MAXNAME],FName[MAXNAME],ame[MAXNAME]={0},ch;

intr;

请键入需要解压的文件名:

〔注意:

文件中的字符权值需与上述一样!

〕"

请输入解压后希望得到的文件名:

gets(FName);

解压后的文件名为:

puts(FName);

ChToCo(DName,ame);

fp2=fopen(FName,"

ch=fgetc(fp1);

{//到压缩文件末尾完毕

translation(fp1,fp2,ch,HT,2*k-1,0);

intmain()

HuffmanTreeHT;

HuffmanCodeHC;

intk=0,flag;

pressFile(HT,HC,k);

\n1.完毕进程\n2.解压文件\n"

if(flag==1){}

DepressFile(HT,k);

else

return0;

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

当前位置:首页 > 人文社科 > 广告传媒

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

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