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

加入VIP,免费下载
 

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

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

下载须知

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

版权提示 | 免责声明

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

哈夫曼编译码实验指导书.docx

1、哈夫曼编译码实验指导书实验七 哈夫曼编/译码器一、实验目的通过哈夫曼树的构造,深刻理解二叉树的构造。通过哈夫曼编/译码过程,深刻领会二叉树的基本操作和二叉树的应用,帮助学生熟练掌握二叉数组织数据的基本原理和对二叉数操作的实现方法。二、实验内容本实验的主要内容是:1、由文本字符及字符在文本文件中出现的频率,构造带权路径最短的最优二叉树(哈夫曼树),并依此为基础构造字符的前缀编码(哈夫曼编码);2、编码:从文本文件中读入文本字符,按照已知的字符哈夫曼编码将文本字符转换为二进制串的哈夫曼编码形式。3、译码:从文件中读入二进制串字符,按照哈夫曼树将其转换为文本字符。4、输出哈夫曼树:以凹入表(层次表)

2、的形式显示哈夫曼树。三、实验仪器微型计算机实验用编程语言:Turbo C 2.0,Borland C 3.0等以上版本四、实验原理1、哈夫曼树的定义哈夫曼树(最优二叉树):设有个权值w1,w2,.,wn,试构造一棵有个叶结点的二叉树,第个叶结点的权值为wi,则其中带权路径长度为最小的二叉树被称为最优二叉树或哈夫曼树。2、哈夫曼算法: 哈夫曼算法要点是: (1)根据给定的个权值w1,w2,.,wn构成棵二叉树的集合T1,T2,.,Tn,其中每棵二叉树Ti只有一个带权为Wi的根结点,左右子树为空。 (2)在中选取两棵根结点的权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树根结点的权值为左

3、右子树根结点权值之和。 (3)在中删除这两棵树,同时将新得到的树加入到中。 (4)重复(2)和(3),直到只剩下一棵二叉树为止。这棵二叉树便是哈夫曼树。3、哈夫曼编码对于字符的二进制编码,若任一字符的二进制编码都不是另一个字符的二进制编码的前缀。这种编码叫做前缀编码。以n种字符出现的频率作权,设计一棵哈夫曼树,并用二叉树的叶结点分别表示待编码的字符,并约定左分支表示字符0,右分支表示字符1。则对每个叶结点,都有唯一的一条从根结点出发的路径,则该路径上分支字符组成的字符串作为该叶子结点的编码。由此得到的编码必为二进制的前缀编码,而且是编码总长最短的二进制前缀编码,这种编码即为哈夫曼编码。例:设有

4、8个字符A,B,C,D,E,F,G,H,其概率为0.05,0.29,0.07,0.08,0.14,0.23,0.03,0.11,设其权值用整数表示为 5,29,7,8,14,23,3,11 100 42 5823 19 29 29 11 8 14 15 5 3 7 8则字符的哈夫曼编码为:A 0110 B 10C 1110 D 1111E 110 F 00G 0111 H 010五、实现 1、哈夫曼树的存储结构根据哈夫曼树的构造算法,哈夫曼数除叶结点外,其余结点的度均为2。对于具有n个权值构造的哈夫曼树,根据二叉树的性质3,哈夫曼树的结点总数为m=2n-1,即哈夫曼树所需存储空间是由文本中不同

5、字符的个数唯一确定的。为了便于对多棵二叉树进行组织和便于查找各二叉树的根结点,采用静态链表作为二叉树的存储结构。其存储结构描述如下:typedef struc char ch; unsigned int weight; unsigned int parent,lchild,rchild; HTNode,*HuffmanTree;A58-1-1B2913-1-1C79-1-1D89-1-1E1411-1-1F2312-1-1G38-1-1H1110-1-1*81060*151123*191287*291349*4214105*581111*100-112132、哈夫曼编码的存储结构 若要编码的文

