数据结构课程设计(哈夫曼编码)要点

合集下载

数据结构课程设计哈夫曼

数据结构课程设计哈夫曼

数据结构课程设计哈夫曼一、课程目标知识目标:1. 理解哈夫曼编码的基本原理和构建方法;2. 掌握哈夫曼树的结构特点及其应用;3. 学会运用哈夫曼编码进行数据压缩,并了解其优缺点。

技能目标:1. 能够运用所学知识构建哈夫曼树并进行编码;2. 能够分析给定数据集的最优哈夫曼编码方案;3. 能够运用哈夫曼编码解决实际问题,如文件压缩与解压。

情感态度价值观目标:1. 培养学生对数据结构在计算机科学中重要性的认识,激发对数据结构学习的兴趣;2. 培养学生的团队合作意识,学会在团队中发挥个人优势,共同解决问题;3. 培养学生严谨、细致的学术态度,养成良好的编程习惯。

课程性质分析:本课程为高中信息技术学科的数据结构部分,旨在让学生了解并掌握常用的数据结构及其应用。

哈夫曼编码作为数据结构中的一种重要应用,具有很高的实用价值。

学生特点分析:高中学生已经具备了一定的逻辑思维能力,能够理解抽象的概念,但实践经验不足,需要通过具体的案例和动手操作来加深理解。

教学要求:1. 理论与实践相结合,注重培养学生的动手能力;2. 以学生为主体,鼓励学生主动探究、合作学习;3. 注重培养学生的创新能力和解决问题的能力。

二、教学内容1. 引入:回顾树的基本概念,为新课哈夫曼树做好知识铺垫。

教材章节:第二章 树与二叉树2. 哈夫曼编码原理:- 哈夫曼编码的基本思想与原理- 哈夫曼树的构建过程教材章节:第二章 树与二叉树,第五节 哈夫曼编码3. 哈夫曼树的构建方法:- 构建哈夫曼树的步骤- 哈夫曼编码的生成方法教材章节:第二章 树与二叉树,第五节 哈夫曼编码4. 哈夫曼编码的应用:- 文件压缩与解压的原理- 哈夫曼编码在数据压缩中的应用案例教材章节:第二章 树与二叉树,第五节 哈夫曼编码及应用5. 实践操作:- 动手编写程序构建哈夫曼树并进行编码- 分析实际数据集,设计最优哈夫曼编码方案教材章节:第二章 树与二叉树,第五节 哈夫曼编码实践6. 总结与拓展:- 总结哈夫曼编码的特点及其在数据压缩中的应用优势- 探讨哈夫曼编码在其他领域的拓展应用教材章节:第二章 树与二叉树,第五节 哈夫曼编码拓展与应用教学内容安排与进度:1. 引言与回顾:1课时2. 哈夫曼编码原理与构建方法:2课时3. 哈夫曼编码应用与实践操作:2课时4. 总结与拓展:1课时总计:6课时三、教学方法1. 讲授法:- 在讲解哈夫曼编码的基本原理、构建方法及应用场景时,采用讲授法进行知识传授,使学生在短时间内掌握关键概念和理论。

数据结构 哈夫曼编码器课程设计报告

数据结构 哈夫曼编码器课程设计报告

数据结构哈夫曼编码器课程设计报告数据结构哈夫曼编码器课程设计报告1.引言1.1 编写目的本文档旨在详细介绍数据结构课程设计中的哈夫曼编码器的设计过程和实现方法。

1.2 背景哈夫曼编码是一种常用的数据压缩技术,通过构建变长编码表,将频率较高的字符用较短的编码表示,从而减小数据的存储和传输开销。

1.3 参考资料[1] 斯科特·梅耶, 数据结构与算法分析[C], 机械工业出版社, 2014.[2] Thomas H.Cormen, Charles E.Leiserson, RonaldL.Rivest, Clifford Stein, Introduction to Algorithms, The MIT Press, 2009.2.需求分析2.1 功能需求①输入文件用户可以输入需要进行哈夫曼编码的文件路径。

②编码操作系统根据输入的文件,相应的哈夫曼编码,并显示编码结果。

③解码操作用户可以输入已经编码过的文件,系统将根据编码表进行解码,并显示解码结果。

2.2 非功能需求①性能要求系统在处理大规模文件时需要具备较高的性能,保证编码和解码的效率。

②用户友好性系统需要提供简洁明了的界面,方便用户操作。

③可扩展性系统需要具备良好的扩展性,满足未来需求变化的需要。

3.概要设计3.1 总体设计系统采用面向对象的设计方法,主要包含以下几个类:① HuffmanEncoder该类负责对输入文件进行哈夫曼编码的操作。

② HuffmanDecoder该类负责对已编码文件进行解码的操作。

③ HuffmanTree该类是哈夫曼树的实现,用于构建编码和解码所需的编码表。

3.2 类的详细设计① HuffmanEncoder3.①属性●inputFile: 输入文件路径●codeTable: 编码表3.②方法●setInput: string): 设置输入文件路径●generateCodeTable(): 编码表●encodeFile(): 对输入文件进行编码② HuffmanDecoder3.①属性●encodedFile: 已编码文件路径●codeTable: 编码表3.②方法●setEncoded: string): 设置已编码文件路径●setCodeTable(table: object): 设置编码表●decodeFile(): 对已编码文件进行解码③ HuffmanTree3.①属性●root: 哈夫曼树的根节点3.②方法●buildTree(frequencies: object): 根据字符频率构建哈夫曼树●buildCodeTable(): 构建字符与编码的对应关系表4.详细设计4.1 HuffmanEncoder类①属性●inputFile: string,输入文件路径●codeTable: object,编码表②方法4.① setInput: string)●作用:设置输入文件路径●输入:,string类型,输入文件路径●输出:无4.② generateCodeTable()●作用:编码表●输入:无●输出:无4.③ encodeFile()●作用:对输入文件进行编码●输入:无●输出:无5.实现6.测试与验证7.项目总结8.附件8.1 源代码文件8.2 测试文件9.法律名词及注释9.1 哈夫曼编码哈夫曼编码是一种变长编码方法,通过构建树形结构,将频率较高的字符用较短的编码表示。

数据结构课程设计 哈夫曼编码与译码器课程设计

数据结构课程设计 哈夫曼编码与译码器课程设计

数据结构课程设计题目名称:哈夫曼编码与译码器课程设计计算机科学与技术学院1.需求分析(1)熟练掌握哈夫曼编译原理(2)掌握程序设计步骤(3)根据哈夫曼编码原理,设计一个程序,在已知相关字符和字符对应权值(文件中存在或者用户输入)的情况下,根据用户要求对相应内容进行编码、译码等相应操作。

(4)输入的形式和输入值的范围;(5) 输出的形式;(6) 程序所能达到的功能;(7) 测试数据:包括正确的输入及其输出结果和含有错误的输入及其输出结果2.概要设计1.写好流程图,设计实验方案。

2.初始化,从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件HuofumanTree中。

3.编码。

利用已建好的哈夫曼树,对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。

4.译码。

利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件Textfile中。

5.印代码文件(Print)将文件CodeFile以紧凑格式显示在终端上,每行50个代码。

同时将此字符形式的编码文件写入文件CodePrint中。

6.印哈夫曼树(Treeprinting).将已在内存中的哈夫曼树以直观的方式(比如树)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。

