哈夫曼编码与译码.doc_第1页
哈夫曼编码与译码.doc_第2页
哈夫曼编码与译码.doc_第3页
哈夫曼编码与译码.doc_第4页
哈夫曼编码与译码.doc_第5页
免费预览已结束,剩余10页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、哈夫曼编码与译码用哈夫曼树对字符串进行编码译码一、设计思想程序要求 :要求每个字符有自己唯一的编码。将得到的一串利用哈夫曼树对字符串进行编码 ,字串译成 0、1 编码后存到一个文件夹中,然后再从这个文件夹中读出这串编码进行解码。实现方法 :输入一串字符,要求字符的区间为大写的 26 个英文字母, 将获得的串字符用计算进行字符统计,统计出现的字符种数以及每种字符出现的次权值的函数(jsquanzhi()数, 将该种字符出现的次数作为它的权值。将出现的字符的权值和该字符依次分别赋给两个结构体HT和 HC,利用 HT(节点 ) 权值的大小建立哈夫曼树,首先用选择函数 select()函数选择两个权值

2、最小的字符作为叶子节点,创建一个新的节点作为这两个叶节点的父节点,被选中的节点给他的HTi.parent赋值是他下次不再被选中,父节点的权值为,子节点的权值之和。然后将该将父节点放入筛选区中,再进行选择 ( 被选过的不再被使用 ) ,直到所有的节点都被使用,这样一个哈夫曼树就被建立了。根据每个字符在哈夫曼书中的位置来编译每个字符的0、1 密文代码,从叶节点判断该叶节点是其父节点的左右字左字为0,右子为1,在判断父节点是上级父节点的左右子直至根节点,将生成的0、1 字符串按所表示的字符倒序存入 HC相应的字符的 bins数组。重新一个一个字符的读取输入的字符串,按照字符出现的顺序将它转为0、1

3、代码并存到一个txt文件夹中去。解码时从文件夹中,一个一个字符的读出那串0、1 代码赋给一个临时字符串cd ,用该字符串与每个字符的HCi.bins密文比较,直到与一个字符的密文相同时,译出该字符,将字符存放在临时字符数组tempstr中,清空临时字符串继续读取0、1代码进行翻译,直至文件密文结束为止。于是就得到了原先被加密的那串字符串。- 1 -用哈夫曼树对字符串进行编码译码二、算法流程图开始获得输入的字符串getstr, i=0 。判断 getstri是否 i+;为 26 个大写字母否是k=getstri-64;quantempk+( quantemp为 int型数组开始值都为 0)i+;

4、i=1,j=0否i27?是结束 是 quantempi=i+;0?否j+;strj=i+64;quanj=quantempi;图 1 计算字符权值及字符种类算法说明 : 将的的字符串进行字符种类级每种字符出现频率的统计- 2 -用哈夫曼树对字符串进行编码译码开始将所有的几点的父节点和子节点权值赋成0i=1;(num 为字符的种类 )HTi.weight=quani i=num是 否i=num+1否i=2*num-1?是结束 ?选择权值最小的两个节点将下标赋给s1,s2.HTs1.parent=i;HTs2.parent=i;HTi.lchild=s1;HTi.rchild=s2;HTi.wei

5、ght=HTs1.weight+HTs2.weight;i+图 2 构建哈夫曼树算法说明 : 利用选择排序,选择节点权值最小的两个节点,构建一个子树,将该树的根节点再放入选择区,重复该操作,直至用完所有节点完成哈夫曼数的搭建。- 3 -用哈夫曼树对字符串进行编码译码开始将 stri 的值依次赋给 HCi.ch i=0;cdnum=0;i0否 &cdstart);是HCi.len=num-start; cd-start=(HTp.lchild=c)?0:1;c= HTc.parent;打开 codefile.txt文件 , 获得字符串 str指针, i=0;否i=num;是结束否否HCi.ch=