6、本文件的字符集不变,则其哈夫曼编码不变。字符的哈夫曼编码一旦确定,可以长期使用。因此,需要用文件同时保存字符的哈夫曼编码和字符。哈夫曼编码的表示形式既要考虑存储空间的效率,也要考虑文件读取的方便。文本字符的哈夫曼编码是不等长的二进制码,用不等长的二进制字符串表示,节省存储空间,但用文件读取不方便。若用等长的结构体表示,可能要浪费一点存储空间,但文件存取方便。为了便于文件存取,采用等长结构体表示哈夫曼具有可取之处,其存储结构描述如下:#define NODENUM 26 /字符集struct HuffmanCoding char ch; /字符 char codingNODENUM; /字符编码

7、 ;3、字符及权值的输入形式 为了避免字符及其权值的手工键盘输入带来的错误,可以将字符及其权值组织成文本文件的形式。文本文件的格式为: 字符 权值例如: A 5 B 19 C 7 D 8 E 14 F 23 G 3 H 11一般读入单个字符很不方便,格式化输入字符串和数值型数据很方便,所以字符数据可以采用读串的方式读入,然后把它赋给字符变量。4、文件的设置 (1)字符权值文件 const char *WeighFileName = Weight.txt; 存放需构造哈夫曼树的字符和权值数据,为文本数据,见“字符及权值的输入形式”。 (2)哈夫曼树数据文件const char *TableFil

8、eName = HfmTbl.txt;存放哈夫曼树数据,二进制HTNode结构型。格式为:数据个数哈夫曼树的结点数,M=2n-1,n为权值个数记录i-二进制HTNode结构型数据 (3)字符编码数据文件const char *CodeFileName = CodeFile.txt;存放字符编码数据,二进制struct HuffmanCoding结构型。格式为:数据个数权值个数记录i-二进制struct HuffmanCoding结构型数据(4)文本文件const char *SourceFileName = SrcText.txt; 存放需编码的文本字符串数据,其中的字符属于编码字符集。(5)

9、编码数据文件 const char *EnCodeFileName = EnCodeFile.txt;存放对文本文件编码后的数据,其中的数据为“0”和“1”的字符串。 (6)译码字符文件 const char *DecodeFileName = DecodeFile.txt;存放译码后的字符文件 5、程序基本功能 (1)初始化:输入编码字符和其权值,生成哈夫曼树和字符的哈夫曼编码,并用文件保存哈夫曼树和字符的哈夫曼编码。 (2)编码:把文本字符串转换为“0”和“1”表示的哈夫曼编码。 (3)译码:把“0”和“1”表示的哈夫曼编码串转换为文本字符串 (4)显示哈夫曼树:以凹入形式显示哈夫曼树。

10、(5)显示哈夫曼表:以表格形式显示哈夫曼树 (6)显示字符编码 6、辅助功能(1)菜单选择:将上述功能通过“菜单”形式罗列出来,通过菜单选择进行交互式控制程序运行。(2)读文件:把哈夫曼树数据读入内存。(3)选择结点:选择两个具有最小权值的根结点。7、程序结构 本程序可以由10个函数组成,其中主函数1个,基本功能函数6个,辅助功能函数3个。函数间的调用关系图2所示。8、程序函数(1)主函数:main 功能:通过菜单选择控制对系统功能的操作(2)菜单选择函数:menu函数格式: int menu(void)函数功能:构造功能菜单,并选择下一步要操作的功能。函数参数:无参数。函数返回值:17中的一

11、个序号。 可供选择的功能如下:1- Initialization 2-Encode 3-Decode 4-Print huffmantree 5-Print huffman Table 6-Print char Coding 7-Quit(3)初始化函数:Initialization函数格式:void Initialization()函数参数:无参数函数功能:输入编码字符和权值,生成哈夫曼树和字符编码,并用文件TableFileName和CodeFileName保存哈夫曼树和字符编码数据。函数返回值:无(4)文本串编码函数:Encode函数格式void Encode(void)函数功能:从文本

12、串文件SourceFileName中读入文本字符,按照CodeFileName文件中字符的编码将其转换为“0”和“1”表示的哈夫曼编码,并把编码结果写入文件EnCodeFileName中。函数参数:无 函数返回值:无 (5)译码函数:Decode函数格式 void Decode()函数功能:从文件EnCodeFileName中读入“0”和“1”表示的哈夫曼编码数据,将其转换为文本字符,并将译码结果写入文件DecodeFileName中。函数参数:无 函数返回值:无(6)显示哈夫曼树函数:PrintHuffmanTree函数格式 void PrintHuffmanTree()函数功能:以凹式形式