具体函数如下:1.Initialization()初始化2.Encoding()编码3.Decoding()译码4.Print_file()打印代码文件5.search(k,j,p)搜索二叉树6.Print_tree() 打印二叉树7.menu()主菜单8.main()主函数3.详细设计(1)哈夫曼结点定义类型以一个节点为单位,其中节点中包括他的父亲·左孩子·右孩子,权值(2)存储字符信息(3)用于编码时存取字符长度及起始位置(4)初始化将数据存入文件中void Initialization(){int i,j;FILE* HFM_f;//定义一个指针指向文件HFM_f = fopen("C:/Users/lenovo/Desktop/x.txt","w");//将文件打开,赋值给HFM_fif(HFM_f == NULL){printf("create file error!\n");}printf(" 请输入字符集大小: ");scanf("%d",&leaves);fprintf(HFM_f,"----输入的值-----\n");fprintf(HFM_f," 字符大小%4d\n",leaves);fprintf(HFM_f," 字符权值\n");for(i=0; i<leaves; i++){printf(" 请输入第%d个字符和其权:",i+1);scanf(" %c ",&HFM_num[i].hfstr);scanf("%d",&HFM_num[i].weight);fprintf(HFM_f,"%4c",HFM_num[i].hfstr);fprintf(HFM_f,"%4d\n",HFM_num[i].weight); //存储字符和权值}(5)建立哈夫曼树for(i=0; i<maxsize; i++)//哈夫曼树初始化{HFM_tree[i].parent = -1;HFM_tree[i].lchild = -1;HFM_tree[i].rchild = -1;HFM_tree[i].weight = 0;}for(i=0; i<leaves; i++){HFM_tree[i].weight = HFM_num[i].weight;}for(i=0; i<leaves-1; i++){int m1,m2;int m1_pos,m2_pos;m1=m2=65536;m1_pos=m2_pos=0;for(j=0; j<leaves+i; j++)//选出最小且没被访问的两个数{if(HFM_tree[j].weight<m1&&HFM_tree[j].parent == -1) {m2 = m1;m1 = HFM_tree[j].weight;m2_pos = m1_pos;m1_pos = j;}else{if(HFM_tree[j].weight<m2&&HFM_tree[j].parent == -1){m2 = HFM_tree[j].weight;m2_pos = j;}}}HFM_tree[leaves+i].parent = -1;HFM_tree[leaves+i].lchild = m1_pos;//HFM_tree[leaves+i]为两者的最小和的结点,即他们的父亲HFM_tree[leaves+i].rchild = m2_pos;HFM_tree[m1_pos].parent = leaves+i;HFM_tree[m2_pos].parent = leaves+i;HFM_tree[leaves+i].weight = m2+m1;//将和赋为他们的父亲结点的权值}(6)输出哈夫曼树printf("----------------哈夫曼编码--------------\n");printf(" parent lchild rchild weight\n");fprintf(HFM_f,"-------------哈夫曼编码------------\n");fprintf(HFM_f," parent lchild rchild weight\n");for(i=0; i<leaves*2-1; i++){printf("%8d%8d%8d%8d\n",HFM_tree[i].parent,HFM_tree[i].lchild,HFM_tre e[i].rchild,HFM_tree[i].weight);fprintf(HFM_f,"%8d%8d%8d%8d\n",HFM_tree[i].parent,HFM_tree[i].lchild, HFM_tree[i].rchild,HFM_tree[i].weight);}printf("\n");fclose(HFM_f);//关上文件}(7)编码void Encoding(){int i,j,p,c,k;FILE* HFM_f = fopen("CodeFile.txt","w");//打开文件if(HFM_f == NULL){printf("open file error!\n");}for(i=0; i<leaves; i++){c = i;//当前结点编号p = HFM_tree[i].parent;//父亲结点编号HFM_hf.start = len-1;//单个结点路径长度-1,即循环次数,从0开始算while(p!=-1)//根节点的p=-1,即根结点的父亲值为-1,即为初始化的值,证明根节点没有父亲结点{if(HFM_tree[p].lchild == c)//若左孩子为C,赋值0{HFM_hf.bit[HFM_hf.start] = 0;}else{HFM_hf.bit[HFM_hf.start] = 1;//若右孩子为c,赋值1 }--HFM_hf.start;c = p;//沿着树往上走,将刚才的父亲变为孩子p = HFM_tree[c].parent;//寻找当前结点的父亲,即原节点的爷爷}for(j=HFM_hf.start+1,k=0; j<len; j++,k++){HFM_code[i].bit[k] = HFM_hf.bit[j];}HFM_code[i].length = len-HFM_hf.start-1;HFM_code[i].start = HFM_hf.start+1;}for(i=0; i<leaves; i++){HFM_code[i].hfch = HFM_num[i].hfstr;printf(" character:%c start:%d length:%dCode:",HFM_code[i].hfch,HFM_code[i].start,HFM_code[i].length );for(j=0; j<HFM_code[i].length; j++){printf("%d",HFM_code[i].bit[j]);fprintf(HFM_f,"%d",HFM_code[i].bit[j]);}printf("\n");}printf("\n");fclose(HFM_f);}4.调试结果输入26个字符及其权值26个字母的编码如下:译码如下:打印文件中的内容:打印出的哈夫曼树如下:5.时间复杂度本代码的哈夫曼算法的时间复杂度为O(n^3)。

数据结构 程序设计 哈夫曼编码

数据结构  程序设计 哈夫曼编码

学号数据结构课程设计设计说明书哈夫曼编码起止日期:2011年12月12 日至2011 年12月16日学生姓名班级成绩指导教师(签字)电子与信息工程系2011年12月16日一、设计目的 (3)二、设计要求 (3)三、设计内容 (3)一、需求分析 (3)1.构造哈夫曼树的方法如下: (3)2.程序实现的功能 (4)二、问题求解 (4)三、总体设计 (5)1.程序设计组成框图: (5)2.流程图: (6)四、详细设计 (6)1. 构造结点的结构体 (6)2. 构造哈夫曼树 (6)3. 求哈夫曼编码 (6)五、调试与测试 (7)1.测试过程中遇到的主要问题 (7)六、关键源程序清单和执行结果 (7)1.源代码: (7)2.执行结果: (10)四、参考文献 (11)天津城市建设学院课程设计任务书2011—2012学年第1学期电子与信息工程系软件工程专业班级课程设计名称:数据结构课程设计设计题目:哈夫曼编码完成期限:自2011 年12 月12 日至2011 年12 月16 日共 1 周设计依据、要求及主要内容(可另加附页):一、设计目的熟悉各种数据结构和运算,会使用数据结构的基本操作解决一些实际问题。

二、设计要求(1)重视课程设计环节,用严谨、科学和踏实的工作态度对待课程设计的每一项任务;(2)按照课程设计的题目要求,独立地完成各项任务,严禁抄袭;凡发现抄袭,抄袭者与被抄袭者皆以零分计入本课程设计成绩。

凡发现实验报告或源程序雷同,涉及的全部人员皆以零分计入本课程设计成绩;(3)学生在接受设计任务后,首先要按设计任务书的要求编写设计进程表;(4)认真编写课程设计报告。

三、设计内容一、需求分析1.构造哈夫曼编码的方法如下:第一步定义一个结点的结构体,包括结点的权值,结点的双亲结点,左孩子,右孩子。

并定义两个HTNode,*HuffmanTree为该类型的名字。

第二步创建一个Select函数用来选择结点较小的结点权值和下标。

数据结构课程设计_哈夫曼树

数据结构课程设计_哈夫曼树

数据结构课程设计_哈夫曼树哈夫曼树是数据结构课程设计中的一个重要内容,它是一种用于编码和压缩数据的树形结构。

在这篇文章中,我们将深入探讨哈夫曼树的原理、应用以及实现方法。

一、哈夫曼树的原理哈夫曼树是一种特殊的二叉树,它的构建依赖于哈夫曼编码的思想。

哈夫曼编码是一种变长编码方式,通过将频率较高的字符用较短的编码表示,而频率较低的字符用较长的编码表示,从而实现数据的高效压缩。

构建哈夫曼树的过程如下:1. 首先,将待编码的字符按照出现频率从小到大进行排序。

2. 然后,取出频率最小的两个字符,将它们作为叶子节点构建一个新的二叉树,该树的根节点的权值为这两个字符的频率之和。

3. 将新构建的二叉树插入到原有的字符列表中,并重新进行排序。

4. 重复步骤2和步骤3,直到只剩下一个根节点的二叉树为止,该树就是哈夫曼树。

二、哈夫曼树的应用哈夫曼树在数据压缩和编码中有着广泛的应用。

由于哈夫曼编码能够将频率较高的字符用较短的编码表示,从而减少了数据的存储空间,因此在文件压缩、图像压缩等领域被广泛应用。

在文件压缩中,哈夫曼树可以根据文件中字符的出现频率构建出一个最优的编码表,将文件中的字符替换为对应的哈夫曼编码,从而实现文件的高效压缩。

解压缩时,只需要根据哈夫曼编码表将编码还原为原始字符,即可恢复文件的原始内容。

在图像压缩中,哈夫曼树可以根据图像中像素值的出现频率构建出一个最优的编码表,将像素值替换为对应的哈夫曼编码,从而实现图像的高效压缩。

解压缩时,只需要根据哈夫曼编码表将编码还原为原始像素值,即可恢复图像的原始内容。

三、哈夫曼树的实现方法哈夫曼树的实现方法有多种,其中一种常见的方法是使用优先队列(也称为最小堆)来实现。

优先队列是一种特殊的队列,它的每个元素都有一个优先级,优先级高的元素先出队。

在构建哈夫曼树时,我们可以将字符和对应的频率作为优先队列中的元素,根据频率的大小来确定优先级。

每次从优先队列中取出两个频率最小的字符,将它们作为叶子节点构建一个新的二叉树,并将该二叉树的根节点插入到优先队列中。

数据结构 课程设计之哈夫曼编码

数据结构  课程设计之哈夫曼编码

(一) 哈夫曼树的设计思想对于一组具有确定权值的叶子结点可以构造出多个具有不同带权路径长度的二叉树,其中具有最小带权路径长度的二叉树称作哈夫曼树或者最优二叉树。

首先给定n 个权值创造n 个只含根结点的二叉树,得到一个二叉树林;再在这二叉树林里面找根结点的权值最小和次小的两棵树作成新的二叉树,其中新的二叉树的根结点的权值为摆布子根结点权值之和;最后在二叉树林中把组合过的二叉树删除,再重复第二步,直到最后就剩一颗二叉树的时候得到的这棵二叉树就是哈夫曼树。

(二)哈夫曼编码与解码的设计思想在数据通讯中,时常要将传送的文字转换为二进制字符0 和1 组成的二进制串,称这个过程为编码。

与子相对的是解码或者是译码,就是用与编码相同的方式将二进制串转换称编码前的文字的过程称作解码。

在这里是通过哈夫曼树实现编码与解码的,所以称作是哈夫曼编码与解码。

首先输入一个字符串,还有相应的在哈夫曼树里的权值,这样用哈夫曼树把字符串用二进制串代替它,这个过程要注意树和编码问题,其中树的问题在上面已经解决,主要看编码的问题,就是根据我们输入的字符串和权值建立相应的树模型,这一步完成那编码就已经完成为了,最后打印就行了;然后就是解码,完成编码相应的解码就相对简单了,就是先找到在编码的时候建的那个模型树,将编码中的二进制串再根据权值转换为相应的字符串,这样一步步解码就行了。

以上就是通过用哈夫曼树进行哈夫曼编码与解码如何实现的主要设计思想。

(一)哈夫曼树的流程图不 是图 1 哈夫曼树的流程图(二)编码与解码的流程图图 2 编码与解码的流程图图片说明: (左边)编码流程图, (右边)解码流程图。

开始输入字符串判断权值 建立路径有最小和次小 循环建立二叉树根据树对路径分左 0右 1写出对应结点的编码结束开始初始化哈夫曼链表二叉树林找最小和次小 的二叉树组合成新的二叉树 删除用过的二叉树是不是最后一 个二叉树是结束开始找到树的根结点 输入二进制串扫描根据树的路径打印对应字符继续扫描 是否结束是输出字符串结束否下面给出的是用中缀转后缀算法实现的程序的源代码:#include "stdio.h"#include "string.h"#define MAX 100struct HaffNode{int weight;int parent;char ch;int lchild;int rchild;}*myHaffTree;struct Coding{char bit[MAX];char ch;int weight;}*myHaffCode;void Haffman(int n){int i,j,x1,x2,s1,s2;for (i=n+1;i<=2*n-1;i++) {s1=s2=10000;x1=x2=0;for (j=1;j<=i-1;j++)/*定义常量*//*权值*//*双亲结点下标*//*构造哈夫曼树*//*定义数组*//*字符的权值*//*定义结构体*//*定义哈夫曼函数*//*树的初始化*//*构造哈夫曼树的非叶子结点*/{if(myHaffTree[j].parent==0&&myHaffTree[j].weight<s1){s2=s1;x2=x1;s1=myHaffTree[j].weight;x1=j;/*分配摆布结点*/}else if(myHaffTree[j].parent==0&&myHaffTree[j].weight<s2){s2=myHaffTree[j].weight;x2=j;}}myHaffTree[x1].parent=i;myHaffTree[x2].parent=i;myHaffTree[i].weight=s1+s2;myHaffTree[i].lchild=x1;myHaffTree[i].rchild=x2;/*摆布子组合为新树*/}}void HaffmanCode(int n){int start,c,f,i,j,k;char *cd;/*构造n 个结点哈夫曼编码*/cd=(char *)malloc(n*sizeof(char));myHaffCode=(struct Coding *)malloc((n+1)*sizeof(struct Coding));cd[n-1]='\0';for(i=1;i<=n;++i) /*n 个叶子结点的哈夫曼编码*/ {start=n-1;for(c=i,f=myHaffTree[i].parent;f!=0;c=f,f=myHaffTree[f].parent)if(myHaffTree[f].lchild==c) cd[--start]='0';else cd[--start]='1';for(j=start,k=0;j<n;j++){myHaffCode[i].bit[k]=cd[j];k++;}myHaffCode[i].ch=myHaffTree[i].ch; myHaffCode[i].weight=myHaffTree[i].weight; }free(cd);}Init(){int i,n,m;printf("please input the number of words:"); scanf("%d",&n); /*取编码对应的权值*//*定义有返回值的函数*/m=2*n-1;myHaffTree=(struct HaffNode *)malloc(sizeof(struct HaffNode)*(m+1)); for(i=1;i<=n;i++){printf("please input the word and the equal:");scanf("%s%d",&myHaffTree[i].ch,&myHaffTree[i].weight); myHaffTree[i].parent=0;myHaffTree[i].lchild=0;myHaffTree[i].rchild=0;}for(i=n+1;i<=m;i++){myHaffTree[i].ch ='#';myHaffTree[i].lchild=0;myHaffTree[i].parent=0;myHaffTree[i].rchild=0;myHaffTree[i].weight=0;}Haffman(n);HaffmanCode(n);for(i=1;i<=n;i++){printf("%c %d",myHaffCode[i].ch,myHaffCode[i].weight); printf("\n");}printf("init success!\n");return n;}void Caozuo_C(int m){int n,i,j;char string[50],*p;printf("please input the words :"); scanf("%s",string);n=strlen(string);for(i=1,p=string;i<=n;i++,p++){for(j=1;j<=m;j++)if(myHaffCode[j].ch==*p)printf("%s\n",myHaffCode[j].bit); }}void Caozuo_D(int n){int i,c;char code[1000],*p;printf("please input the coding:"); scanf("%s",code);for(p=code,c=2*n-1;*p!='\0';p++) {if(*p=='0'){c=myHaffTree[c].lchild;if(myHaffTree[c].lchild==0){printf("%c",myHaffTree[c].ch);c=2*n-1;continue;/* 编码函数*//*计算字符串长度*/ /*进行编码*//*解码函数*//*输入二进制编码*//*进行解码*//*结束条件*//*赋值*//* 扫描*//*结束*/}}else if(*p=='1'){c=myHaffTree[c].rchild;if(myHaffTree[c].lchild==0){printf("%c",myHaffTree[c].ch);c=2*n-1; /*赋值*/continue;}}}printf("\n");}void main(){int n;char char1;n=Init();printf("A.coding B.codeprintingwhile(1){scanf("%c",&char1);if(char1=='c')break;switch(char1){case'A':Caozuo_C(n);break;case'B':Caozuo_D(n);break;case'C':;break;}}}/*主函数*//*定义字符*//*函数的调用*/C.exit\nplease input the process:\n");/*判断字符*//*执行编码操作*//*执行解码操作*/哈夫曼编码与解码的实现(一)中缀转后缀算法的运行结果:这部份我主要遇到了如下三个问题,其内容与解决方法如下所列:问题1:刚开始不知道如何建一个好树,因为我开始试着建了几个二叉树,不知道什么原因运行的时候那编码总是不对,跟在草稿纸上自己画的那个二叉树总是不相符,就找原因。

数据结构课程设计哈夫曼编码实验

数据结构课程设计哈夫曼编码实验

数据结构设计性实验Huffman编码与译码学号姓名班级设计性实验—Huffman 编码与译码一.实验目的:在掌握相关基础知识的基础上,学会自己设计实验算法,熟练掌握Huffman 树的建立方法,Huffman 编码的方法,进而设计出Huffman 译码算法,并编程实现。

二.实验要求:在6学时以内,制作出能够实现基于26个英文字母的任意字符串的编译码。

写出技术工作报告并附源程序。

三.实验内容及任务:1.设字符集为26个英文字母,其出现频度如下表所示。

2.建Huffman 树; 3.利用所建Huffman 树对任一字符串文件进行编码——即设计一个Huffman 编码器;4.对任一字符串文件的编码进行译码——即设计一个Huffman 译码器。

实现步骤:1.数据存储结构设计; 2.操作模块设计; 3.建树算法设计; 4.编码器设计;5. 译码器设计;51 48 1 15 63 57 20 32 5 1频度z y x w v u t 字符11611882380频度p 21 f q15 g r 47 h s o n m l k j 字符 57 103 32 22 13 64 186 频度 i e d c b a 空格 字符四.分析以及算法描述1.分析问题1)首先学习二叉树的知识,了解二叉树的路径、权数以及带权路径长度计算。