6、*str? i+是将 HCi.bitsj存进文件图 3 利用哈夫曼树加密算法说明 : 利用每个字符在哈夫曼树中的位子,得到每个字符的0、1 密文编码。再将字符串按字符密文进行编译,然后存入文件夹中。- 4 -用哈夫曼树对字符串进行编码译码开始cjs=0, i=0打开文件夹 codefile.txt,!feof(fp)结束(inum)&(cjs=0)&(!feof(fp)cdi=;cdi+1=0;cdi=fgetc(fp);j=1;j=num i+j+strcmp(HCj.bits,cd)=0strk=HCj.ch;cjs=1;k+;strk=0;break;图 4 解密算法说明 : 从文件夹中

7、读出密文,和HCi.bis中的密文进行比较译出字符,存入临时数组。待译码结束后,输出字符串。- 5 -用哈夫曼树对字符串进行编码译码三、源代码/ hafuman.cpp :定义控制台应用程序的入口点。/#include stdafx.h#include stdlib.h#include string.h#include stdio.h#define n 100 /叶节点的个数小等于n #define m 2*n-1 /总结点的个数为m=2*n-1 int num; /定义一个全局变量用于存放字符种类个数typedef struct /结构体用于存放树节点包括节点的父节点、左子、右子以及权值 i

8、nt weight;int parent,lchild,rchild;HTNode;typedef HTNode HafumanTreem+1; /重命名HTNodetypedef struct /结构体由于存放每个字符的密文和长度char ch;char bits10;int len;CodeNode;typedef CodeNode HafumanCoden+1; /重命名CodeNodeint _tmain(int argc, _TCHAR* argv) int quan27; /声明一个数组用以存放26 字符的权值char getstr300,str27;/ 声明两个字符串数组一个用于

9、存输入一个由于存放输入中含有的字符char *s; / 声明一个 char 型指针用于指向字符 HafumanTree HT; / 声明 m+1 个树节点 HafumanCode HC; / 声明 n+1 个 codeint jisuanquan(char *s,int quan,char str); /声明需要调用的函数void gjhafumantree(HafumanTree HT,HafumanCode HC,int quan,char str); void Hafumanencode(HafumanTree HT,HafumanCode HC); voidcoding(Hafuman

10、Code HC,char *str); char *decode(HafumanCode HC); - 6 -用哈夫曼树对字符串进行编码译码printf(请输入要加密的字符串 :n);gets(getstr); /获得输入的字符串num=jisuanquan(getstr,quan,str); /统计字符串中含有字符种类个数/printf(%dn,num);gjhafumantree(HT,HC,quan,str); /根据字符权值构建哈夫曼树Hafumanencode(HT,HC); /根据哈夫曼树确定每个字符的codecoding(HC,getstr); /将字符串译码存入文件夹s=dec

11、ode(HC); /将暗文解码printf(解密为 :n);printf(%sn,s);system(pause);return 0;/ 函数int jisuanquan(char *s,int quan,char str) /char *p;int i,j,k,quantemp27;计算字符串中字符权值for(i=1;i=A&*p=Z) /判断字符是否为26 字母k=*p-64; / 看是 26个字符中的哪个字符quantempk+; /字符权值加 1j=0;for(i=1,j=0;i27;i+)if(quantempi!=0)j+; /用于统计字符种类个数strj=i+64; /str按字

12、母表顺序存储出现过的字符quanj=quantempi;return j;- 7 -用哈夫曼树对字符串进行编码译码void select(HafumanTree HT,int k,int *s1,int*s2) /选择权值最小的两个 int i,j;int min1=9999; /声明一个 int类型的数值 min1,赋个较大的输给它for(i=1;i=k;i+) /选择权值最小的一个节点( 且该节点无父节点 )if(HTi.weightmin1)&(HTi.parent=0)j=i;min1=HTi.weight;*s1=j;min1=9999;for(i=1;i=k;i+)if(HTi.w

13、eightmin1)&(HTi.parent=0)&(i!=*s1)/ 选择权值最小的一个节点 ( 且该节点无父节点 ) j=i;min1=HTi.weight;*s2=j;void gjhafumantree(HafumanTree HT,HafumanCode HC,int quan,charstr) /构建哈夫曼树 int i,s1,s2;for(i=1;i2*num-1;i+) /将所有的节点赋空HTi.lchild=0;HTi.rchild=0;HTi.parent=0;HTi.weight=0;for(i=1;i=num;i+) /将 num个字符的权值赋给num叶节点HTi.we

14、ight=quani;for(i=1;i=num;i+) /将 num个字符赋给 codenodeHCi.ch=stri;i=1;while(i=num) printf(=%c=%d=n,HCi.ch,quani);i+; /输出每个字符的及其权值for(i=num+1;i=2*num-1;i+)select(HT,i-1,&s1,&s2); /选择两个权值最小的叶节点HTs1.parent=i;HTs2.parent=i; /两个节点指向同一父节点HTi.lchild=s1;HTi.rchild=s2;HTi.weight=HTs1.weight+HTs2.weight;/ 父节点的权值为子

15、节点相加 ( 父节点继续放入选择区 )- 8 -用哈夫曼树对字符串进行编码译码void Hafumanencode(HafumanTree HT,HafumanCode HC)int c,p,i;char cdn; / 临时数组用于记录字符在哈夫曼树的位置 int start;cdnum=0; /给 cd 赋个结束符for(i=1;i0) /根据节点是其父节点的左右子来记录它的位置cd-start=(HTp.lchild=c)?0:1;c=p; /将父节点转为子节点strcpy(HCi.bits,&cdstart); /将得到的0、1字串存入结构体HCprintf(%c:%sn,HCi.ch,

16、HCi.bits);HCi.len=num-start; /求每个字符0、1 编码长度void coding(HafumanCode HC,char *str) /根据哈夫曼树确定每个字符的0、1 代码code int i,j;FILE *fp; /声明一个文件夹指针fp=fopen(codefile.txt,w); /打开文件夹codefile printf(密文为 :n);while(*str) /字符串未结束时for(i=1;i=num;i+)if(HCi.ch=*str) /判断字符是否在Codenode中存在for(j=0;jHCi.len;j+) /将 codenode 中该字符的

17、1、 0 代码存入文件夹fputc(HCi.bitsj,fp);printf(%s,HCi.bits);break;str+; /printf(n);fclose(fp);字符后移- 9 -用哈夫曼树对字符串进行编码译码char *decode(HafumanCode HC)FILE *fp;char tempstr9999;char *p;static char cdn+1; /char型数组用于存放从文件夹中读取的1、0 代码int i,j,k=0,jsjs;fp=fopen(codefile.txt,r);while(!feof(fp) /当文件夹读取没有结束jsjs=0; /判读一个字

18、符是否译码结束for(i=0;(inum)&(jsjs=0)&(!feof(fp);i+) /当一个字符未译完并且文件未读取结束 cdi= ;cdi+1=0; /让cd赋成空格cdi=fgetc(fp); /读取文件夹中的一个字符for(j=1;j=num;j+)f(strcmp(HCj.bits,cd)=0) /看 cd 的字符串是否等于Codenode中的某个密文tempstrk=HCj.ch;jsjs=1;printf(=%s=,HCj.bits);k+;break;/ 将译出的字符赋给临时字符串 tempstr, 标记一个字符译码结束 jsjs 赋1,跳出循环tempstrk=0; /

19、赋给临时字符串一个结束标志p=tempstr; /char型指针指向临时字符串return p;-10-用哈夫曼树对字符串进行编码译码四、运行结果图 5 哈夫曼编码与译码运行结果图-11-用哈夫曼树对字符串进行编码译码五、遇到的问题及解决这部分我主要遇到了如下两个问题,其内容与解决方法如下所列:, 当我写完程序,输入一段字符串让程序进行译码和解码是出现了一个问题,译出的结果不是想要的结果,但结果又有一定规律,就是结果中的字符都在明文中出现过,可是字符数量明显比明文中的要少很多。首先我认为为题可能出现在我将明文加密后的存储阶段,于是我在程序将0、 1代码存入 codeflie.txt文件前,先将

20、临时存储字符串数组内容输出,结果发现没有问题,于是我又在,译码阶段将从codeflie.txt读出的内容逐字输出发现结果和存入的一样。输入和输出都一样。问题不是出现在存储上,于是我想到问题可能出现在,我将 0、1 编码转成明文的时。于是我认真的看了看我的decode 函数,添加了些辅助输出,发现有写编码不是原先的一个字符的译文,有的是两个字符的译文译成了一个字符。于是我又输进一段字符将暗文带入函数计算,发现问题出在但一出一个字符后,我的一个循环并没有终止,而是继续向cd数组中添加,1 和0;直至cd的长度超过num时才结束,而下次调用该循环式,前面会有几个1、0 没有被编译。所以导致了以上的错误,于是我在函数中声明了一个变量jsjs(计算结束 ) ,用它在译完一个字符是让函数跳出循环。于是问题得到了解决。, 第二个问题再之前就出现了只不过他和前一个问题没有多大的联系,就是在输出明文结果是字符串的结尾变成了 : 烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫 。一开始我认为他和第一个问题是一个问题,是存储或者译码出错了,但是但第一个问题解决后他依然存在。于是我才确定这是另外的一个问题。根据以晚的经验出现这种情况的原因就几种,存储出错或者输出形式不对,或者输出的位置不

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论