13、显示哈夫曼树函数参数:无 函数返回值:无(7)显示哈夫曼树表函数:PrintHuffmanTable函数格式 void PrintHuffmanTable()函数功能:以表格形式显示哈夫曼树函数参数:无 函数返回值:无(8)显示字符哈夫曼编码函数:PrintCharCoding函数格式 void PrintCharCoding()函数功能:显示字符的哈夫曼编码函数参数:无 函数返回值:无(9)读文件函数:ReadFromFile函数格式 int ReadFromFile()函数功能:从文件TableFileName中读哈夫曼树数据函数参数:无 函数返回值:0读数据失败 0-读入的数据个数(10

14、)选择根界点函数:Select函数格式 void Select(struct node ht,int n, int *s1,int *s2)函数功能:从多棵树中选择两个权值最小的根结点函数参数:struct node ht哈夫曼树int n选择结点的范围,即只能在0n中选择结点int *s1指向第一个权值最小的结点的指针int *s2指向第二个权值最小的结点的指针 函数返回值:无六、主要算法描述 1、初始化函数Initialization算法描述功能:读入字符及其权值,生成哈夫曼树和字符哈夫曼编码。字符输入的处理:C语言输入字符的处理很不方便,任何一个字符都当作有效字符处理,包括空格字符和回车

15、符。而用格式读函数读字符串很方便,空格字符和回车符都当作字符串数据的分隔。因此,可以先把字符用格式读函数把字符读入字符数组中,再将其赋值给字符变量,这样处理更简单。算法步骤: (1)输入:读入n个叶结点的字符和权值存放于静态树T中的前n个分量中。(2)初始化:将树T的其余结点的三个指针均置为空(-1),权值置为0,字符为“*”。 (3)合并:进行n-1次合并,将产生的新结点i依次放入T的第i个分量中(nim-1)。合并分两步进行: 在当前森林T0.i-1的所有结点中,选取权最小和次小的两个根结点Tp1和Tp2作为合并对象。(0p1,p2i-1) 将根为Tp1和Tp2的两棵树作为左右子树合并为一

16、棵新的树。新树的根为Ti,权值为Tp1和Tp2的权值之和。并且Tp1和Tp2的parent为i,Ti的lchild和rchild分别为p1和p2。 (4)保存哈夫曼树数据。 (5)生成字符编码。 (6)保存字符编码数据。算法描述如下: 2、编码函数Encode算法描述 原理:对被编码文件中的每个字符,在编码数据表中查找,若字符在编码数据表中,则取出字符编码放入结果文件中。算法描述如下:3、译码函数Decode算法描述 译码原理:依次从文件中读入“0”和“1”串,从哈夫曼树根结点开始,若读入的是“0”,则指针以到根结点的左孩子结点;若为“1”,则指针以到根结点的右孩子结点。重复该过程,直到指针达

17、到哈夫曼树的叶结点,输出该叶结点对应的字符,即完成一个字符的译码。算法描述如下图所示。3、显示哈夫曼树函数PrintHuffmanTree算法描述 原理:显示哈夫曼树的过程实际上就是按先根顺序输出哈夫曼树结点的过程。如果要按凹式形式输出结点,不仅要知道结点的树出顺序,而且要知道结点的层次,通过结点的层次可以计算出输出内容凹进的格数。在先序遍历的非递归算法中,把结点的层次也作为栈元素的基本内容就可以解决该问题。 栈的结点结构定义如下:struct stacknode int NodeLevel; /结点的层次 int NodeElem; /结点的序号 ; 采用顺序栈存储结构。 算法描述如下:4、

18、选择具有最小权值的两个根结点的函数Select算法描述 原理:根结点的条件是指向父结点的指针为空。选择第一个具有最小权值的跟结点时,首先要找到第一个根结点,即父结点指针为空的结点,再以次为基础找具有最小权值的根结点。 选择第二个具有最小权值的跟结点时,首先要找到第一个根结点,即父结点指针为空,而且不是第一个被选择的的结点,在以次为基础找具有最小权值的根结点时,同样要注意,满足条件的结点既是根结点,又不是第一个已选结点。算法描述如下图所式。七、部分函数代码#include /* for size_t, printf() */#include /* for getch() */#include /

