ImageVerifierCode 换一换
格式:DOCX , 页数:21 ,大小:195.93KB ,
资源ID:6658050      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/6658050.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(13利用贪婪法构造哈夫曼编码1.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

13利用贪婪法构造哈夫曼编码1.docx

1、13利用贪婪法构造哈夫曼编码1数学与计算机学院课程设计说明书课 程 名 称: 算法设计与分析-课程设计 课 程 代 码: 7106620 题 目: 利用贪婪法构造哈夫曼编码 年级/专业/班: 学 生 姓 名: 学 号: 开 始 时 间: 2010 年 12 月 26 日完 成 时 间: 2011 年 01 月 09 日课程设计成绩:学习态度及平时成绩(30)技术水平与实际能力(20)创新(5)说明书撰写质量(45)总 分(100)指导教师签名: 年 月 日 目 录 1 引 言 11.1 问题的提出 11.2国内外研究的现状 11.3任务与分析 42 程序的主要功能 42.1定义结构体 42.2

2、动态存储 42.3 静态存储 42.4哈夫曼算法 42.5选择结点编码 43 总体设计 53.1 数据存储结构设计 53.2 操作模块设计 63.3 建树算法设计 64 结构体的说明 75 模块分析 75.1 静态存储选择最小结点的算法 75.2静态存储哈夫曼编码 85.3动态存储选择最小结点的算法 95.4动态存储哈夫曼编码 106 系统测试 126.1设计测试数据 126.2静态存储测试结果及分析 126.3动态存储测试结果及分析 137 结论 148 参考文献 14致 谢 15摘 要 哈夫曼编码是哈夫曼树的一个应用。哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。哈夫曼在上世纪五

3、十年代初就提出这种编码时,根据字符出现的概率来构造平均长度最短的编码。它是一种变长的编码。在编码中,若各码字长度严格按照码字所对应符号出现概率的大小的逆序排列,则编码的平均长度是最小的。(注:码字即为符号经哈夫曼编码后得到的编码,其长度是因符号出现的概率而不同,所以说哈夫曼编码是变长的编码。)哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。以哈夫曼树即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。关键词:哈夫曼树,哈夫曼编码,最优二叉树,贪婪法1 引 言 1.1 问题的提出 随着计算机的普及,网络进入大众的家庭,算法在现实生活中也

4、越来越重要,算法在现实生活中应用节约大量时间和空间,算法是计算机专业重要的一门专业基础课,也是学生最先接触到的专业课,该课程的掌握情况直接影响后继课程的深入学习以及学生软件开发能力的培养及提高。利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本,但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站写一哈夫曼编/译码系统。1.2国内外研究的现状 随着计算机科学的蓬勃发展,社会已进入信息时代。电子计算机和通信网络的广泛应用,一方面为人们

5、的工作和生活提供了很大的方便,另一方面也提出了许多亟待解决的问题,其中信息的安全性就是一个突出的问题。因此,密码学理论和技术已成为信息科学和技术中的一个重要领域。随着计算机网络的迅速发展,特别是近年来电子商务的兴起,现代密码学的应用已不仅仅局限于政治、军事以及外交等领域,其商用价值和社会价值也已得到了充分的肯定。而哈夫曼编码是其中一个重要应用之一。在一般的数据结构的书中,树的那章后面,著者一般都会介绍一下哈夫曼(HUFFMAN)树和哈夫曼编码。哈夫曼编码是哈夫曼树的一个应用。哈夫曼编码应用广泛,如JPEG中就应用了哈夫曼编码。 哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带

6、权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的带权路径长度记为WPL=(W1*L1+W2*L2+W3*L3+.+Wn*Ln),N个权值Wi(i=1,2,.n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,.n)。可以证明哈夫曼树的WPL是最小的。哈夫曼在上世纪五十年代初就提出这种编码时,根据字符出现的概率来构造平均长度最短的编码。它是一种变长的编码。在编码中,若各码字长度严格按照码字所对应符号出现概率的大小的逆序排列,则编码的平均长度是最小的。(注:码字即为符号经哈夫曼编码后得到的编码,其

7、长度是因符号出现的概率而不同,所以说哈夫曼编码是变长的编码。)然而怎样构造一棵哈夫曼树呢?最具有一般规律的构造方法就是哈夫曼算法。一般的数据结构的书中都可以找到其描述:一、对给定的n个权值W1,W2,W3,.,Wi,.,Wn构成n棵二叉树的初始集合F=T1,T2,T3,.,Ti,.,Tn,其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。(为方便在计算机上实现算法,一般还要求以Ti的权值Wi的升序排列。)二、在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。三、从F中删除这两棵树,并把这棵新的二叉树同样以升序排

8、列加入到集合F中。四、重复二和三两步,直到集合F中只有一棵二叉树为止。用C语言实现上述算法,可用静态的二叉树或动态的二叉树。若用动态的二叉树可用以下数据结构: struct treefloat weight; /*权值*/unionchar leaf; /*叶结点信息字符*/struct tree *left; /*树的左结点*/ ;struct tree *right; /*树的右结点*/;struct forest /*F集合,以链表形式表示*/struct tree *ti; /* F中的树*/struct forest *next; /* 下一个结点*/;例:若字母A,B,Z,C出现的

9、概率为:0.71,0.54,0.28,0.43;则相应的权值为:75,54,28,43。构造好哈夫曼树后,就可根据哈夫曼树进行编码。例如:上面的字符根据其出现的概率作为权值构造一棵哈夫曼树后,经哈夫曼编码得到的对应的码值。只要使用同一棵哈夫曼树,就可把编码还原成原来那组字符。显然哈夫曼编码是前缀编码,即任一个字符的编码都不是另一个字符的编码的前缀,否则,编码就不能进行翻译。例如:a,b,c,d的编码为:0,10,101,11,对于编码串:1010就可翻译为bb或ca,因为b的编码是c的编码的前缀。刚才进行哈夫曼编码的规则是从根结点到叶结点(包含原信息)的路径,向左孩子前进编码为0,向右孩子前进

10、编码为1,当然你也可以反过来规定。这种编码方法是静态的哈夫曼编码,它对需要编码的数据进行两遍扫描:第一遍统计原数据中各字符出现的频率,利用得到的频率值创建哈夫曼树,并必须把树的信息保存起来,即把字符0-255(28=256)的频率值以2-4BYTES的长度顺序存储起来,(用4Bytes的长度存储频率值,频率值的表示范围为0-232-1,这已足够表示大文件中字符出现的频率了)以便解压时创建同样的哈夫曼树进行解压;第二遍则根据第一遍扫描得到的哈夫曼树进行编码,并把编码后得到的码字存储起来。 静态哈夫曼编码方法有一些缺点:一、对于过短的文件进行编码的意义不大,因为光以4BYTES的长度存储哈夫曼树的

11、信息就需1024Bytes的存储空间;二、进行哈夫曼编码,存储编码信息时,若用与通讯网络,就会引起较大的延时;三、对较大的文件进行编码时,频繁的磁盘读写访问会降低数据编码的速度。 因此,后来有人提出了一种动态的哈夫曼编码方法。动态哈夫曼编码使用一棵动态变化的哈夫曼树,对第t+1个字符的编码是根据原始数据中前t个字符得到的哈夫曼树来进行的,编码和解码使用相同的初始哈夫曼树,每处理完一个字符,编码和解码使用相同的方法修改哈夫曼树,所以没有必要为解码而保存哈夫曼树的信息。编码和解码一个字符所需的时间与该字符的编码长度成正比,所以动态哈夫曼编码可实时进行。动态哈夫曼编码比静态哈夫曼编码复杂的多,有兴趣

12、的读者可参考有关数据结构与算法的书籍。前面提到的JPEG中用到了哈夫曼编码,并不是说JPEG就只用哈夫曼编码就可以了,而是一幅图片经过多个步骤后得到它的一列数值,对这些数值进行哈夫曼编码,以便存储或传输。哈夫曼编码方法比较易懂,大家可以根据它的编码方法,自己编写哈夫曼编码和解码的程序。 1.3任务与分析 本课题主要的任务是使用贪婪法构造哈夫曼编码,就是要通过构造哈夫曼树来实现。主要任务:(1)给出静态存储方式下的Huffman编码算法并编程实现;(2)给出动态存储方式下的Huffman编码算法并编程实现;通过此课题,能加深对贪婪法的理解,具有初步的独立分析和设计能力,提高综合运用所学理论知识和

13、方法独立分析和解决问题的能力。2 程序的主要功能2.1定义结构体定义一个结构体反映二叉树每个结点的包含内容,包含数据域和左右指针域2.2动态存储按照动态存储方式存储结点。2.3 静态存储了解存储的长度分配存储空间,。2.4哈夫曼算法熟悉贪婪法,选择贪婪发进行哈夫曼编码。第一步:初始化n个单节点的树,并为它们标上字母表中的字符。把每个字符的概率记在树的根中,用来指出树的权重。第二步:重复下面的步骤,直到只剩一棵单独的树。找到两棵权重最小的树。把它们作为新树中的左右子树,并把权重之和作为新的权重记录在新树的根中。2.5选择结点编码选择合适的算法,从中选择连个最小的结点编码。3 总体设计 主函数哈夫

14、曼编码调用选择算法输出哈夫曼编码 图1 总体结构设计 3.1 数据存储结构设计(1) 哈夫曼树的存储结构设计对于哈夫曼编码问题,在构造哈夫曼树时要求能方便地实现从双亲点到左右孩子结点的操作,在进行哈夫曼编码时又要求能方便地实现从孩子到双亲结点的操作。因此,设计哈夫曼树的存储结构为双亲孩子存储结构如图(一)。weightParentleftChildringthChild表(一)哈夫曼树的结点存储结构设计如下:typedef struct int weight; /权值 int parent; /双亲结点下标 int leftChild; /左孩子下标 int rightChild; /右孩子下

15、标 HaffNode; /哈夫曼树的结点结构(2) 哈夫曼编码的存储结构设计对于存放哈夫曼编码数据元素的结构,由于哈夫曼编码是不等长编码,所以存放编码的数组必须有 一个start来存储数组中码字的起始位置。如图(二)。startBit0Bit1BitMaxBit-1表(二)存放哈夫曼编码的数组元素的存储结构设计如下:typedef struct int bitMaxN; /数组 int start; /编码的起始下标值 int weight; /字符的权值Code; /哈夫曼编码的结构3.2 操作模块设计(1) 此模块构造了一个函数Haffman()用来建立叶结点的个数为n权值数组为weigh

16、t的哈夫曼树haffTree(2) 此模块构造了一个函数HaffmanCode()用来将n个结点的哈夫曼树haffTree构造成哈夫曼编码haffCode(3) 此模块构造了一个函数HaffmanCoding()根据每个结点的编码hcode对哈夫曼编码strcode进行译码,此函数调用了一个字符匹配函数BFIndex()。(4) 字符匹配函数BFIndex(),由BF算法改造而成,函数的功能是确认当前子串是否在母串的前部,如果是返回1否则返回0。(5) 主函数模块main()用来进行字符串的输入和各个函数模块的调用和结果的显示等。3.3 建树算法设计(3) 在给定的n个取值构造n棵只有根结点的

17、二叉树,从而得到一个二叉树森林。(4) 在二叉树森林F中选取根结点的权值最小和次小的两棵二叉树作为左右树构造心的二叉树,此时,新的二叉树的根结点权值为左右子树根结点权值之和。(5) 在二叉树森林F中删除作为心二叉树左右子树的两棵二叉树,将新二叉树假如到二叉树森林F中。(6) 重复步骤(2)和(3),当二叉树森林F中只剩下一棵二叉树时,这棵二叉树就是所构造的哈夫曼树。4 结构体的说明静态存储结构体定义typedef structint weight;int parent,lchild,rchild;HTnode,*Huffmantree;typedef char *Huffmancode;动态存

18、储结构体定义typedef struct node int weight; int parent,lchild,rchild; int loca; struct node *next,*father; node,*Huffmantree;5 模块分析5.1 静态存储选择最小结点的算法依次遍历静态存储结构选出权值最小的两个结点;核心代码如下:void select(Huffmantree HT,int k,int *s1,int *s2) /赫夫曼树HT中选paren为0且权值最小的两结点,s1,s2 int i,j=1,min,e; while(HTj.parent !=0) j+; if(j

19、k) printf(无空闲结点!n);exit(0); else min=HTj.weight ; for(i=1;i=k;i+) if(HTi.weight k) printf(无空闲结点 !n);exit(0); else min=HTj.weight ; for(i=1;i=k;i+) if(HTi.weight min)&(HTi.parent =0)&(i!=e) j=i;min=HTi.weight ; *s2=j;5.2静态存储哈夫曼编码选择贪婪法在静态存储方式下编制哈夫曼;核心代码如下:void Huffmancoding(Huffmantree *HT,Huffmancode

20、 *HC,int w,int n) int i,m,c,s1,s2,start,f; /char * cd; Huffmantree p; if(n=1) printf(无法构成树!n);exit(0); m=2*n-1; *HT=(Huffmantree)malloc(m+1)*sizeof(HTnode); /0号单元未用 for(p=*HT+1,i=1;i=n;i+,+p ) (*p).weight =wi; printf(HT%d.weight=%dn,i,(*p).weight ); (*p).lchild =0; (*p).parent =0; (*p).rchild =0; fo

21、r(;i=m;i+,+p) (*p).weight =0; (*p).lchild =0; (*p).parent =0; (*p).rchild =0; for(i=n+1;i HT%d.weightn,s1,s2,i,(*HT)i.weight); *HC=(Huffmancode)malloc(n+1)*sizeof(char *); char *cd; cd=(char *)malloc(n*sizeof(char); cdn-1=0; printf(HuffmanTree Code is as follows :); for(i=1;iparent!=0) j+;p=p-next ;

22、 else break; if(jk) printf(无空闲结点!n);exit(0); else min=p-weight ;q=HT; for(i=1;iweight parent =0) j=i;min=q-weight ;p=q; q=q-next ; if(q=NULL) break; *s1=p; e=j;j=1; p=HT; while(p) if(p-parent !=0|j=e) j+;p=p-next ; else break; if(jk) printf(无空闲结点 !n);exit(0); else min=p-weight ;q=HT; for(i=1;iweight

23、 parent =0) j=i;min=q-weight ;p=q; if(q=NULL) break; q=q-next ; *s2=p;5.4动态存储哈夫曼编码选择贪婪法在动态态存储方式下编制哈夫曼;核心代码如下:void Huffmancoding(Huffmantree *HT,Huffmancode *HC,int w,int n)int i,m,c,start,f; Huffmantree s1,s2, p,q,q1; if(n=1) printf(无法构成树!n);exit(0); m=2*n-1; *HT=(Huffmantree)malloc(sizeof(node); fo

24、r(p=*HT,i=1;i=n;i+) (*p).weight =wi; printf(HT%d.weight=%dn,i,(*p).weight ); (*p).lchild =0; (*p).parent =0; (*p).rchild =0; (*p).loca =i; if(inext=q; p=q; p-next =NULL; for(i=n+1;iparent =i; s2-parent =i; q1-lchild =s1-loca ; q1-rchild =s2-loca; q1-loca=i;q1-parent=0; q1-weight =s1-weight+s2-weight

25、; s1-father=q1;s2-father=q1; p-next=q1;p=q1; printf(HT%dandHT%d-HT%d.weightn,s1-loca ,s2-loca ,i,p-weight); p-next =NULL; *HC=(Huffmancode)malloc(n+1)*sizeof(char *); char *cd; cd=(char *)malloc(n*sizeof(char); cdn-1=0; printf(HuffmanTree Code is as follows :); p=*HT; for(i=1;iparent,q1=q-father;f!=

26、0;c=f,f=q1-parent,q1=q1-father) if(q1-lchild=c) d-start=0; else cd-start=1; (*HC)i=(char*)malloc(n-start)*sizeof(char); strcpy(*HC)i,&cdstart); printf(n %d nodes Huffman code is: %s,p-weight,(*HC)i); p=p-next ; free(cd); printf( n ); 6 系统测试6.1设计测试数据图2 6.2静态存储测试结果及分析当运行程序时首先跳出界面如下: 图3输入各结点权值后运行结果如下: 图46.3动态存储测试结果及分析当运行程序时首先跳出界面如下: 图5输入各结点权值后运行结果如下: 图67 结论通过这次实验,

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

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