基于赫夫曼编码的文本压缩程序Word文件下载.docx

上传人:b****5 文档编号:21101692 上传时间:2023-01-27 格式:DOCX 页数:21 大小:22.40KB
下载 相关 举报
基于赫夫曼编码的文本压缩程序Word文件下载.docx_第1页
第1页 / 共21页
基于赫夫曼编码的文本压缩程序Word文件下载.docx_第2页
第2页 / 共21页
基于赫夫曼编码的文本压缩程序Word文件下载.docx_第3页
第3页 / 共21页
基于赫夫曼编码的文本压缩程序Word文件下载.docx_第4页
第4页 / 共21页
基于赫夫曼编码的文本压缩程序Word文件下载.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

基于赫夫曼编码的文本压缩程序Word文件下载.docx

《基于赫夫曼编码的文本压缩程序Word文件下载.docx》由会员分享,可在线阅读,更多相关《基于赫夫曼编码的文本压缩程序Word文件下载.docx(21页珍藏版)》请在冰豆网上搜索。

基于赫夫曼编码的文本压缩程序Word文件下载.docx

字符第一字节机内码/ASCII第二字节机内码权重

的18119620a9709

把17620914

表1772375

班1762241

补1781852

百17621417

防18319212

飞1832019

博17816913

包1762522

才1781976

方1831898

拜1762213A6503

份1832215

必1772165

英文字符在计算机中是以标准ASCII码进行表示,一个英文字符占一个字节空间,编码范围为0~127;

汉字在计算机中是以GB2312编码进行表示。

每个汉字占两个字节存储空间,汉字的存储使用机内码,各字节的机内码编码范围为160~254。

现在需要考虑使用怎样的数据结构来存放这些字符,如果采用如下简单的数据结构存放:

typedefstruct

{

chardata[3];

//存放字符

intinternal_code1;

//存放第一字节的机内码/ASCII码

intinternal_code2;

//存放第二字节的机内码,英文默认为0intweight;

//存放字符的权重

char*code;

//字符的赫夫曼编码

}CodeList,*CodePList;

分析所要处理的字符数据会发现:

许多的字符的第一字节的机内码相同,如"

防"

、"

飞"

方"

份"

,第一字节机内码都是183。

这是因为汉字是通过划分区号和位号来表示的,所有汉字被划分成了94个区,94个位,所以当汉字属于同一个区,那么它的第一字节机内码就会相同。

如果采用如上的数据结构建立的线性表来存放处理字符,就会存在大量数据冗余。

在这种情况下,就有必要为特定的数据设计合适的数据结构。

通过分析,采用如下数据结构:

charinternal_code;

//存放第二字节机内码

//存放字符的赫夫曼编码

}InternalCode;

intcount;

//已编码字符数

//存放第一字节机内码

InternalCode*internal_code_address;

//第二字节机内码及字符的

}HuffmanCode,*HuffmanPCode;

//赫夫曼编码的地址

该结构的优点:

当汉字的第一字节机内码相同,则该第一字节机内码只会被存储一次,从而消除汉字第一字节机内码存储的冗余,而且可以方便的使用折半查找快速检索编码表来确定字符的赫夫曼编码。

采用该数据结构对表1数据进行表示如图1。

图1编码表HC的存储结构

这种数据结构形式上类似于图的邻接表结构,功能上类似于哈希表的链地址法。

但邻接表的表结点采用链式存储,而图1的表结点和头结点都采用线性表储存。

图1中编码表HC的内码1是纵向非递减排列,内码2是横向非递减排列。

HC[i].count–HC[i–1].count等于HC[i]实际存储的字符数量。

例如,HC[3]中字符数为7,HC[2]中字符数为2,则HC[3]存放了5个字符,这5个字符拥有相同的第一字节机内码176。

程序执行压缩操作详细过程:

当程序从文件中读取一个字符后,通过字符的编码范围分析该字符是属于ASCII还是GB2312,若是ASCII编码,增加编码表HC纵向表长,将该字符的ASCII码按非递减次序插入到内码1处,并将当前位置的字符数加1,并置内码2默认为0;

如果是汉字,首先通过折半查找算法纵向查找编码表HC的内码1成员,若当前汉字第一字节机内码已经出现过,则折半查找返回该机内码1在HC表中的位置,增加当前位置的横向表长,将汉字的第二字节机内码按非递减次序插入当前位置的内码2处。

否则将汉字的第一字节机内码按非递减次序插入HC表的内码1区域,第二字节机内码直接插入内码2处。

在读取文件的同时记录文件中各字符出现的频率,当编码表HC表构建完成,此时w={3,9,14,3,1,2,17,5,5,13,2,6,20,9,8,5,12}。