19、* for tolower() */#include /* for malloc(), calloc(), free() */#include /* for memmove(), strcpy() */*树结构和全局结构指针*/#define NODENUM 26/*-哈夫曼树结点结构-*/struct node char ch; int weight; int parent; int lchild,rchild; *ht; /指向哈夫曼树的存储空间的指针变量/*-字符编码结点结构-*/struct HuffmanCoding char ch; char codingNODENUM; ;/*-

20、哈夫曼树遍历时栈的结点结构-*/struct stacknode int NodeLevel; int NodeElem; ;/*-常量文件名-*/ const char *TableFileName = HfmTbl.txt; /哈夫曼树数据文件 const char *CodeFileName = CodeFile.txt; /字符编码数据文件 const char *SourceFileName = SrcText.txt; /需编码的字符串文件 const char *EnCodeFileName = EnCodeFile.txt; /编码数据文件 const char *Decode

21、FileName = DecodeFile.txt; /译码字符文件/*/* 释放哈夫曼树数据空间函数 */*/ void free_ht() if(ht != NULL) free(ht); ht = NULL; /*/* 从文件读取哈夫曼树数据函数 */*/int ReadFromFile() int i; int m; FILE *fp; if(fp=fopen(TableFileName,rb)=NULL) printf(cannot open %sn, TableFileName); getch(); return 0; fread(&m,sizeof(int),1,fp); /m为

22、数据个数 free_ht(); ht=(struct node *)malloc(m*sizeof(struct node); fread(ht,sizeof(struct node),m,fp); fclose(fp); return m; /*/* 吃掉无效的垃圾字符函数函数 */* 从键盘读字符数据时使用,避免读到无效字符 */*/ void EatCharsUntilNewLine() while(getchar()!=n) continue;/*/* 选择权值最小的两个根结点函数 */*/void Select(struct node ht,int n, int *s1,int *s

23、2) int i,j; (学生完成) /*/* 创建哈夫曼树和产生字符编码的函数 */*/void Initialization() int i=0,n,m,j,f,s1,s2,start; char cdNODENUM; struct HuffmanCoding codeNODENUM; FILE *fp; printf(输入字符总数 n:); scanf(%d,&n); EatCharsUntilNewLine(); m=2*n-1; ht=(struct node *)malloc(m*sizeof(struct node);/申请哈夫曼树的存储空间 /*/ /* 创建哈夫曼树 */ /

24、* 1、输入字符和权值 */ /* 2、初始化哈夫曼树 */ /* 3、建立哈夫曼树 */ /*/ /把哈夫曼树的数据存储到文件中 if(fp=fopen(TableFileName,wb)=NULL) printf(cannot open %sn, TableFileName); getch(); return; fwrite(&m,sizeof(int),1,fp); fwrite(ht,sizeof(struct node),m,fp); fclose(fp); /*/ /* 产生字符编码 */ /* 从页结点开始,沿父结点上升,直到根结点 ,若沿 */ /* 父结点的左分支上升,则得编

25、码字符“0”, 若沿父结 */ /* 点的右分支上升,则得编码字符“1” */ /*/ /把字符编码数据存储到文件中 if(!(fp=fopen(CodeFileName,wb) printf(cannot open %sn, CodeFileName); getch(); return; fwrite(&n,sizeof(int),1,fp); fwrite(code,sizeof(struct HuffmanCoding),n,fp); fclose(fp); free_ht(); printf(nInitial successfule!n); getch(); /*/* 哈夫曼编码的函数 */*/void Encode(void) int i,j,n; char Encodestr256; struct HuffmanCoding codeNODENUM; FILE *fp1, *fp2; /*/ /* 字符编码 */ /* 1、读字符编码数据 */ /* 2、读需编码的字符串 */ /* 3、存储被编码的字符串数据到文件中 */ /* 4、打开存储编码的数据文件 */ /* 5、字符编码

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

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