2)认识霍夫曼树,了解霍夫曼树的定义,构造霍夫曼树构造算法①又给定的n个权值{w1,w2,w3,……,w n}构造根节点的二叉树,从而得到一个二叉树森林F={T1,T2,T3,……T n}。

②在二叉树森里选取根节点全职最小和此最小的两棵二叉树作为左右节点构造新的二叉树,此时新的二叉树的根节点权值为左右子树权值之和。

③在二叉树森林中删除作为新二叉树的根节点左右子树的两棵二叉树,将新的二叉树加入到二叉树森林F中。

④重复②和③,当二叉树森林F只剩下一棵二叉树时,这棵二叉树是所构造的霍夫曼树。

3)练习通过普通树来构造霍夫曼树。

《数据结构课程设计》赫夫曼编码实验报告

《数据结构课程设计》赫夫曼编码实验报告

目录一、概述 (1)二、系统分析 (1)三、概要设计 (2)四、详细设计 (4)4.1 赫夫曼树的建立 (4)4.1.1 选择选择parent 为0 且权值最小的两个根结点的算法 (5)4.1.2 统计字符串中字符的种类以及各类字符的个数 (7)4.1.3构造赫夫曼树 (8)4.2赫夫曼编码 (10)4.2.1赫夫曼编码算法 (10)4.2.2建立正文的编码文件 (11)4.3代码文件的译码 (12)五、运行与测试 (14)六、总结与心得 (14)参考文献 (15)附录 (15)一、概述本设计是对输入的一串电文字符实现赫夫曼编码,再对赫夫曼编码生产的代码串进行译码,输出电文字符串。

在当今信息爆炸时代,如何采用有效的数据压缩技术节省数据文件的存储空间和计算机网络的传送时间越来越引起人们的重视,赫夫曼编码正是一种应用广泛且非常有效的数据压缩技术。

二、系统分析赫夫曼编码的应用很广泛,利用赫夫曼树求得的用于通信的二进制编码成为赫夫曼编码。

树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为和每个叶子对应的字符的编码,这就是赫夫曼编码。

通常我们把数据压缩的过程称为编码,解压缩的过程称为解码。

电报通信是传递文字的二进制码形式的字符串,但在信息传递时,总希望总长度能尽可能短,即采用最短码。

假设每种字符在电文中出现的次数为W i ,编码长度为L i ,电文中有n 种字符,则电文编码总长为∑W i L i 。