依次从w中选择权重最小并且双亲为0的两个结点,根据这两个结点生成新的结点,新结点的权重为这两个最小结点的和,新结点的左右子树为这两个结点在w中的位置。

根据表1数据构建赫夫曼树如图2所示。

赫夫曼树存储结构的初始状态如图3(a),终结状态如图3(b)。

图2根据表1构造的赫夫曼树

图3(a)HT初始状态图3(b)HT终止状态

根据生成的赫夫曼树对HC表中的字符进行编码,编码的方法:

从该叶子到根逆向求该字符的编码。

例如图2中"

把"

的权值为14,对应的编码为:

"

000"

将得到的赫夫曼编码写入HC[i].internal_code_address[j].code指向的区域。

当字符编码完成之后,打开压缩文件,将赫夫曼树HT中除权重以外的数据(解码无需权重信息)写入压缩文件中,作为下一次解压缩的解码表。

再次打开要压缩的文本文件,读取文件中的字符,根据编码的范围确定该字符是ASCII还是GB2312,如果ASCII则调用折半查找函数,在编码表HC中进行纵向查找,查找此ASCII出现的位置p1,该字符的编码为HC[p1].internal_code_address[1].code;

如果字符是汉字,则调用折半查找先纵向查找该汉字的第一字节机内码在HC中的位置p1,然后从HC[p1].internal_code_address开始横向查找该汉字的第二字节机内码的位置p2,这样就得到了该汉字的赫夫曼编码为HC[p1].internal_code_address[p2].code因为赫夫曼编码在HC表中是以字符串形式存放(因为计算机的基本储单位是字节,如果以位存放,需要另设一个空间来表示未编码的位空间大小)。

所以需要将字符串"

0101"

转换为二进制0101写入文件。

因为每个赫夫曼编码的长度是不一样的,假设某字符的赫夫曼长度为4,则将该编码写入一个字节后,还剩余4个位,则下一次可以继续从第5个位开始写入,当所有字符的编码都写入完毕后,最后一个字节并不一定会用完,所以需要附设一个字节来记录最后一个字符编码实际写入的编码位数。

编码文件的结构如下图所示:

图4压缩文件存储结构

程序解压文件:

打开压缩文件,取出压缩文件的解码表长度N,根据N读取N条解码表记录,重建解码表HT,然后读取压缩数据DATA,解码的过程是从根出发,按DATA数据的0或1确定找左子树还是右子树,直至叶子结点,便求得了DATA相应的字符。

将字符写入文件,直至所有DATA数据处理完毕,整个解压过程结束。

三、程序源代码

1.头文件CourseDesign.h

#ifndef_COURSEDESIGN_H_

#define_COURSEDESIGN_H_

//---Huffman树存储结构

charch[3];

unsignedintweight;

unsignedintparent,lchild,rchild;

}HTNode,*HuffmanTree;

//--Huffman编码表存储结构

//---解码表存储结构

unsignedintlchild,rchild;

}DecodeList,*DecodePList;

//--辅助数组,置/取一个字节的指定位

conststaticunsignedcharmask[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};

templateclassTstaticintxj_Search_Bin(intkey,TL,intlow,inthigh);

templateclassTstaticvoidxj_InsertSort(TL,intstart,intend);

voidxj_Select(constHuffmanTreeHT,intn,int&

s1,int&

s2);

voidxj_Statistics(HuffmanPCode&

HC,intinternal_code1,intinternal_code2,int(*FrequencyMeter)[255],int&

n);

boolxj_Init(char*filename,HuffmanPCode&

HC,int*&

w,int&

voidxj_CreateHuffmanTree(HuffmanTree&

HT,constHuffmanPCodeHC,constint*w,intn);

voidxj_HuffmanCoding(constHuffmanTreeHT,HuffmanPCodeHC,intn);

boolxj_Compress(char*ifilename,char*ofilename,constHuffmanPCodeHC,constHuffmanTreeHT,intn);

boolxj_DeCompress(char*ifilename,char*ofilename);

voidxj_Interface();

#endif2.函数实现文件CourseDesign.cpp

#include"

CourseDesign.h"

#includeiostream

#includefstream

#includeiomanip

#includemalloc.h

#includestring.husingnamespacestd;

//---折半查找--

templateclassT

intxj_Search_Bin(intkey,TL,intlow,inthigh)

intmid=0;

intinternal_code;

while(low=high)

mid=(low+high)/2;

internal_code=int(L[mid].internal_code&

0xFF);

if(key==internal_code)

returnmid;

}

elseif(internal_codekey)

high=mid-1;

else

low=mid+1;

return0;

//--对HC表的字符域做插入非递减排序---

voidxj_InsertSort(TL,intstart,intend)

inti;

L[0]=L[end];

