数据结构课程设计-哈夫曼树
数据结构哈夫曼树和哈夫曼编码权值

主题:数据结构——哈夫曼树和哈夫曼编码权值1. 引言在计算机科学中,对于大规模的数据存储和传输,有效地压缩数据是一项重要的任务。
哈夫曼树和哈夫曼编码权值是一种经典的数据结构和算法,用于实现数据的高效压缩和解压缩。
本文将介绍哈夫曼树和哈夫曼编码权值的概念和原理,探讨其在数据压缩中的应用以及个人对该主题的理解。
2. 哈夫曼树2.1 概念哈夫曼树,又称最优二叉树,是一种具有最小带权路径长度的二叉树。
树的带权路径长度定义为树中所有叶子节点的权值乘以其到根节点的距离,即路径长度的总和。
2.2 构造方法哈夫曼树的构造方法是一种贪心算法。
将所有的权值作为叶子节点构建n棵单节点树。
从这些树中选择两棵权值最小的树合并,得到一棵新的树,新树的根节点的权值为这两棵树根节点权值之和。
重复此过程,直到只剩下一棵树,即为哈夫曼树。
2.3 例子以数据集[7, 5, 2, 4]为例,构造哈夫曼树的过程如下: 1. 初始状态下,将每个权值看作一棵树:7、5、2、4。
2. 选择两棵权值最小的树2和4进行合并,得到一棵新树,根节点的权值为2+4=6。
此时,剩下的树为6、5、7。
3. 选择两棵权值最小的树5和6进行合并,得到一棵新树,根节点的权值为5+6=11。
此时,剩下的树为11、7。
4. 选择两棵权值最小的树7和11进行合并,得到一棵新树,根节点的权值为7+11=18。
得到最终的哈夫曼树。
3. 哈夫曼编码权值3.1 概念哈夫曼编码权值是指在哈夫曼树中,从根节点到每个叶子节点的路径上所经过的边的权值。
对于哈夫曼树中的每个字符(叶子节点),都可以通过从根节点到叶子节点的路径上的边的权值,来进行编码。
3.2 编码方法哈夫曼编码方法的基本原则是将出现频率高的字符用较短的编码表示,出现频率低的字符用较长的编码表示。
在哈夫曼树中,根节点到左子树的路径上的边标记为0,到右子树的路径上的边标记为1。
通过遍历哈夫曼树,可以分配每个字符的编码。
数据结构课程设计_哈夫曼树

数据结构课程设计_哈夫曼树哈夫曼树是数据结构课程设计中的一个重要内容,它是一种用于编码和压缩数据的树形结构。
在这篇文章中,我们将深入探讨哈夫曼树的原理、应用以及实现方法。
一、哈夫曼树的原理哈夫曼树是一种特殊的二叉树,它的构建依赖于哈夫曼编码的思想。
哈夫曼编码是一种变长编码方式,通过将频率较高的字符用较短的编码表示,而频率较低的字符用较长的编码表示,从而实现数据的高效压缩。
构建哈夫曼树的过程如下: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:刚开始不知道如何建一个好树,因为我开始试着建了几个二叉树,不知道什么原因运行的时候那编码总是不对,跟在草稿纸上自己画的那个二叉树总是不相符,就找原因。
数据结构课程设计_哈夫曼压缩文件