若将此对应到二叉树上,W i 为叶节点的权,L i 为根节点到叶节点的路径长度。

那么,∑W i L i 恰好为二叉树上带权路径长度。

因此,设计电文总长最短的二进制前缀编码,就是以n 种子符出现的频率作权,构造一刻赫夫曼树,此构造过程成为赫夫曼编码。

根据设计要求和分析,要实现设计,必须实现以下方面的功能:(1)赫夫曼树的建立;(2)赫夫曼编码的生成;(3)编码文件的译码;三、概要设计程序由哪些模块组成以及模块之间的层次结构、各模块的调用关系;每个模块的功能。

数据结构课程设计哈夫曼编码

数据结构课程设计哈夫曼编码

数据结构课程设计报告题目:赫夫曼编码一、需求分析1. 问题描述利用赫夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。

这要求在发送端通过一个编码系统对待传输数据预先编码,在接收端将传来的数据进行译码(复原)。

对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。

试为这样的信息收发站编写一个赫夫曼码的编/译码系统。

2.基本要求一个完整的系统应具有以下功能:(1) I:初始化(Initialization)。

从终端读入字符集大小n,以及n个字符和n个权值,建立赫夫曼树,并将它存于文件hfmTree中。

(2) E:编码(Encoding)。

利用已建好的赫夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。

(3) D:译码(Decoding)。

利用已建好的赫夫曼树将文件CodeFile中的代码进行译码,结果存入文件Textfile中。

(4) P:印代码文件(Print)。

将文件CodeFile以紧凑格式显示在终端上,每行50个代码。

同时将此字符形式的编码文件写入文件CodePrin中。

(5) T:印赫夫曼树(Tree printing)。

将已在内存中的赫夫曼树以直观的方式(比如树)显示在终端上,同时将此字符形式的赫夫曼树写入文件TreePrint 中。

3.测试要求(1) 已知某系统在通信联络中只可能出现八种字符,其频率分别为0.05,0.29,0.07,0.08,0.14,0.23,0.03,0.11,试设计赫夫曼编码。

(2) 用下表给出的字符集和频度的实际统计数据建立赫夫曼树,并实现以下报文的编码和译码:“THIS PROGRAME IS MY FA VORITE”。

4.实现提示(1) 编码结果以文本方式存储在文件Codefile中。

(2) 用户界面可以设计为“菜单”方式:显示上述功能符号,再加上“Q”,表示退出运行Quit。

数据结构课程设计报告(HuffMan编码器)

数据结构课程设计报告(HuffMan编码器)

《数据结构》课程设计报告题目:HuffMan编码器目录一.问题描述二.基本要求(需求分析)三.•概要设计(设计思想、实现方法、模块设计)四.•详细设计(数据结构设计、算法设计、算法分析)五.测试数据及测试结果六.课程设计小结(心得体会、存在问题、改进措施)一.问题描述利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。

但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。

对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。

试为这样的信息收发站写一个哈夫曼码的编/译码系统。

二.基本要求(需求分析)一个完整的系统应具有以下功能:(1)I:初始化(Initialization)。

从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree中。

(2)E:编码(Encoding)。

利用已建好的哈夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。

(3)D:译码(Decoding)。

利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。

(4)P:印代码文件(Print)。

将文件CodeFile以紧凑格式显示在终端上,每行50个代码。

同时将此字符形式的编码文件写入文件CodePrin中。

(5)T:印哈夫曼树(Tree printing)。

将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。

[测试数据]用下表给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:“THIS PROGRAM IS MY FA VORITE”。

字符空格 A B C D E F G H I J K L M频度186 64 13 22 32 103 21 15 47 57 1 5 32 20字符N O P Q R S T U V W X Y Z频度57 63 15 1 48 51 80 23 8 18 1 16 1[实现提示](1)编码结果以文本方式存储在文件CodeFile中。

数据结构课程设计报告 哈弗曼编码

数据结构课程设计报告 哈弗曼编码

数据结构课程设计院系:班级:组别:指导教师:摘要随着计算机的普遍应用与日益发展,其应用早已不局限于简单的数值运算,而涉及到问题的分析、数据结构框架的设计以及设计最短路线等复杂的非数值处理和操作。

算法与数据结构的学习就是为以后利用计算机资源高效地开发非数值处理的计算机程序打下坚实的理论、方法和技术基础。

算法与数据结构旨在分析研究计算机加工的数据对象的特性,以便选择适当的数据结构和存储结构,从而使建立在其上的解决问题的算法达到最优。

数据结构是在整个计算机科学与技术领域上广泛被使用的术语。

它用来反映一个数据的内部构成,即一个数据由那些成分数据构成,以什么方式构成,呈什么结构。

数据结构有逻辑上的数据结构和物理上的数据结构之分。

逻辑上的数据结构反映成分数据之间的逻辑关系,而物理上的数据结构反映成分数据在计算机内部的存储安排。

数据结构是数据存在的形式。

《数据结构》主要介绍一些最常用的数据结构,阐明各种数据结构内在的逻辑关系,讨论其在计算机中的存储表示,以及在其上进行各种运算时的实现算法,并对算法的效率进行简单的分析和讨论。

数据结构是介于数学、计算机软件和计算机硬件之间的一门计算机专业的核心课程,它是计算机程序设计、数据库、操作系统、编译原理及人工智能等的重要基础,广泛的应用于信息学、系统工程等各种领域。

学习数据结构是为了将实际问题中所涉及的对象在计算机中表示出来并对它们进行处理。

通过课程设计可以提高学生的思维能力,促进学生的综合应用能力和专业素质的提高。

目录一.设计目的数据结构作为一门学科主要研究数据的各种逻辑结构和存储结构,以及对数据的各种操作。

因此,主要有三个方面的内容:数据的逻辑结构;数据的物理存储结构;对数据的操作(或算法)。

通常,算法的设计取决于数据的逻辑结构,算法的实现取决于数据的物理存储结构。

数据结构是信息的一种组织方式,其目的是为了提高算法的效率,它通常与一组算法的集合相对应,通过这组算法集合可以对数据结构中的数据进行某种操作。

数据结构_课程设计报告(哈夫曼编码)

数据结构_课程设计报告(哈夫曼编码)

(原创)数据结构课程设计报告学院:计算机科学与工程专业:计算机科学与技术班级:09级班学号:姓名:指导老师:时间: 2010年12月一、课程设计题目:1、哈夫曼编码的实现2、城市辖区地铁线路设计3、综合排序算法的比较二、小组成员:三、题目要求:1.哈夫曼编码的实现(1)打开若干篇英文文章,统计该文章中每个字符出现的次数,进一步统一各字符出现的概率。

(2)针对上述统计结果,对各字符实现哈夫曼编码(3)对任意文章,用哈夫曼编码对其进行编码(4)对任意文章,对收到的电文进行解码2.某城市要在其各个辖区之间修建地铁来加快经济发展,但由于建设地铁的费用昂贵,因此需要合理安排地铁的建设路线。

(1)从包含各辖区的地图文件中读取辖区的名称和各辖区的直接距离(2)根据上述读入的信息,给出一种铺设地铁线路的解决方案。

使乘客可以沿地铁到达各个辖区,并使总的建设费用最小。

(3)输出应该建设的地铁路线及所需要建设的总里程信息。

3.综合排序算法的比较各种内部排序算法的时间复杂度分析结果只给出了算法执行时间的阶,或大概的执行时间。

试通过随机的数据比较各算法的关键字比较次数和关键字移动的次数。

(1)对以下各种常用的内部排序算法进行比较:直接插入排序,折半插入排序,二路归并排序,希尔排序,冒泡排序,快速排序,简单选择排序,堆排序,归并排序,基数排序。

(2)待排序的表长不少于100,要求采用随机数。

(3)至少要用5组不同的输入数据做比较:比较的次数为有关键字参加的比较次数和关键字移动的次数(4)改变数据量的大小,观察统计数据的变化情况。

(5)对试验统计数据进行分析。

对各类排序算法进行综合评价。

四、项目安排:1、小组内分工合作分工:xx负责哈夫曼编码的实现,zz负责城市辖区地铁线路设计,yy负责综合排序算法的比较。

合作:组内,组外进行交流,组长帮助解决组员的在项目过程中的困难,并控制进度。