i=end-1;

while(i=start&

&

int(L[i].internal_code&

0xFF)int(L[0].internal_code&

0xFF))

L[i+1]=L[i];

i--;

L[i+1]=L[0];

//---寻找权重最小的两个结点--

s2)

inti=0;

s1=s2=0;

for(i=1;

i=n;

++i)

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

if(s1==0)

s1=i;

elseif(s2==0)

s2=i;

elseif(HT[i].weightHT[s1].weight||HT[i].weightHT[s2].weight)

s1=HT[s1].weightHT[s2].weight?

s1:

s2;

//--构建HC.internal_code以及HC.internal_code_address结构---

n)

intposition;

if(internal_code1128)

if(FrequencyMeter[internal_code1][0]==0)

++n;

HC=(HuffmanPCode)realloc(HC,(n+1)*sizeof(HuffmanCode));

HC[n].internal_code=internal_code1;

HC[n].count=1;

HC[n].internal_code_address=(InternalCode*)malloc(2*sizeof(InternalCode));

HC[n].internal_code_address[1].internal_code=0;

//0号单元未用

xj_InsertSort(HC,1,n);

++FrequencyMeter[internal_code1][0];

if(FrequencyMeter[internal_code1][internal_code2]==0)

position=xj_Search_Bin(internal_code1,HC,1,n);

if(position!

=0)

++HC[position].count;

HC[position].internal_code_address=(InternalCode*)realloc(HC[position].internal_code_address,(HC[position].count+1)*sizeof(InternalCode));

HC[position].internal_code_address[HC[position].count].internal_code=internal_code2;

xj_InsertSort(HC[position].internal_code_address,1,HC[position].count);

HC[n].internal_code_address[1].internal_code=internal_code2;

++FrequencyMeter[internal_code1][internal_code2];

//--统计不同字符出现的频率以及构建HC的机内码成员结构---

ifstreamifs(filename);

inti=0,j=0;

intFrequencyMeter[255][255]={0};

charch1,ch2;

n=0;

HC=NULL;

w=NULL;

if(ifs.fail())

cout"

can'

topenfile!

endl;

returnfalse;

while((ch1=ifs.get())!

=EOF)

if(int(ch1&

0xFF)128)

ch2=ifs.get();

ch2=0;

xj_Statistics(HC,int(ch1&

0xFF),int(ch2&

0xFF),FrequencyMeter,n);

HC[0].count=0;

for(i=2;

++i)HC[i].count+=HC[i-1].count;

w=(int*)malloc(HC[n].count*sizeof(int));

for(j=HC[i-1].count;

jHC[i].count;

++j)

w[j]=FrequencyMeter[int(HC[i].internal_code&

0xFF)][int(HC[i].internal_code_address[j-HC[i-1].count+1].internal_code&

0xFF)];

ifs.close();

returntrue;

//--构造赫夫曼树HT---

HT,constHuffmanPCodeHC,constint*w,intn)

intm=0,s1=0,s2=0;

if(HC[n].count=1)return;

m=2*HC[n].count-1;

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

for(j=HC[i-1].count+1;

j=HC[i].count;

++j,++w)

HT[j].ch[0]=HC[i].internal_code;

HT[j].ch[1]=HC[i].internal_code_address[j-HC[i-1].count].internal_code;

HT[j].ch[2]='

[message]'

HT[j].weight=*w;

HT[j].lchild=HT[j].rchild=HT[j].parent=0;

for(i=HC[n].count+1;

i=m;

*HT[i].ch=0;

HT[i].weight=HT[i].lchild=HT[i].rchild=HT[i].parent=0;

xj_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;

//--建立编码表HC---

voidxj_HuffmanCoding(constHuffmanTreeHT,HuffmanPCodeHC,intn)

intstart=0,c=0,f=0;

inti=0,k=1,r=1;

char*cd=NULL;

cd=(char*)malloc(HC[n].count*sizeof(char));

cd[HC[n].count-1]='

i=HC[n].count;

start=HC[n].count-1;

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

f!

=0;

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

if(HT[f].lchild==c)

cd[--start]='

0'

1'

if(kHC[r].count-HC[r-1].count)

k=1;

++r;

HC[r].internal_code_address[k].code=(char*)malloc((HC[n].count-start)*sizeof(char));

strcpy(HC[r].internal_code_address[k].code,&

cd[start]);

++k;

free(cd);

//---压缩文件--

boolxj_Compress(char*ifilename,char*ofilename,constHuffmanPCodeHC,constHuffmanTreeHT,intn)

ifstreamifs(ifilename);

ofstreamofs(ofilename,ios:

binary);

intbit_size=0;

intposi

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

当前位置:首页 > 农林牧渔 > 林学

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

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