《数据结构》基于哈夫曼算法的文件压缩程一.总体设计1.目标设计:*实现目标:利用哈夫曼算法编写一个可以对文件进行压缩和解压缩的程序,即可以将指定的文件用哈夫曼算法压缩为一个新的文件,也可以将一个压缩后的文件还原,并可以将压缩或还原后的文件保存到指定位置。
*功能描述:任何文件都可以看作是由字节组成的字节块,将字节看作基本编码单元,一个文件就可以看作是由字节组成的信息串。
对文件中各字节的出现频率进行统计,并以出现频率作为字节的权值,就可以用字节为叶结点构造哈夫曼树,进而构造出各字节的对应哈夫曼编码。
字节编码是一种8位定长编码,将各字节用哈夫曼编码进行重新编码,就有可能使得总的编码长度更短,从而达到压缩的效果。
哈夫曼编码是无损压缩当中最好的方法。
它使用预先二进制描述来替换每个符号,长度由特殊符号出现的频率决定。
常见的符号需要很少的位来表示,而不常见的符号需要很多位来表示。
哈夫曼算法对文件的压缩和解压缩的程序就是将存储源文件的二进制编码通过利用哈夫曼算法译为长度不等的哈夫曼编码,即得到哈夫曼树。
这棵树有两个目的:1.编码器使用这棵树来找到每个符号最优的表示方法,进而存储树实现文件的压缩。
2.解码器使用这棵树唯一的标识在压缩流中每个编码的开始和结束,其通过在读压缩数据位的时候自顶向底的遍历树,选择基于数据流中的每个独立位的分支,一旦一个到达叶子节点,解码器知道一个完整的编码已经读出来了,即通过对哈夫曼树的遍历实现解压过程。
2.框架设计:定义结构体类型变量struct head {}定义函数void compress() /*压缩文件*/{在函数compress内定义变量;读取被压缩文件;建立并打开目标文件;逐字节读入,并进行累加计数,得到各个字节在文件中的出现频率;利用哈夫曼算法构造出字节对应的哈夫曼树;将压缩后的数据写入目标文件,并保存;}定义函数uncompress() /*解压文件*/{在函数uncompress内定义变量;读取需解压文件;建立并打开目标文件;对哈夫曼树进行遍历实现解压;将解压后的数据写入目标文件,并保存;}定义主函数int main(){输入A,压缩文件,调用函数compress;输入B,解压文件,调用函数uncompress;}二.详细设计1、文件的字节频率统计字节共有256个,从0~255,可定义长度为256的频率数组来记录每个字节的出现频率。
(完整word版)数据结构课程设计(哈夫曼编码)

目录目录 (1)1 课程设计的目的和意义 (3)2 需求分析 (5)3 系统设计 (6)(1)设计思路及方案 (6)(2)模块的设计及介绍 (6)(3)主要模块程序流程图 (9)4 系统实现 (14)(1)主调函数 (14)(2)建立HuffmanTree (14)(3)生成Huffman编码并写入文件 (18)(4)电文译码 (19)5 系统调试 (22)小结 (25)参考文献 (26)附录源程序 (27)1 课程设计的目的和意义在当今信息爆炸时代,如何采用有效的数据压缩技术来节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视。
哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。
哈夫曼编码的应用很广泛,利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。
树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0"码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1"的序列作为和各个对应的字符的编码,这就是哈夫曼编码。
通常我们把数据压缩的过程称为编码,解压缩的过程称为解码。
电报通信是传递文字的二进制码形式的字符串。
但在信息传递时,总希望总长度尽可能最短,即采用最短码。
作为软件工程专业的学生,我们应该很好的掌握这门技术。
在课堂上,我们能过学到许多的理论知识,但我们很少有过自己动手实践的机会!课程设计就是为解决这个问题提供了一个平台。
在课程设计过程中,我们每个人选择一个课题,认真研究,根据课堂讲授内容,借助书本,自己动手实践。
这样不但有助于我们消化课堂所讲解的内容,还可以增强我们的独立思考能力和动手能力;通过编写实验代码和调试运行,我们可以逐步积累调试C程序的经验并逐渐培养我们的编程能力、用计算机解决实际问题的能力。
在课程设计过程中,我们不但有自己的独立思考,还借助各种参考文献来帮助我们完成系统。
更为重要的是,我们同学之间加强了交流,在对问题的认识方面可以交换不同的意见.同时,师生之间的互动也随之改善,我们可以通过具体的实例来从老师那学到更多的实用的知识。
数据结构课程设计(哈夫曼编码)要点

┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊目录目录 (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程序的经验并逐渐培养我们的编程能力、用计算机解决实际问题的能力。
数据结构哈夫曼树课件

总结词
优化、提升
详细描述
基于哈夫曼树的网络流量分类算法的优化策 略主要从以下几个方面进行优化和提升:一 是优化哈夫曼树的构造算法,提高树的构造 效率和准确性;二是利用多级哈夫曼编码技 术,降低编码和解码的时间复杂度;三是引 入机器学习算法,对网络流量特征进行自动
提取和分类,进一步提升分类准确率。
THANKS
基于堆排序的构造算法
总结词:堆排序是一 种基于比较的排序算 法,它利用了堆这种 数据结构的特点,能 够在O(nlogn)的时间 内完成排序。在哈夫 曼树的构造中,堆排 序可以用来找到每个 节点的父节点,从而 构建出哈夫曼树。
详细描述:基于堆排 序的构造算法步骤如 下
1. 定义一个最大堆, 并将每个节点作为一 个独立的元素插入到 堆中。每个元素包含 了一个节点及其权值 。
哈夫曼编码的基本概念
哈夫曼编码是一种用于无损数据压缩的熵编码算法,具有较高的编码效率和较低的 编码复杂度。
它利用了数据本身存在的冗余和相关性,通过构建最优的前缀编码来实现高效的数 据压缩。
哈夫曼编码是一种可变长编码,其中每个符号的编码长度取决于它在输入序列中出 现的频率。
哈夫曼编码的实现方法
构建哈夫曼树
节ቤተ መጻሕፍቲ ባይዱ。
优化编码长度
在分配码字时,通过一些策略优化 编码长度,例如给高频符号更短的 码字。
可变长度编码
为了提高压缩比,可以使用可变长 度编码,即对于高频符号赋予更短 的码字,对于低频符号赋予更长的 码字。
04
哈夫曼树在数据压 缩中的应用
基于哈夫曼编码的数据压缩算法
哈夫曼编码是一种可变长度的 编码方式,通过统计数据的出 现频率来构建哈夫曼树,实现 数据压缩。
数据结构课程设计-哈夫曼树

嘉应学院计算机学院实验报告课程名称:数据结构课程设计开课学期:2017-2018学年第2学期班级:指导老师:实验题目:哈夫曼树学号:姓名:上机时间:一、实验目的本实验的目的是通过对简单的哈夫曼编/译码系统的设计与实现来熟练掌握树形结构在实际问题中的应用。
二、实验问题描述利用哈夫曼编码进行通信可以大大提高通信利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码,此试验即设计这样的一个简单的编/译码系统。
系统应该具备如下的几个功能。
1、求出各个叶子节点的权重值输入一个字符串,统计其中各个字母的个数和总的字母个数。
2、构造哈夫曼树统计出的字母种类为叶子结点个数,每个字母个数为相应的权值,建立哈夫曼树。
3、打印哈弗曼树的功能模块按照一定形式打印出哈夫曼树。
4、编码利用已经建立好的哈夫曼树进行编码。
5、译码根据编码规则对输入的代码进行翻译并将译码。
三、实验步骤1、实验问题分析(1)设计一个结构体数组保存字母的类型和个数。
{; 字母的种类; 字母的个数};(2)在构造哈夫曼树时,设计一个结构体数组保存哈夫曼树中各结点的信息,根据二叉树的性质可知,具有n个结点的哈夫曼树共有21个结点,所以数组大小设置为21,描述结点的数据类型为:{; 权值; 双亲; 左孩子; 右孩子};[]; 定义此类型的数组(3)求哈夫曼编码,实质上是在已经建立的哈夫曼树中,从叶子结点开始,沿着结点的双亲链表域退回到根节点,每退回一步,就走过了哈夫曼树的一个分支,从而得到一位哈夫曼值,由于一个字符的哈夫曼编码是从根结点所经过的路径上各分支所组成的0、1序列,因此先得到的分支代码为所求编码的低位码,后得到的分支代码为所求编码的高位码,所以设计如下的数据类型:10;{[]; 每个结点的哈夫曼编码; 开始位置};(4)设置全局变量。
s; 为输入的字符串0; 记录输入的字符串中字母的种类,即叶子结点个数0; 记录字符串中字母的总个数[]叶子结点类型2、功能(函数)设计(1)统计字母种类和个数模块此模块的功能为从键盘接受一个字符串,统计字符串中字母种类即结点个数,每种字母出现次数即各叶子结点的权值。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
嘉应学院计算机学院实验报告课程名称:数据结构课程设计开课学期:2017-2018学年第2学期班级:指导老师:实验题目:哈夫曼树学号:姓名:上机时间:一、实验目的本实验的目的是通过对简单的哈夫曼编/译码系统的设计与实现来熟练掌握树形结构在实际问题中的应用。
二、实验问题描述利用哈夫曼编码进行通信可以大大提高通信利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码,此试验即设计这样的一个简单的编/译码系统。
系统应该具备如下的几个功能。
1、求出各个叶子节点的权重值输入一个字符串,统计其中各个字母的个数和总的字母个数。
2、构造哈夫曼树统计出的字母种类为叶子结点个数,每个字母个数为相应的权值,建立哈夫曼树。
3、打印哈弗曼树的功能模块按照一定形式打印出哈夫曼树。
4、编码利用已经建立好的哈夫曼树进行编码。
5、译码根据编码规则对输入的代码进行翻译并将译码。
三、实验步骤1、实验问题分析(1)设计一个结构体数组保存字母的类型和个数。
{; 字母的种类; 字母的个数};(2)在构造哈夫曼树时,设计一个结构体数组保存哈夫曼树中各结点的信息,根据二叉树的性质可知,具有n个结点的哈夫曼树共有21个结点,所以数组大小设置为21,描述结点的数据类型为:{; 权值; 双亲; 左孩子; 右孩子};[]; 定义此类型的数组(3)求哈夫曼编码,实质上是在已经建立的哈夫曼树中,从叶子结点开始,沿着结点的双亲链表域退回到根节点,每退回一步,就走过了哈夫曼树的一个分支,从而得到一位哈夫曼值,由于一个字符的哈夫曼编码是从根结点所经过的路径上各分支所组成的0、1序列,因此先得到的分支代码为所求编码的低位码,后得到的分支代码为所求编码的高位码,所以设计如下的数据类型:10;{[]; 每个结点的哈夫曼编码; 开始位置};(4)设置全局变量。
s; 为输入的字符串0; 记录输入的字符串中字母的种类,即叶子结点个数0; 记录字符串中字母的总个数[]叶子结点类型2、功能(函数)设计(1)统计字母种类和个数模块此模块的功能为从键盘接受一个字符串,统计字符串中字母种类即结点个数,每种字母出现次数即各叶子结点的权值。
全局变量s保存输入的字符串,将种类和个数保存到[]中。
函数原型:()如输入的字符串是“”则显示如下。
(2)哈夫曼树的建立模块此模块的功能为从(1)中计算出的结点个数和各个叶子结点的权值构造一棵哈弗曼树。
函数原型:* ()函数返回结点类型的数组(3)打印哈弗曼树的功能模块此模块的功能是将由(2)建立的哈弗曼树按照一定规则<>打印在屏幕上。
函数原型: ( *)如输入的字符串是””,则构造的哈夫曼树为(4)建立哈夫曼编码的功能模块此模块功能为将(2)中建立的哈夫曼树进行哈弗曼编码,然后将字符与对应的0、1代码串打印到屏幕上。
函数原型: ( *)如输入的字符串是“”,则每个字母的代码和输入的字符串的哈夫曼编码是(5)译码的功能模块此模块的功能为接收需要译码的0和1代码串,按照(4)中建立的编码规则将其翻译成字符集中字符所组成的字符串形式,并将翻译的结果在屏幕上打印出来。
函数原型: ( *)如输入的代码串是“110111100”,则对应的字符串是“”四、实验结果(程序)及分析1、实验主要模块代码(一)函数功能:统计字母种类和个数模块(){;<<"请输入字符串"<<;>>s; 为输入的字符串(s[v]){;}<<"共有字符"<<v<<"个"<<; v是全局变量[0][0][0]1;(1<) 统计s中字母种类和个数{(0<){([m][k]){[m];}}(m>n){[][k][n]1;}}(0<) 输出种类和个数<<"字符"<<[m]<<"有"<<[m]<<"个"<<;}(二)函数功能:哈弗曼树的建立模块* (){* ;1212; 1记录最小的重权值,m2为次小(0<2*1){ 结点初始化[i]1;[i]0;[i]1;[i]1;}(0<) 将每个字母的个数当做叶子结点的权值[i][i];(0<1){m12;x12=0;(0<){([j]1 [j]<m1){m21;x21;m1[j];x1; 1记录最小重权值在数组中的下标 }([j]1 [j]<m2){m2[j];x2; 2记录次小重权值在数组中的下标}}[x1];[x2];[]12;[]1;[]2;}; 返回数组首地址}(三)函数功能:打印哈弗曼树的功能模块( *){<<<<<<; 界面优化<<"哈弗曼树"<<;<<" "<<""<<" "<<"" <<" "<<""<<""<<""<<; 界面优化( 0<2*1)<<" "<<[i]<<" "<<[i]<<" "<<[i]<<" "<<[i]<<;}(四)函数功能:建立哈弗曼编码的功能模块( *){[];;(0<){ 求每个结点的哈弗曼编码1;;[c];(1){ 由叶子结点向上直到树根([p])[]=0;[]=1;;;[c];}(1<) 将结果保存[i][j][j]保存每位号码[i]; 保存开始位置}<<<<<<;<<"哈弗曼编码"<<;(0<) 打印各个字母对应的编码{<<""<<;<<[i]<<"的代码是";([i]1<)<<[i][j];<<;}<<""<<;<<<<"输入的字符串的哈夫曼编码为:"<<;(0<)打印输入的字符串的编码结果( 0<)(s[i][y]){( [y]1<)<<[y][j];}<<;}(五)函数功能:译码的功能模块( *){; 记录输入的0,1代码t;<<<<<<;<<"请输入代码串:";>>;0;([]); 确定0,1代码长度 *[2*2];<<<<<<;<<"译码结果"<<;( 0<){([i]'0') 从根向下[>];[>];(>1 >1){ 如果到达叶子结点>; 保存叶子结点的权值( 0<)([j]){<<[j]; 输出权值的对应的字母;}[2*2]; 重新从根节点开始}}<<;}2、测试数据实验结果截图3、调试过程中出现的问题以及解决策略译码模块中,如果输入的代码串无对应的字母,则会出错。
解决办法:提示用户输入时注意附最终代码:<><>121223;0;0;s;{;;};[12];{;权值;;;};[];10;{[];;};(){;<<"请输入字符串"<<;>>s;<<"共有字符"<<v<<"个"<<;[0][0][0]1;(1<){(0<){([m][k]){[m];}}(m>n){[][k][n]1;}}(0<)<<"字符"<<[m]<<"有"<<[m]<<"个"<<;}* (){* ;1212;1记录最小的重权值,m2为次小(0<2*1){ 结点初始化[i]1;[i]0;[i]1;[i]1;}(0<) 将每个字母的个数当做叶子结点的权值[i][i];(0<1){m12;x12=0;(0<){([j]1 [j]<m1){m21;x21;m1[j];x1;1记录最小重权值在数组中的下标}([j]1 [j]<m2){m2[j];x2;2记录次小重权值在数组中的下标}}[x1];[x2];[]1;[]2;};返回数组首地址}( *){[];;(0<){求每个结点的哈弗曼编码1;;[c];(1){由叶子结点向上直到树根([p])[]=0;[]=1;;;[c];}(1<) 将结果保存[i][j][j]保存每位号码[i]; 保存开始位置}<<<<<<;<<"哈弗曼编码"<<;(0<) 打印各个字母对应的编码{<<""<<;<<[i]<<"的代码是";([i]1<)<<[i][j];<<;}<<""<<;<<<<"输入的字符串的哈夫曼编码为:"<<;(0<)打印输入的字符串的编码结果( 0<)(s[i][y]){( [y]1<)<<[y][j];}<<;}( *){<<<<<<;<<"哈弗曼树"<<;<<" "<<""<<" "<<""<<" "<<""<<" "<<""<<;界面优化( 0<2*1)<<" "<<[i]<<" "<<[i]<<" "<<[i]<<" "<<[i]<<;}( *){; 记录输入的0,1代码t;<<<<<<;<<"请输入代码串:";>>;0;([])确定0,1代码长度*[2*2];<<<<<<;<<"译码结果"<<;( 0<){([i]'0')[>];[>];(>1 >1){如果到达叶子结点>; 保存叶子结点的权值( 0<)([j]){<<[j]输出权值的对应的字母;}[2*2]重新从根节点开始}}<<;}(){();*h;();(h);(h);(h);("");0;}。