五、完成自己的任务:任务:哈夫曼编码的实现1、思想实现流程图2、代码实现头文件define.h#ifndef _DEFINE_H_#define _DEFINE_H_#include <windows.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#define n 128typedef struct{int weight;int parent,lchild,rchild;}HuffmanTree; //哈夫曼树数据类型typedef struct{int ch;char codes[30];}coding; //哈夫曼编码数据存储typedef struct{int point;char codes[30]; //栈存}stack;extern void stat_file(HuffmanTree charer[256]); //统计字符频率extern void make_tree(HuffmanTree charer[256]); //构造哈夫曼树extern void make_code(HuffmanTree charer[256],coding inside[128]); //生成字符编码extern void article_code(coding inside[128]); //文章转码extern void decoding(HuffmanTree charer[256]); //文章解码#endif主函数:main.cpp#include "define.h"void main(){char choose;HuffmanTree charer[256];coding inside[128];printf("********************************************\n");printf(" 请选择\n");printf("*********** 1 刷新哈夫曼编码**********\n");printf("*********** 2 用统计频率编码**********\n");printf("*********** 3 任意文章编码**********\n");printf("*********** 4 任意文章解码**********\n");printf("*********** 0 退出本系统**********\n");printf("********************************************\n");do{fflush(stdin);scanf("%c",&choose); //暂时未加入未进行编码的判断switch(choose){case '1':memset(charer,0,256*sizeof(HuffmanTree));stat_file(charer);printf("请继续选择相应选项\n");break;case '2':make_tree(charer);memset(inside,0,128*sizeof(coding)); //先清空make_code(charer,inside);printf("请继续选择相应选项\n");break;case '3':article_code(inside);printf("请继续选择相应选项\n");break;case '4':decoding(charer); //如果只进行反编译,必须要输入相同的文章以建立哈夫曼树,printf("译码完毕!请打开根目录下的文件查看!\n"); //而之前翻译成代码时也要使用相同文章printf("请继续选择相应选项\n");break;case '0':MessageBox(NULL," 已退出系统!","提示",MB_OK);break;default: printf("对不起,您的操作错误,请重新输入编号!");}}while (choose!='0');}函数1:input_files.cpp#include "define.h"void stat_file(HuffmanTree charer[256]){FILE *fp;char choose;int i,looking;char path[30];loop: printf("请输入文件名:\n"); //设置循环点scanf("%s",path);if((fp=fopen(path,"r"))==NULL) //寻找文件{printf("文件不存在\n");goto loop;}for(i=0;1;i++) // 对应字符的数组元素++{looking=fgetc(fp);if(looking==EOF)break;charer[looking].weight++;}fflush(stdin);printf("继续增加文件???(y/n)?\n");scanf("%c",&choose); //选择if(choose == 'y')goto loop; //返回循环点fclose(fp); //关闭文件}函数2:make_tree.cpp#include "define.h"void make_tree(HuffmanTree charer[256]) //建树函数{int i,min1,min2;int k,j;int flag1=0,flag2=0;void prnt(HuffmanTree charer[256]); //输出到文件中,以后改进时可以直接从文件读取for(i=0;i<n-1;i++) //两重多组的循环,算法不太好,比较的次数递增{for(k=0;k<n+i;k++)if( charer[k].parent == 0) //找出第一个叶子作为最小值{min1=charer[k].weight;flag1=k;break;}for(j=k;j<n+i;j++){if(min1==0) //考虑0的情况,减少循环break;if(charer[j].weight < min1 && charer[j].parent == 0) //否则进行比较{min1=charer[j].weight;flag1=j;}}for(k=0;k<n+i;k++)if( charer[k].parent == 0 && k!=flag1) //找第二个叶子作为次小值{min2=charer[k].weight;flag2=k;break;}for(j=k;j<n+i;j++){if(min2==0)break;if(charer[j].weight < min2 && charer[j].parent == 0 && j!=flag1){min2=charer[j].weight;flag2=j;}}charer[n+i].weight=charer[flag1].weight+charer[flag2].weight; //关键步骤:最小值和次小值的相加并构成子树charer[n+i].rchild=flag1;charer[n+i].lchild=flag2;charer[flag1].parent=n+i;charer[flag2].parent=n+i;}prnt(charer); //顺便输出到文件中}void prnt(HuffmanTree charer[256]){FILE *fp;char sn[20]={"哈夫曼树的如下:"};char xinxi[5][7]={"序号","权值","双亲","左孩子","右孩子"};fp = fopen("HuffmanTree.txt","w+");fprintf(fp,"%s\n",sn);fprintf(fp,"%s\t%s\t%s\t%s\t%s\n",xinxi[0],xinxi[1],xinxi[2],xinxi[3],xinxi[4]);for(int i=0;i<255;i++)fprintf(fp,"%d\t%d\t%d\t%d\t%d\n",i,charer[i].weight,charer[i].parent,charer[i].lc hild,charer[i].rchild);fclose(fp);MessageBox(NULL," 哈夫曼树写入文件成功!","提示",MB_OK);system("HuffmanTree.txt");}函数4:produce_code.cppvoid make_code(HuffmanTree charer[256],coding inside[128]) //从哈夫曼树中生成字符编码{stack push_pop;int k,j;void prn(coding inside[128]); //把编码输出到文件中,共128个for(int i=0;i<128;i++){memset(&push_pop,0,1*sizeof(stack)); //栈存inside[i].ch=i;for(k=i,j=0;1; ) //下面可控制循环退出{if(charer[k].parent!=0) //从下往上找到根节点{if(charer[charer[k].parent].lchild==k) // 子根节点的左孩子编0,右孩子编1push_pop.codes[push_pop.point++]='0'; //压栈// push_pop.point++; // 把++直接放入括号,减少代码量if(charer[charer[k].parent].rchild==k)push_pop.codes[push_pop.point++]='1';// push_pop.point++;j=k;k=charer[k].parent;}else{/* if(charer[charer[j].parent].lchild==j){push_pop.codes[push_pop.point++]='0';// push_pop.point++;}if(charer[charer[j].parent].rchild==j){push_pop.codes[push_pop.point++]='1';// push_pop.point++;}*/break;}}for(k=0,j=push_pop.point;k<push_pop.point;) //从栈顶回取,所得编码存入所设数组inside[i].codes[k++]=push_pop.codes[--j];}prn(inside);}void prn(coding inside[128]){FILE *fp;char sn[20]={"编码的如下:"};char xinxi[3][5]={"序号","字符","编码"};fp = fopen("HuffmanCode.txt","w+");fprintf(fp,"%s\n",sn);fprintf(fp,"%s\t%s\t%s\n",xinxi[0],xinxi[1],xinxi[2]);for(int i=0;i<128;i++)fprintf(fp,"%d\t%c\t%s\n",i,inside[i].ch,inside[i].codes);fclose(fp);MessageBox(NULL," 编码写入文件成功!","提示",MB_OK);system("HuffmanCode.txt");}函数5:article_code.Cpp#include "define.h"void article_code(coding inside[128]){FILE *fp,*fq;char path[50];char ch=0;printf("请输入需要转码的文章名称:\n");scanf("%s",path);if((fp=fopen(path,"r"))==NULL) //寻找文件{MessageBox(NULL," 文件不存在!","提示",MB_OK);exit(1);}fq=fopen("article_code.txt","w+");for(int i=0;1;i++) //从文件读取字符,转换成编码写入文件中{ch=fgetc(fp);if(ch==EOF) //防止多读一次加入到中间比较好break;fprintf(fq,"%s",inside[ch].codes);}fclose(fp); //关闭文件fclose(fq);MessageBox(NULL," 文章转换完毕!","提示",MB_OK);system("article_code.txt");}函数6:decoding.cpp#include "define.h"void decoding(HuffmanTree charer[256]){FILE *fp,*fq; //文件指针,一个读取,一个写入char path[20];int k;char ch;loop: printf("请输入需要解码文件的路径:\n");scanf("%s",path);if((fp=fopen(path,"r"))==NULL) //寻找文件{printf("文件不存在,请确认路径是否正确! \n");goto loop;}fq=fopen("decoding.txt","w+");for(int i=0;1;i++) //从文件中读取编码,由根进行寻找{k=254;ch=fgetc(fp);if(ch==EOF)break;for(int j=0;1;j++){if(ch=='0') //左孩子,继续判断左孩子的左右孩子是否存在,{if(charer[charer[k].lchild].lchild==0 && charer[charer[k].lchild].rchild==0){fprintf(fq,"%c",charer[k].lchild);break;}k=charer[k].lchild; //非叶子节点,即刻转向孩子节点,并进行下一次判断ch=fgetc(fp);if(ch==EOF)break;continue; //读取下一个}if(ch=='1') //右孩子,继续判断右孩子的左右孩子是否存在,不存在即为叶子节点。

数据结构课程设计哈夫曼编码译码器

数据结构课程设计哈夫曼编码译码器

题目一: 哈夫曼编码与译码一、任务设计一个运用哈夫曼算法的编码和译码系统, 反复地显示并解决以下项目, 直到选择退出为止。

规定:1) 将权值数据存放在数据文献(文献名为data.txt, 位于执行程序的当前目录中) ;2) 初始化:键盘输入字符集记录字符权值、自定义26个字符和26个权值、记录文献中一篇英文文章中26个字母, 建立哈夫曼树;3) 编码: 运用建好的哈夫曼树生成哈夫曼编码;4) 输出编码(一方面实现屏幕输出, 然后实现文献输出);5)译码(键盘接受编码进行译码、文献读入编码进行译码);6) 界面优化设计。

二、流程图三、代码分解 //头文献 #include<stdio.h> #include<string.h> #include<stdlib.h> #include <conio.h> #define N 1000 #define M 2*N-1 #define MAXcode 6000 //函数声明void count(CHar &ch,HTNode ht[]);void editHCode(HTNode ht[],HCode hcd[],CHar &ch,int n,char bianma[]); //编码函数void printyima(HTNode ht[],HCode hcd[],int n,char bianma[]); //译码函数 void creatHT(HTNode ht[],int n);字符集记录符集记录权值 权值 至文献“哈夫曼树。

t xt” 菜单1.从键盘输入字符集进行编码2.从文献读入字符集进行编码1.从键盘输入编码进行译码2.从文献读入编码进行译码0.返回上级菜单 0.返回上级菜单void CreateHCode (HTNode ht[],HCode hcd[],int n);void DispHCode(HTNode ht[],HCode hcd[],int n);void input_key(CHar &ch);void input_file(CHar &ch);void input_cw(HTNode ht[]);void bianma1(HTNode ht[],HCode hcd[],CHar &ch,int n,char bianma[]); void bianma2(HTNode ht[],HCode hcd[],CHar &ch,int n,char bianma[]); void yima1(HTNode ht[],HCode hcd[],int n,char bianma[]);void yima2(HTNode ht[],HCode hcd[],int n,char bianma[]);void creat_cw();void bianmacaidan();void yimacaidan();void bianmayima();int caidan();//结构体typedef struct{char data;int parent;int weight;int lchild;int rchild;}HTNode;typedef struct{char cd[N];int start;}HCode;typedef struct{char s[N];int num;}CHar;CHar ch;HTNode ht[M];HCode hcd[N];//主函数int main(){int xh;while(1){system("color 1f"); //操作菜单背景颜色 xh=caidan(); //调用菜单函数switch(xh) //switch语句 {case 1:system("cls");creat_cw();break;case 2:system("cls");creatHT(ht,n);break;case 3:system("cls");CreateHCode(ht,hcd,n);DispHCode(ht,hcd,n);break;case 4:system("cls");bianmayima();break;case 0:system("cls");printf("\n\n\n\n\n\n\n\n\n\t\t\t\t感谢使用本系统!\n\n\n\n\n\n\n \t\t\t");exit(0);default:system("cls");putchar('\a');printf("\n\t\t输入有误, 请重新输入:\n");break;}}return 0;}//菜单函数int caidan() //菜单函数模块//{int xh;printf("\n\n\n");printf("\t\t 欢迎使用哈夫曼编码译码系统\n");printf("\t\t \n");printf("\t\t*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*\n");printf("\t\t*= =*\n");printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*= =*\n");printf("\t\t*= 1.建立字符权值=*\n");printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*= =*\n"); printf("\t\t*= 2.建立并输出哈夫曼树=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*= =*\n"); printf("\t\t*= 3.生成并查看哈夫曼编码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*= =*\n"); printf("\t\t*= 4.编码与译码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*= =*\n"); printf("\t\t*= 0.退出系统=*\n"); printf("\t\t*= =*\n"); printf("\t\t*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*\n"); printf("\n\t\t请输入序号进行选择:");scanf("%d", &xh);return xh; //返回从键盘接受的选项}void bianmayima(){int xh;while(1){printf("\n\n\n\n\n");printf("\t\t 编码与译码\n"); printf("\t\t \n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n");printf("\t\t*= 1.编码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 2.译码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 0.返回上级菜单=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\n\t\t请输入序号进行选择:");scanf("%d",&xh);switch(xh) //switch语句{case 1:system("cls");bianmacaidan();break;case 2:system("cls");yimacaidan();break;case 0:system("cls");return;default:system("cls");putchar('\a');printf("\n\t\t输入有误, 请重新输入:\n");break;}}}void yimacaidan(){int xh;while(1){printf("\n\n\n\n\n");printf("\t\t 译码\n"); printf("\t\t \n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 1.键盘输入编码进行译码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 2.文献读入编码进行译码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 0.返回上级菜单=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\n\t\t请输入序号进行选择:");scanf("%d",&xh);switch(xh) //switch语句{case 1:system("cls");yima1(ht,hcd,n,bianma);break;case 2:system("cls");yima2(ht,hcd,n,bianma);break;case 0:system("cls");return;default:system("cls");putchar('\a');printf("\n\t\t输入有误, 请重新输入:\n");break;}}}void bianmacaidan(){int xh;while(1){printf("\n\n\n\n\n");printf("\t\t 编码\n"); printf("\t\t \n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 1.键盘输入字符集编码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 2.文献读入文章编码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 0.返回上级菜单=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\n\t\t请输入序号进行选择:");scanf("%d",&xh);switch(xh) //switch语句{case 1:system("cls");bianma1(ht,hcd,ch,n,bianma);break;case 2:system("cls");bianma2(ht,hcd,ch,n,bianma);break;case 0:system("cls");return;default:system("cls");putchar('\a');printf("\n\t\t输入有误, 请重新输入:\n");break;}}}void creat_cw(){int xh2;while(1){printf("\n\n\n\n\n");printf("\t\t 建立字符权值\n"); printf("\t\t \n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 1.从键盘输入字符集进行记录=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 2.从文献读入字符集记录=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 3.自定义字符权值=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 0.返回上级菜单=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\n\t\t请输入序号进行选择:");scanf("%d",&xh2);switch(xh2) //switch语句{case 1:system("cls");input_key(ch);break;case 2:system("cls");input_file(ch);break;case 3:system("cls");input_cw(ht);break;case 0:system("cls");return;default:system("cls");putchar('\a');printf("\n\t\t输入有误, 请重新输入:\n");break;}}}//建立字符权值模块void input_key(CHar &ch){int i,j=0;char st[N];printf("请输入字符集(以‘#’结束):\n");for(i=0;i<N;i++){scanf("%c",&st[i]);if(st[i]=='#'){st[i]='\0';break;}}strcpy(ch.s,st);count(ch,ht);printf("按任意键返回!");getch();system("cls");return;}void input_file(CHar &ch){int i;FILE*fp;char filename[20];printf("请输入要打开的文献名(*.txt):");scanf("%s",&filename);if((fp=fopen(filename,"r"))==NULL){printf("\n\t\t文献打开失败");return;}for(i=0;!feof(fp);i++){fread(&ch.s[i],sizeof(char),1,fp);}printf("读入成功!\n");printf("文献中的字符集为:%s\n",ch.s);fclose(fp);count(ch,ht);printf("按任意键返回!");getch();system("cls");return;}void input_cw(HTNode ht[]){int i,w,s,j;char a;printf("要输入的字符总个数是?:");scanf("%d",&s);n=s;printf("请输入字符及其权值:\n");for(i=0;i<s;i++){printf("请输入第%d个字母:",i+1);scanf("%s",&a);ht[i].data=a;printf("请输入其权值:");scanf("%d",&w);ht[i].weight=w;}FILE *fp;if((fp=fopen("data.txt","w"))==0){printf("\n\t\t文献打开失败");return;}printf("\n定义权值成功!\n\n");printf("各字符及其权值为:\n\n");fprintf(fp,"各字符及其权值为:\n");printf(" 字符\t权值");fprintf(fp," 字符\t权值");for(j=0;j<i;j++){ printf("\n");fprintf(fp,"\n");printf(" %-8c%-8d",ht[j].data,ht[j].weight);fprintf(fp," %-8c%-8d%",ht[j].data,ht[j].weight); }printf("\n");printf("\n字符权值已输出至文献“data.txt”!");fclose(fp);printf("输入完毕, 按任意键返回!");getch();system("cls");return;}//记录字符权值函数void count(CHar &ch,HTNode ht[]){int i,j,m=0;char c[N];int sum[N]={0};for(i=0;ch.s[i]!='\0';i++){for(j=0;j<m;j++)if(ch.s[i]==c[j]||(c[j]>='a'&&c[j]<='z'&&ch.s[i]+32==c[j])) break;if(j<m)sum[j]++;else{if(ch.s[i]>='A'&&ch.s[i]<='Z')c[j]=ch.s[i]+32;else c[j]=ch.s[i];sum[j]++;m++;}}for(i=0;i<m;i++){ht[i].data=c[i];ht[i].weight=sum[i];}n=m;FILE *fp;if((fp=fopen("data.txt","w"))==0) {printf("\n\t\t文献打开失败"); return;}printf("\n记录权值成功!\n\n"); printf("各字符及其权值为:\n\n"); fprintf(fp,"各字符及其权值为:\n"); printf(" 字符\t权值");fprintf(fp," 字符\t权值");for(j=0;j<m;j++){ printf("\n");fprintf(fp,"\n");printf(" %-8c%-8d",ht[j].data,ht[j].weight);fprintf(fp," %-8c%-8d%",ht[j].data,ht[j].weight);}printf("\n");printf("\n字符权值已输出至文献“data.txt”!");fclose(fp);}//构造哈夫曼树void creatHT(HTNode ht[],int n){FILE *fp;if((fp=fopen("哈夫曼树.txt","w"))==0){printf("\n\t\t文献打开失败");return;}int i,j,k,lnode,rnode;int min1,min2;for (i=0;i<2*n-1;i++)ht[i].parent=ht[i].lchild=ht[i].rchild=-1;for (i=n;i<2*n-1;i++){min1=min2=32767;lnode=rnode=-1;for(k=0;k<=i-1;k++)if(ht[k].parent==-1){if (ht[k].weight<min1){min2=min1;rnode=lnode;min1=ht[k].weight;lnode=k;}else if(ht[k].weight<min2){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].lchild=lnode;ht[i].rchild=rnode;}printf("建立huffman树成功!\n");printf("输出huffman树:\n");fprintf(fp,"输出huffman树:\n");printf("\t字符\t权值\t父节点\t 左子节点\t右子节点");fprintf(fp,"\t字符\t权值\t父节点\t 左子节点\t右子节点");for(j=1;j<i;j++){ printf("\n");fprintf(fp,"\n");printf("\t %-8c%-8d%-10d%-14d%-10d",ht[j].data,ht[j].weight,ht[j].parent,ht[i]. lchild,ht[j].rchild);fprintf(fp,"\t %-8c%-8d%-10d%-14d%-10d",ht[j].data,ht[j].weight,ht[j].parent,h t[i].lchild,ht[j].rchild);}printf("\n");printf("哈夫曼树已输出至文献“哈夫曼树.txt”!按任意键返回!");fclose(fp);getch();system("cls");return;}//生成哈夫曼编码void CreateHCode (HTNode ht[],HCode hcd[],int n){int i,f,c,j=0;HCode hc;for(i=0;i<n;i++){hc.start=n;c=i;hc.cd[hc.start--]='0';f=ht[i].parent;while(f!=-1){if (ht[f].lchild==c)hc.cd[hc.start--]='0';elsehc.cd[hc.start--]='1';c=f;f=ht[f].parent;}hc.start++;for(j=0;j<hc.start;j++)hc.cd[j]=' ';hcd[i]=hc;}}void DispHCode(HTNode ht[],HCode hcd[],int n) {FILE *fp;if((fp=fopen("哈夫曼编码.txt","w"))==0){printf("\n\t\t文献打开失败");return;}int i,k;int sum=0,m=0,j;printf("输出字符哈夫曼编码:\n"); fputs("输出字符哈夫曼编码:\n",fp); for (i=0;i<n;i++){j=0;printf("%c:\t",ht[i].data);fprintf(fp,"\n%c:\t",ht[i].data);for (k=hcd[i].start;k<=n;k++){printf("%c",hcd[i].cd[k]);j++;fprintf(fp,"%c",hcd[i].cd[k]); }m+=ht[i].weight;sum+=ht[i].weight*j;printf("\n");}printf("\n哈夫曼编码已保存至文献“哈夫曼编码.txt!按任意键返回!”");fclose(fp);getch();system("cls");}//编码函数void bianma1(HTNode ht[],HCode hcd[],CHar &ch,int n,char bianma[]){int i;char str[N];printf("请输入要编码的字符集(以‘#’结束):\n");for(i=0;i<N;i++){scanf("%c",&str[i]);if(str[i]=='#'){str[i]='\0';break;}}strcpy(ch.s,str);ch.num=strlen(str);editHCode(ht,hcd,ch,n,bianma);getch();system("cls");}void bianma2(HTNode ht[],HCode hcd[],CHar &ch,int n,char bianma[]) {int i;FILE*fp;char filename[20];printf("请输入要打开的文献名(*.txt):");scanf("%s",&filename);if((fp=fopen(filename,"r"))==NULL){printf("\n\t\t文献打开失败");return;}for(i=0;!feof(fp);i++){fread(&ch.s[i],sizeof(char),1,fp);}ch.num=strlen(ch.s);printf("\n读入成功!\n");printf("文献中的字符集为:\n%s",ch.s);fclose(fp);editHCode(ht,hcd,ch,n,bianma);system("cls");return;}//译码函数void yima1(HTNode ht[],HCode hcd[],int n,char bianma[]) {int i;char code[MAXcode];printf("请输入编码进行译码(以‘#’结束):\n");for(i=0;i<MAXcode;i++){scanf("%c",&code[i]);if(code[i]=='#'){code[i]='\0';break;}}strcpy(bianma,code);printyima(ht,hcd,n,bianma);printf("\n译码完毕!按任意键返回!");getch();system("cls");return;}void yima2(HTNode ht[],HCode hcd[],int n,char bianma[]) {int i;FILE*fp;char filename[20];printf("请输入要打开的文献名(*.txt):");scanf("%s",&filename);if((fp=fopen(filename,"r"))==NULL){printf("\n\t\t文献打开失败");return;}for(i=0;!feof(fp);i++){fread(&bianma[i],sizeof(char),1,fp);}printf("读入成功!\n");printf("文献中的编码是:%s\n",bianma);printyima(ht,hcd,n,bianma);printf("\n译码完毕!按任意键返回!");getch();system("cls");}四、调试结果主菜单建立字符权值选择2.从文献读入字符进行记录输入测试文献名“cs.txt”输出个字符权值建立哈夫曼树并输出至文献生成哈夫曼编码并保存至文献编码选择2.从文献读入字符集编码编码结果保存至文献译码选择2.从文献读入编码, 读入上一步的编码译码完毕, 返回!退出系统。

数据结构课程设计哈夫曼编码译码器

数据结构课程设计哈夫曼编码译码器

数据结构课程设计哈夫曼编码译码器个节点的权值、父节点、左孩子和右孩子,然后通过选择最小的两个节点合并,构建Huffman树;3:Huffman编码:通过遍历Huffman树,对每个叶子节点进行编码,将编码结果存入新的文件中;4:译码:读取存放Huffman编码的文件,通过遍历Huffman树进行译码,将译码结果存入新的文件中;5:结果验证:比较原文件和译码结果文件的内容是否一致,输出结果;3.函数说明1:CrtHuffmanTree():创建Huffman树;2:HuffmanCoding():对Huffman树进行遍历,生成Huffman编码;3:HuffmanDecoding():对Huffman编码进行译码,生成原文件内容;4:CompareFile():比较原文件和译码结果文件的内容是否一致;五、详细设计1.统计字符频率:定义结构体typedef struct strchar data;char num;str;其中data域存放字符名称,num域存放字符出现频率,读取文件ywq1.txt,通过循环比较将结果赋入S2[128]中;2.创建Huffman树:定义结构体typedef structchar data;int weight;int parent;int lchild;int rchild;HTNode,HuffmanTree[M+1];作为Huffman树存储节点类型,调用CrtHuffmanTree()函数,初始化各个节点的权值、父节点、左孩子和右孩子,然后通过选择最小的两个节点合并,构建Huffman树;3.Huffman编码:通过遍历Huffman树,对每个叶子节点进行编码,将编码结果存入新的文件中;4.译码:读取存放Huffman编码的文件,通过遍历Huffman树进行译码,将译码结果存入新的文件中;5.结果验证:比较原文件和译码结果文件的内容是否一致,输出结果;六、测试1.测试数据测试文件:ywq1.txt(包含英文字母、数字和符号)2.测试结果测试结果正确,能够正确地对文件进行Huffman编码和译码,生成的译码结果文件与原文件内容一致;七、总结通过本次课程设计,我深入了解了Huffman编码/译码器的实现原理和过程,掌握了Huffman树的创建、存储和遍历方法,提高了动手能力,同时也为数据压缩问题提供了一种有效的解决方法。

数据结构课程设计--哈夫曼编码问题的设计和实现

数据结构课程设计--哈夫曼编码问题的设计和实现

题目哈夫曼编码问题的设计和实现课程名称数据结构课程设计院(系、部、中心)专业班级学生姓名学号设计地点指导教师设计起止时间:2008 年6月2日至2008 年6月 6 日目录1 问题描述 (2)1.1 题目内容 (2)1.2 基本要求 (3)1.3 测试数据 (3)2 需求分析 (3)2.1 程序的基本功能 (3)2.2 输入值、输出值以及输入输出形式 (3)2.3 各个模块的功能要求 (4)3 概要设计 (4)3.1 所需的ADT,每个程序中使用的存储结构设计说明(如果指定存储结构请写出该存储结构的定义) (4)3.2 主程序流程以及模块调用关系 (5)3.3 各个模块的算法设计说明 (5)4 详细设计 (8)4.1 数据类型 (8)4.2 函数调用 (9)5 各个算法实现的源程序 (9)6 调试分析 (12)7 使用说明 (12)8 测试结果 (13)9 源程序 (13)1 问题描述1.1 题目内容哈夫曼编码问题的设计和实现输入一个英文字符串,对该字符串中各字符个数进行统计取得各字符的出现次数;以其出现次数作为关键字建立哈夫曼树并进行编码,最后输出各个字符对应的码值。

1.2 基本要求要求:设计存储结构、基本算法(主要采用程序流程图体现);完成基本算法的实现代码;设计测试输入数据对程序进行测试,分析输出结果数据、算法的时间复杂度分析,如有改进算法则提出算法的改进方法。

1.3 测试数据测试数据三组:AAAABBBCCD(判断连续的字符串是否可行)AABBAABCDC(判断间段的字符串是否可行)AAAA BBBCCD(判断含空格的字符串是否可行)2 需求分析2.1 程序的基本功能该程序大体上有两个功能:1.输入任何一个字符串后,该程序能统计不同字符串的个数,并以不同字符串的个数作为权值。

2.已知不同字母的权值,以该权值作为叶结点,构造一棵带权路径最小的树,对该树从叶结点到根结点路径分支遍历,经过一个分支就得到一位夫曼编码值。

数据结构 哈夫曼编码器课程设计报告

数据结构 哈夫曼编码器课程设计报告

数据结构哈夫曼编码器课程设计报告哈夫曼编码器课程设计报告设计目标:本课程设计的目标是实现一个哈夫曼编码器,能够实现对给定文本文件进行压缩和解压缩操作。

通过使用哈夫曼编码,可以使文本文件的大小大幅度减小,从而节约存储空间。

设计原理及实现方法:本设计主要包括以下几个步骤:1、文本文件的读取:首先需要从外部文件中读取待压缩的文本文件,读取过程可以通过使用文件输入流进行操作。

读取的文本内容将用于构建哈夫曼树和编码表。

2、构建哈夫曼树:哈夫曼树是通过给定文本中的字符出现频率来构建的,出现频率更高的字符将拥有更短的编码。

构建哈夫曼树的过程可以通过使用优先队列和二叉树来实现。

3、编码表:在构建哈夫曼树的过程中,每个字符都会有一个唯一的编码。

根据哈夫曼树的特性,左子树的编码为0,右子树的编码为1,根据这个规则可以通过遍历哈夫曼树来编码表。

4、压缩文本文件:在编码表后,可以利用编码表来对文本文件进行压缩操作。

遍历文本文件中的每个字符,通过编码表将字符转换为对应的哈夫曼编码,并将编码存储在一个压缩文件中。

5、解压缩文本文件:解压缩操作是压缩操作的逆过程。

根据编码表将压缩文件中的哈夫曼编码逐个解码为字符,并将解码后的字符写入解压缩文件中。

附件说明:本文档的附件包括以下内容:1、源代码文件:- HuffmanEncoder:java:包含了哈夫曼编码器的主要实现代码。

- Mn:java:包含了测试哈夫曼编码器的主函数。

2、示例文本文件:- input:txt:用于测试的示例文本文件。

法律名词及注释:本文档中涉及的法律名词及注释如下:1、哈夫曼编码:用于数据压缩的一种编码方式,旨在通过减少字符的编码长度来节省存储空间。

2、压缩:将原始文件经过编码转换为较短的文件,从而减小存储空间的占用。

3、解压缩:将压缩文件经过解码转换为原始文件,恢复原始文件的过程。

全文结束。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊目录目录 (1)1 课程设计的目的和意义 (2)2 需求分析 (3)3 系统设计 (4)(1)设计思路及方案 (4)(2)模块的设计及介绍 (4)(3)主要模块程序流程图 (6)4 系统实现 (10)(1)主调函数 (10)(2)建立HuffmanTree (10)(3)生成Huffman编码并写入文件 (13)(4)电文译码 (14)5 系统调试 (16)小结 (18)参考文献 (19)附录源程序 (20)┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊1 课程设计的目的和意义在当今信息爆炸时代,如何采用有效的数据压缩技术来节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视。

哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。

哈夫曼编码的应用很广泛,利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。

树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为和各个对应的字符的编码,这就是哈夫曼编码。

通常我们把数据压缩的过程称为编码,解压缩的过程称为解码。

电报通信是传递文字的二进制码形式的字符串。

但在信息传递时,总希望总长度尽可能最短,即采用最短码。

作为软件工程专业的学生,我们应该很好的掌握这门技术。

在课堂上,我们能过学到许多的理论知识,但我们很少有过自己动手实践的机会!课程设计就是为解决这个问题提供了一个平台。

在课程设计过程中,我们每个人选择一个课题,认真研究,根据课堂讲授内容,借助书本,自己动手实践。

这样不但有助于我们消化课堂所讲解的内容,还可以增强我们的独立思考能力和动手能力;通过编写实验代码和调试运行,我们可以逐步积累调试C程序的经验并逐渐培养我们的编程能力、用计算机解决实际问题的能力。

在课程设计过程中,我们不但有自己的独立思考,还借助各种参考文献来帮助我们完成系统。

更为重要的是,我们同学之间加强了交流,在对问题的认识方面可以交换不同的意见。

同时,师生之间的互动也随之改善,我们可以通过具体的实例来从老师那学到更多的实用的知识。

数据结构课程具有比较强的理论性,同时也具有较强的可应用性和实践性。

课程设计是一个重要的教学环节。

我们在一般情况下都能够重视实验环节,但是容易忽略实验的总结,忽略实验报告的撰写。

通过这次实验让我们明白:作为一名大学生必须严格训练分析总结能力、书面表达能力。

需要逐步培养书写科学实验报告以及科技论文的能力。

只有这样,我们的综合素质才会有好的提高。

┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊2 需求分析题目:哈夫曼编码/译码器问题描述:利用哈夫曼编码进行信息通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。

但是这要求在发送端通过一个编码系统对待传数据预先编码;在接收端将传来的数据进行译码(复原)。

对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。

试为这样的信息收发站写一个哈夫曼码的编译码系统。

具体要求:1)初始化:键盘输入字符集大小n及n个字符和m个权值,建立哈夫曼树,并将它存于文件hfmtree中。

2)编码:利用建好的哈夫曼树,对文件tobetrans中的正文进行编码,然后将结果存入文件codefile中。

3)解码:利用建好的哈夫曼树将文件codefile中的代码进行译码,结果存入文件textfile中。

4)打印代码文件:将文件codefile以紧凑格式显示在终端上,每行50个代码。

同时将此字符形式的编码文件写入文件codeprint中。

5)打印哈夫曼树:将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件treeprint中。

┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊3 系统设计(1)设计思路及方案本课题是用最优二叉树即哈夫曼树来实现哈夫曼编码译码器的功能。

假设每种字符在电文中出现的次数为Wi,编码长度为Li,电文中有n种字符,则电文编码总长度为(W1*L1)+(W2*L2)+…+(Wi*Li)。

若将此对应到二叉树上,Wi为叶结点,Li为根结点到叶结点的路径长度。

那么,(W1*L1)+(W2*L2)+…+(Wi*Li)恰好为二叉树上带权路径长度。

因此,设计电文总长最短的二进制前缀编码,就是以n种字符出现的频率作权,构造一棵哈夫曼树,此构造过程称为哈夫曼编码。

该系统将实现以下几大功能:从硬盘读取字符串,建立哈夫曼树,输出哈夫曼树的存储结构的初态和终态,输出各种字符出现的次数以及哈夫曼编码的译码等。

(2)模块的设计及介绍①从硬盘读取字符串fileopen(参数){实现命令;打印输出;}②建立HuffmanTree通过三个函数来实现:void select(参数){初始化;for{接受命令;处理命令;}}┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊说明:在ht[1....k]中选择parent为0且权值最小的两个根结点的算法int jsq(参数){初始化;for{接受命令;处理命令;}}说明:统计字符串中各种字母的个数以及字符的种类void ChuffmanTree(){初始化;for{接受命令;处理命令;}输出字符统计情况;}说明:构造哈夫曼树③输出哈夫曼树的存储结构的初态和终态分别调用print1()和print2()来实现void print1(参数){初始化;输出初态;}说明:输出哈夫曼树的初态┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊void print2(参数){for{输出终态;}}说明:输出哈夫曼树的终态④哈夫曼编码和译码void HuffmanEncoding(参数){定义变量;{处理命令;}}说明:哈夫曼编码char*decode(参数){定义变量;while{接受命令;处理命令;}}说明:哈夫曼译码(3)主要模块程序流程图下面介绍三个主要的程序模块流程图:┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊①主函数流程图:图3.1流程图注释:该图比较简单,主要是调用各个函数模块,首先代开已经存在的文件,然后统计总的字符数以及出现的各个字符和频率。

然后才开始建立哈夫曼树,接着在哈夫曼树的基础上对其进行编码,编码之后才是译码。

最后输出结束。

┊┊┊Array┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊图3.2┊流程图注释:该图是表示构造哈夫曼树的过程。

首先输入num个叶结点的权值,当i=num是循环结束。

然后进行哈夫曼树的构建,当i=2*num-1是循环结束。

最后输出所得到的字符统计情况。

┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊图3.3流程图解释:该流程图表四哈夫曼编码情况。

首先初始化,Cd[--start]=0,start=num。

然后进行编码,使用了一个三目运算符。

cd[--start]=(T[p].lchild==c) ? '0' : '1',即当cd[--start]=T[p].lchild= =c时,cd[--start]=0;当cd[--start]=T[p].lchild!= =c时,cd[--start]=1。

这个编码循环一直到i=num时结束。

┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊4 系统实现各模块关键代码及算法的解释:(1)主调函数代码解释:这是main函数里的各个函数调用情况。

fileopen(string); //从硬盘中读取文件num=jsq(string,cnt,str); //统计字符种类及各类字符出现的频率DhuffmanTree(HT,cnt,str);printf("HuffmanTree的初态:\n");print1(HT); //输出哈夫曼树的初态ChuffmanTree(HT,HC,cnt,str);//建立哈夫曼树HuffmanEncoding(HT,HC); //生成哈夫曼编码printf("HuffmanTree的终态:\n");print2(HT); //输出哈夫曼树的终态s=decode(HC); //读编码文件译码printf("译码后的字符串:\n");printf("%s\n",s); //输出译码后的字符串(2)建立HuffmanTree代码解释:该函数为在ht[1....k]中选择parent为0且权值最小的两个根结点的算法,其序号为s1和s2。

void select(HuffmanTree T,int k,int &s1,int &s2){int i,j;int min1=101;for(i=1;i<=k;i++)if(T[i].weight<min1 &&T[i].parent==0){j=i;min1=T[i].weight;}s1=j;min1=32767;for (i=1;i<=k;i++)┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊if(T[i].weight<min1 && T[i].parent==0 && i!=s1){j=i;min1=T[i].weight;}s2=j;}代码解释:下面函数用来统计字符串中各种字母的个数以及字符的种类。

当字符在A和Z之间时即被计数,并用str[j]保存字母到数组中,用cnt[j]统计每种字符个数。

j返回总共读取的字符数目。

int jsq(char *s,int cnt[],char str[]){int i,j,k;char *p;int temp[27];for(i=1;i<=26;i++)temp[i]=0;for(p=s; *p!='\0';p++){{if(*p>='A'&&*p<='Z')k=*p-64;temp[k]++;}} //统计各种字符的个数for(i=1,j=0;i<=26;++i)if(temp[i]!=0 ){j++;str[j]=i+64; //送对应的字母到数组中cnt[j]=temp[i]; //存入对应字母的权值┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊}return j; //j是输入字母总数}代码解释:下面函数用来构造哈夫曼树HT。

相关文档
最新文档