哈夫曼编码译码器实验报告免费
哈夫曼编码译码实验报告
哈夫曼编码译码实验报告哈夫曼编码译码实验报告一、引言哈夫曼编码是一种用来对数据进行压缩的算法,它能够根据数据的频率分布来分配不同长度的编码,从而实现对数据的高效压缩。
本次实验旨在通过实际操作,深入理解哈夫曼编码的原理和实现方式,并通过编码和解码过程来验证其有效性。
二、实验目的1. 掌握哈夫曼编码的原理和算法;2. 学会使用编程语言实现哈夫曼编码和解码;3. 验证哈夫曼编码在数据压缩中的实际效果。
三、实验过程1. 数据准备在实验开始前,首先需要准备一段文本数据作为实验材料。
为了更好地展示哈夫曼编码的效果,我们选择了一篇新闻报道作为实验文本。
这篇报道涵盖了多个领域的信息,包括科技、经济、体育等,具有一定的复杂性。
2. 哈夫曼编码实现根据哈夫曼编码的原理,我们首先需要统计文本中每个字符的频率。
为了方便处理,我们将每个字符与其频率构建成一个字符-频率的映射表。
然后,我们根据频率构建哈夫曼树,将频率较低的字符作为叶子节点,频率较高的字符作为内部节点。
最后,根据哈夫曼树构建编码表,将每个字符映射到对应的二进制编码。
3. 哈夫曼解码实现在哈夫曼解码过程中,我们需要根据编码表将二进制编码转换回字符。
为了实现高效解码,我们可以将编码表转换为一个二叉树,其中每个叶子节点对应一个字符。
通过遍历二叉树,我们可以根据输入的二进制编码逐步还原出原始文本。
4. 编码和解码效果验证为了验证哈夫曼编码的有效性,我们需要对编码和解码的结果进行比较。
通过计算编码后的二进制数据长度和原始文本长度的比值,我们可以得到压缩率,进一步评估哈夫曼编码的效果。
四、实验结果经过实验,我们得到了以下结果:1. 哈夫曼编码表根据实验文本统计得到的字符-频率映射表,我们构建了哈夫曼树,并生成了相应的编码表。
编码表中每个字符对应的编码长度不同,频率较高的字符编码长度较短,频率较低的字符编码长度较长。
2. 编码结果将实验文本使用哈夫曼编码进行压缩后,得到了一串二进制数据。
哈弗曼编译器实验报告
实习报告题目:哈弗曼编译码器班级:电信系通信工程0902班完成日期:2010.11一、需求分析1、编写哈弗曼编译码器,其主要功能有(1)I:初始化(Initialization)。
从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树。
(2)E:编码(Encoding)。
利用已建好的哈夫曼树),对从终端输入的正文进行编码,然后从终端输出。
(3)D:译码(Decoding )。
利用已建好的哈夫曼树将从终端输入的代码进行译码,结果从终端输出。
(4)P:印哈夫曼树(Print)。
将已编码的的哈夫曼树显示在终端上,同时将此字符形式的哈夫曼树。
2、测试数据:输入的字符={a, b, c, d, e}其对应的权值={5,29,7,8,14}二、概要设计1、二哈弗曼树的抽象数据类型定义为:ADT HuffmanTree{数据对象D:D是具有相同性质的数据元素的集合数据关系R:若D=Φ,则R= Φ,哈弗曼树为空若D≠Φ,则R= {H},H是如下二元关系:(1)在D中存在唯一的称为根的数据元素root,它在关系H下无前驱(2)若D-{root}≠Φ,则存在D-{root}={Dl,Dr}。
且Dl∩Dr=Φ(3)若Dl≠Φ,则Dl中存在唯一的数据元素Xl,<root, Xl>属于H,且存在Dl上的关系H1属于H。
若Dr≠Φ,则Dr中存在唯一的数据元素Xr,<root, X>属于H,且存在Dr上的关系Hr属于HH={<root, Xl>,<root, X>,Hl,Hr};(4)(Dl,{Hl})是一棵符合本定义的哈弗曼树,称为根的左子树。
(Dr,{Hr})是一棵符合本定义的哈弗曼树,称为根的右子树。
基本操作:HuffmanCoding(&HT, &HC, &sum)操作结果:建立哈弗曼树并进行编码将编码存放在HC中,并返回字符的个数。
Encoding(HT, HC, sum)操作结果:利用已建立的哈弗曼树对字符进行编码Decoding(HuffmanTree HT,HuffmanCode HC,int sum)操作结果:对输入的密码进行翻译Print(HT, HC, sum)操作结果:打印建立好的哈弗曼树}ADT HuffmanTree三、详细设计(1)哈弗曼树每个节点的定义:typedef struct{unsigned int weight;unsigned int parent,lchild,rchild;char elemt[20];}HTNode,*HuffmanTree;(2)定义指向哈弗曼树的指针,用于动态分配空间typedef char **HuffmanCode;(3)哈弗曼树的基本操作Void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n){ //建立哈弗曼树,求出哈弗曼编码if (n<=1)return;m=2*n-1; //n 个叶子的HuffmanTree共有2n-1个结点HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));for(p=HT+1,i=0; i<n; ++i,++p,++w)*p={*w,0,0,0};//给前n个单元初始化for(;i<=m; ++i,++p)*p ={0,0,0,0}; //从叶子之后的存储单元清零for(i=n+1;i<=m; ++i){ //建Huffman树(从n个叶子后开始存内结点) Select(HT, i-1, s1, s2);//选择parent为0且weight最小的两个结点,HT[s1].parent=i; HT[s2].parent=i; //给双亲分量赋值HT[i].lchild=s1; HT[i].rchild=s2; //给合并后的内结点赋孩子值HT[i].weight=HT[s1].weight+ HT[s2].weight;} //以上建立了哈弗曼树,以下求哈弗曼编码HC=(HuffmanCode)malloc((n+1)*sizeof(char*));//分配n个字符编码的头指针向量(一维数组)cd=(char*) malloc(n*sizeof(char)); //分配求编码的临时最长空间cd[n-1]=“\0”; //编码结束符(从cd[0]~cd[n-1]为合法空间)for(i=1;i<=n;++i) //逐个字符求Huffman编码{start=n-1; //编码结束符位置for(c=i,f=HT[i].parent; f!=0; c=f, f=HT[f].parent)//从叶子到根逆向求编码if(HT[f].lchild==c) cd[--start]=“0”;else cd[--start]=“1”;HC[i]=(char*)malloc((n-start)*sizeof(char));//为第i个字符编码分配空间,并以数组形式存放各码串指针strcpy(HC[i],&cd[start]); //从cd复制编码串到HC所指空间}free(cd); //释放临时空间}//HuffmanCodingfor(i=0; i<n; ++i){start=n-1; //编码结束符位置for(c=i, f=HT[i].parent;f!=0;c=f, f=HT[f].parent) {If(HT[f].lchild==c) cd[--start]=“0”;else cd[--start]=“1”;} / /从叶子到根逆向求编码}// HuffmanCodingVoid Encoding(HuffmanTree HT,HuffmanCode HC,int sum) //利用已经建立的哈弗曼树对输入的字符进行哈弗曼编码{for(int i=0;a[i]!='\0';i++)//依次判断字符的对应的哈弗曼编码{for(int n=0;HT[n].elemt[0];n++)//查找a[i]在哈弗曼树中的位置{strcpy(p,HC[n]);p=p+strlen(HC[n]);break;//把编码复制接到code后}}i=0;printf("得到的编码是:\n");while(code[i]!='\0') //输出字符对应的哈弗曼编码{printf("%c",code[i++]);}}// EncodingVoid Decoding(HuffmanTree HT,HuffmanCode HC,int sum) //译码{while(code1[i]!='\0'){if(code1[i]=='0') b=HT[b].lchild;//当遇到0时指向哈弗曼树的左子树else if(code1[i]=='1') b=HT[b].rchild;//当遇到1时指向哈弗曼树的右子树}if(HT[b].lchild==0&&HT[b].rchild==0)//当左右子树均为空时表明已找到对应的字符{a1[n++]=HT[b].elemt[0];b=2*sum-2;//将对应的字符放在数组a1中并重新设置b的值继续翻译 }i++;}// DecodingVoid Print(HuffmanTree HT,HuffmanCode HC,int sum)//打印哈弗曼树{for(int i=0;i<2*sum-1;i++)//从首元素开始,逐个输入哈弗曼树的各项数据{printf("%d%c%d%d%d",i,HT[i].elemt[0],HT[i].parent,HT[i].lch ild,HT[i].rchild);}}// Print四、调试分析1、由于书上有详细的建立哈弗曼树的算法,编码,译码,打印哈弗曼树的算法比较简单,程序的模块比较简单,所以整体的思路比较清晰,但是在将算法,写为C语言的过程中,出现了很多的语法和逻辑上的错误,所以用了很多的时间调试,修改错误。
Huffman实验报告
实习报告题目:哈夫曼编/译码器班级:计算机四班24021004学号:2402100402姓名:张青赛完成日期:2011年6月10日一、设计题目哈夫曼编码/译码器二、需求分析Ⅰ、运行环境:Microsoft Visual C++Ⅱ、程序执行的命令包括1 初始化:输入一串字符(正文),计算不同字符(包括空格)的数目以及每种字符出现的频率(以该种字符出现的次数作为其出现频率),根据权值建立哈夫曼树,输出每一种字符的哈夫曼编码。
2 编码:利用求出的哈夫曼编码,对该正文(字符串)进行码,并输出。
3 译码:对于得到的一串编码,利用已求得的哈夫曼编码进行译码,将译出的正文输出。
4 结束5 测试数据:E : 12 H : 2 M : 3 K : 7三、设计目的:1. 掌握建立哈夫曼树和哈夫曼编码的方法。
2. 掌握哈夫曼编码的实际应用方法。
四、设计内容利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
这要求在发送端通过一个编码系统,对待传数据预先编码,在接收端将传来的数据进行译码。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编\译码系统。
试为这样的信息收发站写一个哈夫曼的编\译系统。
五设计说明:1 算法设计思想:确定哈夫曼树和哈夫曼编码的存储表示,在数组中存放结点的各类信息,设计构造哈夫曼树的程序creathuffmantree、求出n个字母的哈夫曼编码程序huffmancode和哈夫曼的译码程序huffmandecode。
利用译码程序进行译码并输出,main()中调用各个函数,实现整个过程。
2.二叉树的抽象数据类型定义为:ADT BinaryTree{数据对象D:D是具有相同特性的数据元素的集合数据关系R:若D为空,则BinaryTree称为空二叉树;若D不为空,则BinaryTree满足二元关系;基本操作P:InitBiTree(&T);操作结果:构造空二叉树T。
实验九 哈夫曼编码-译码器
实验九哈夫曼编码-译码器实验十哈夫曼编/译码器一、实验目的(1)掌握哈夫曼树的构造和应用(2)利用哈夫曼方法及其编/译码技术实现对传输信息编码/译码系统二、实验内容[问题描述](设计性实验)哈夫曼树很易求出给定字符集及其概率(或频度)分布的最优前缀码。
哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。
该技术一般可将数据文件压缩掉20,至90,,其压缩效率取决于被压缩文件的特征。
利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传送电文须预先编码,在接收须将传送来的数据进行译码。
请自行设计实现一个具有初始化、编码、译码、输入/输出等功能的哈夫曼码的编码/译码系统。
并实现以下报文的编码和译码:“this program is my favorite”。
[测试数据]某通信的电文字符集为26个英文字母及空格字符,其出现频度如下表所示:[实现提示]如何创建哈夫曼树及如何求得各结点对应的哈夫曼编码算法:参见ppt。
1、设计思想描述(1) 问题分析。
(2) 哈夫曼树中各结点的结构描述(提示:图示)。
(3) 哈夫曼树的存储结构描述(提示:分析采用顺序存储还是利用链式存储等)。
2、主要算法设计与实现[要求]1)、利用类模板来实现。
2)、类中各成员函数要求给出自行设计的算法步骤描述及主要设计思想。
3)、给出类中各成员函数算法设计实现。
4)、对自行设计的各算法进行评估(提示:时间复杂度、空间复杂度等)。
#include<iostream>#include<string>using namespace std;const int MAX = 1000;class HTree;class HTNode{friend class HTree;unsigned int weight;unsigned int parent, lchild, rchild; };class HuCode{friend class HTree;char *ch; //字符的编码char data;//被编码的字符};//动态分配数组存储哈夫曼编码表。
哈夫曼编码译码器实验报告
哈夫曼编码译码器实验报告实验名称:哈夫曼编码译码器实验一、实验目的:1.了解哈夫曼编码的原理和应用。
2.实现一个哈夫曼编码的编码和译码器。
3.掌握哈夫曼编码的编码和译码过程。
二、实验原理:哈夫曼编码是一种常用的可变长度编码,用于将字符映射到二进制编码。
根据字符出现的频率,建立一个哈夫曼树,出现频率高的字符编码短,出现频率低的字符编码长。
编码过程中,根据已建立的哈夫曼树,将字符替换为对应的二进制编码。
译码过程中,根据已建立的哈夫曼树,将二进制编码替换为对应的字符。
三、实验步骤:1.构建一个哈夫曼树,根据字符出现的频率排序。
频率高的字符在左子树,频率低的字符在右子树。
2.根据建立的哈夫曼树,生成字符对应的编码表,包括字符和对应的二进制编码。
3.输入一个字符串,根据编码表将字符串编码为二进制序列。
4.输入一个二进制序列,根据编码表将二进制序列译码为字符串。
5.比较编码前后字符串的内容,确保译码正确性。
四、实验结果:1.构建哈夫曼树:-字符出现频率:A(2),B(5),C(1),D(3),E(1) -构建的哈夫曼树如下:12/\/\69/\/\3345/\/\/\/\ABCDE2.生成编码表:-A:00-B:01-C:100-D:101-E:1103.编码过程:4.译码过程:5.比较编码前后字符串的内容,结果正确。
五、实验总结:通过本次实验,我了解了哈夫曼编码的原理和应用,并且实现了一个简单的哈夫曼编码的编码和译码器。
在实验过程中,我充分运用了数据结构中的树的知识,构建了一个哈夫曼树,并生成了编码表。
通过编码和译码过程,我进一步巩固了对树的遍历和节点查找的理解。
实验结果表明,本次哈夫曼编码的编码和译码过程正确无误。
在实验的过程中,我发现哈夫曼编码对于频率较高的字符具有较短的编码,从而实现了对字符串的高效压缩。
同时,哈夫曼编码还可以应用于数据传输和存储中,提高数据的传输效率和存储空间的利用率。
通过本次实验,我不仅掌握了哈夫曼编码的编码和译码过程,还深入了解了其实现原理和应用场景,加深了对数据结构和算法的理解和应用能力。
哈夫曼编码实验报告
实验1哈夫曼编码实验的目的是掌握哈夫曼编码的原理,掌握哈夫曼树的生成方法。
了解数据压缩。
实验要求实现Huffman编解码器生成算法。
三。
实验内容首先统计待压缩文件中出现的字符和字母的数量,根据字符字母和空格的概率对其进行编码,然后读取要编码的文件并将其存储在另一个文件中;然后调用已编码的文件,对输出进行解码,最后存储到另一个文件中。
5实验原理1。
假设树的权值是用huffn树的定义来构造的。
每个加权叶为wi,权值路径最小的二叉树成为Huffman树或最优二叉树。
Huffman树的结构:权重是一个输入频率的数组,这些值根据节点对象中的数据属性按顺序分配给HTs,即每个HT节点对应一个输入频率。
然后,根据数据属性,从最小值到最大值取两个最小值和这个小HT节点,将它们的数据相加,构造一个新的htnode作为它们的父节点。
指针parentleftchild和rightchild被分配了相应的值。
将这个新节点插入最小堆。
按照这个程序,我们能建一棵树吗?通过构造的树,从下至上搜索父节点,直到父节点成为树的顶点。
这样,每次向上搜索后,根据原始节点是父节点的左子节点还是右子节点记录1或0。
每一个01都有一个完整的编码,每一个都有一个完整的编码。
初始化,以文本文件中的字符数为权值,生成Huffman树,按符号概率由大到小对符号进行排序,概率最小的两个符号形成一个节点。
重复步骤()(),直到概率和为1,从根节点到每个符号对应的“叶”,概率高的符号标为“0”,概率低的符号从根节点开始,对符号7进行编码。
实验程序ා include<iostream>ා include<iomanip>ා include<iomanip>使用命名空间STD;typedef struct//节点结构{char data;//记录字符值long int weight;//记录字符权重unsigned int parent,lchild,rchild;}Htnode,*HuffmanTree;typedef char**huffmancode;//dynamicly allocate array to store Huffman code table void select(HuffmanTree&HT,int i,int&S1,int&S2)//选择HT[1中权重最小且父节点不为0的两个节点。
哈夫曼编译码系统实验报告
数学与计算机学院数据结构实验报告年级大二学号********* 姓名******* 成绩专业电气信息类(计算机)实验地点主楼402 指导教师实验项目实验日期2010年11月20日一、实验目的和要求通过对简单哈夫曼编/译码系统的设计与实现来熟练掌握树型结构在实际问题中的应用。
此实验可以作为综合实验,阶段性实验时可以选择其中的几个功能来设计和实现。
二、问题描述利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。
试为这样的信息收发编写一个哈夫曼码的编/译码系统。
三、数据结构设计1、构造哈夫曼树时使用静态链表作为哈夫曼树的存储。
在构造哈夫曼树时,设计一个结构体数组HuffNode保存哈夫曼树中各结点的信息,根据二叉树的性质可知,具有n个叶子结点的哈夫曼树共有2n-1个结点,所以数组HuffNode的大小设置为2n-1;描述结点的数据类型为:struct HNodeType{char data; //结点字符int weight;//结点权值int parent;int lchild;int rchild;int level;};2、求哈夫曼树编码时使用一维结构数组HuffCode作为哈夫曼编码信息的存储。
求哈夫曼编码,实质上就是在已建立的哈夫曼树中,从叶子结点开始,沿结点的双亲链域回退到根结点,每回退一步,就走过了哈夫曼树的一个分支,从而得到一位哈夫曼码值,由于一个字符的哈夫曼编码是从根结点到相应叶子结点所经过的路径上各分支所组成的0、1序列,因此先得到的分支代码为所求编码为所求编码的低位码,后得到的分支代码为所求编码的高位码,所以设计如下数据类型:struct HCodeType{int bit[MAXBIT];int start;};3、文件hfmtree.txt、codefile.txt、textfile.txt。
哈夫曼编码译码器实验报告
中北大学数据结构课程设计说明书学生姓名:郝晨栋学号:1021010933学院: 软件学院专业: 软件开发与测试题目: 哈夫曼编码/译码器指导教师康珺2011年12月20日目录1 问题描述.............................................................. 错误!未定义书签。
2 需求分析.............................................................. 错误!未定义书签。
3 概要设计 (1)3.1抽象数据类型定义 (1)3.2总体框图以及功能描述 (2)4 详细设计 (2)4.1数据类型的定义 (2)4.2主要模块的算法描述 (3)5 测试分析 (4)6 课程设计总结 (6)附录(源程序清单) (7)1 问题描述1.设计一个利用哈夫曼算法的编码和译码系统,重复地显示并处理以下项目,直到选择退出为止。
(1) 将权值数据存放在数据文件(文件名为data.txt,位于当前目录中);(2) 分别采用动态和静态存储结构; 初始化:键盘输入字符集大小n、n个字符和n个权值,建立哈夫曼树;(3) 编码:利用建好的哈夫曼树生成哈夫曼编码;输出编码;设计要求:(1) 符合课题要求,实现相应功能;(2) 要求界面友好美观,操作方便易行;(3) 注意程序的实用性、安全性。
2 需求分析编写此软件是为了实现一个利用哈夫曼算法的编码和译码系统。
比如,再利用电报进行通讯时,需要将文字转换成由二进制的字符组成的字符串。
比如需传送的电文为“A B A C C D A”假设将A,B,C,D分别编码为00、01、10、11.则上述电文遍为00010010101100,总长度为14位。
但是在传送过程中,总希望长度能够尽可能的短,于是我们想采用长度不等的编码。
但是这种编码必须遵循:任何一个字符的编码都不是另一个字符编码的前缀。
哈夫曼实验报告(附代码)
哈夫曼实验报告(附代码)以下是为大家整理的哈夫曼实验报告(附代码)的相关范文,本文关键词为哈夫曼,实验,报告,代码,,您可以从右上方搜索框检索更多相关文章,如果您觉得有用,请继续关注我们并推荐给您的好友,您可以在综合文库中查看更多范文。
哈弗曼编码/译码器一、程序的功能分析1.构造哈夫曼树及哈夫曼编码:从终端读入字符集大小n、n 个字符以及n个对应的权值,建立哈夫曼树;利用已经建好的哈夫曼树求每个叶结点的哈夫曼编码,并保存。
2.编码:利用已构造的哈夫曼编码对“明文”文件中的正文进行编码,然后将结果存入“密文”文件中。
3.译码:将“密文”文件中的0、1代码序列进行译码。
(读文件) 4.打印“密文”文件:将文件以紧凑格式显示在终端上,每行30个代码;同时,将此字符形式的编码文件保存。
5.打印哈夫曼树及哈夫曼编码:将已在内存中的哈夫曼树以凹入表形式显示在终端上,同时将每个字符的哈夫曼编码显示出来;并保存到文件。
二、基本要求分析1、输入输出的要求按提示内容从键盘输入命令,系统根据用户输入的需求在保证界面友好的前提下输出用户所需信息,并按要求保存文件,以便保存备份信息。
2、测试数据(1).令叶子结点个数n为4,权值集合为{1,3,5,7},字符集合为{A,b,c,D},且字符集与权值集合一一对应。
(2).令叶子结点个数n为7,权值集合为{12,6,8,18,3,20,2},字符集合为{A,b,c,D,e,F,g},且字符集与权值集合一一对应。
(3).请自行选定一段英文文本,统计给出的字符集,实际统计字符的频度,建立哈夫曼树,构造哈夫曼编码,并实现其编码和译码。
三、概要设计1.主模块的流程及各子模块的主要功能主函数负责提供选项功能,循环调控整个系统。
创建模块实现接收字符、权值、构建哈夫曼树,并保存文件,此功能是后续功能的基础。
编码模块实现利用已编好的哈夫曼树对每个字符进行哈夫曼编码,即对每个字符译出其密文代码,并保存文件。
哈夫曼编码实验报告
哈夫曼编码实验报告数据结构实验报告1.实验要求利用二叉树结构实现哈夫曼编/解码器。
基本要求:1、初始化(Init):能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立哈夫曼树2、建立编码表(CreateTable):利用已经建好的哈夫曼树进行编码,并将每个字符的编码输出。
3、编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的字符串输出。
4、译码(Decoding):利用已经建好的哈夫曼树对编码后的字符串进行译码,并输出译码结果。
5、打印(Print):以直观的方式打印哈夫曼树(选作)计算输入的字符串编码前和编码后的长度,并进行分析,讨论哈夫曼编码的压缩效果。
并用I love data Structure, I love Computer。
I will try my best to study data Structure.进行测试。
2. 程序分析哈夫曼树结点的存储结构包括双亲域parent,左子树lchild,右子树rchild,还有字符word,权重weight,编码code对用户输入的信息进行统计,将每个字符作为哈夫曼树的叶子结点。
统计每个字符出现的次数作为叶子的权重,统计次数可以根据每个字符不同的ASCII码,根据叶子结点的权重建立一个哈夫曼树。
建立每个叶子的编码从根结点开始,规定通往左子树路径记为0,通往右子树路径记为1。
由于编码要求从根结点开始,所以需要前序遍历哈夫曼树,故编码过程是以前序遍历二叉树为基础的。
同时注意递归函数中能否直接对结点的编码域进行操作。
编码信息只要遍历字符串中每个字符,从哈夫曼树中找到相应的叶子结点,取得相应的编码。
最后再将所有找到的编码连接起来即可。
译码则是将编码串从左到右逐位判别,直到确定一个字符。
这就是哈夫曼树的逆过程。
遍历编码串,从哈夫曼树中找到相应的叶子结点,取得相应的字符再将找到的字符连接起来即可。
2.1 存储结构哈夫曼树结点存储结构2.2 关键算法分析1.统计字符频度自然语言描述:(1)取出字符串中的一个字符(2)遍历所有初始化的哈夫曼树结点(3)如果结点中有记录代表的字符且字符等于取出的字符,说明该字符的叶子存在,则将该结点的权值加1(4)如果所有结点记录的字符均没有与取出的字符一致,说明该字符的叶子不存在,则将结点的字符记为取出字符,并将权重设为1 (5)重复以上步骤,直至字符串中所有字符全部遍历伪代码描述:1. for(int i=0;i<length;i++)< p="">1.1 for (int j=0;j<length;j++)< p="">1.1.1if (WordStr[i]==HuffTree[j].word)//若字符已被统计,则增加权值即可1.1.1.1 权重++;1.1.1.2 break;1.1.2 else if(!HuffTree[j].word)//否则需要一个新结点储存这个字符1.1.2.1 HuffTree[j].word=WordStr[i];1.1.2.2 HuffTree[j].weight=1;1.1.2.3 叶子结点个数++;1.1.2.4 break;时间复杂度O(n2),空间复杂度S(0)2. 构造哈夫曼树自然语言描述:(1)选出权值最小的两个结点,其权值和作为其根结点的权值,最小的结点作为左子树,次小的作为右子树,不断将两棵子树合并为一棵树。
编码译码实验报告
一、实验目的1. 理解编码译码的基本原理和方法。
2. 掌握哈夫曼编码和译码的实现过程。
3. 通过实验,提高编程能力和数据结构应用能力。
二、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发工具:Visual Studio 2019三、实验内容1. 哈夫曼编码与译码(1)哈夫曼编码的原理哈夫曼编码是一种变长编码,通过为不同频率的字符分配不同的编码长度,达到压缩数据的目的。
哈夫曼编码的核心是构建一棵哈夫曼树,树中每个叶子节点对应一个字符,非叶子节点对应两个子节点的编码。
(2)哈夫曼编码的实现首先,根据输入的字符及其频率,构建哈夫曼树。
然后,从根节点开始,对每个叶子节点进行编码,编码规则为从根节点到叶子节点的路径,左子节点编码为“0”,右子节点编码为“1”。
(3)哈夫曼译码的实现根据哈夫曼编码的编码规则,将编码后的数据还原成原始字符。
从编码数据的第一个比特开始,根据编码规则,逐步还原出原始字符。
2. 字符串编码与译码(1)字符串编码的原理字符串编码是将字符串中的字符转换成二进制表示,以达到压缩数据的目的。
常见的字符串编码方法有ASCII编码、UTF-8编码等。
(2)字符串编码的实现以ASCII编码为例,将字符串中的每个字符转换为对应的ASCII码,然后将其转换为二进制表示。
(3)字符串译码的实现将编码后的二进制数据转换回对应的ASCII码,再将ASCII码转换成字符。
四、实验步骤1. 创建一个新的C++项目,命名为“编码译码实验”。
2. 在项目中创建两个源文件:main.cpp和编码译码.cpp。
3. 在main.cpp中编写代码,实现以下功能:(1)从文件中读取字符串,进行哈夫曼编码。
(2)将编码后的数据写入文件。
(3)从文件中读取编码后的数据,进行哈夫曼译码。
(4)将译码后的字符串输出到屏幕。
4. 在编码译码.cpp中编写代码,实现以下功能:(1)构建哈夫曼树。
(2)实现哈夫曼编码和译码算法。
哈夫曼编码译码实训报告
一、实训目的本次实训旨在通过实际操作,使学生掌握哈夫曼编码的基本原理和方法,熟悉哈夫曼树的构建过程,并能够熟练地进行哈夫曼编码和译码操作。
通过实训,提升学生对数据压缩技术的理解和应用能力。
二、实训内容1. 哈夫曼树构建- 收集给定字符串中每个字符的出现频率。
- 根据字符频率构建哈夫曼树,其中频率高的字符对应较大的权重。
- 使用优先队列(最小堆)实现哈夫曼树的构建。
2. 哈夫曼编码- 遍历哈夫曼树,为每个叶子节点分配唯一的编码,左分支为0,右分支为1。
- 根据分配的编码生成字符编码表。
3. 哈夫曼译码- 使用生成的编码表,将编码字符串转换回原始字符串。
三、实训步骤1. 数据准备- 选择一段英文或中文文本作为输入数据。
2. 构建哈夫曼树- 统计输入数据中每个字符的出现频率。
- 使用优先队列构建哈夫曼树。
3. 生成哈夫曼编码- 遍历哈夫曼树,为每个叶子节点分配编码。
- 生成字符编码表。
4. 编码数据- 使用哈夫曼编码表对输入数据进行编码。
5. 译码数据- 使用哈夫曼编码表对编码后的数据进行译码。
6. 结果分析- 比较编码前后数据的大小,分析哈夫曼编码的压缩效果。
四、实训结果1. 哈夫曼树构建- 成功构建了给定字符串的哈夫曼树。
2. 哈夫曼编码- 成功生成了每个字符的哈夫曼编码。
3. 哈夫曼译码- 成功将编码后的数据译码回原始字符串。
4. 压缩效果分析- 通过对比编码前后数据的大小,验证了哈夫曼编码的压缩效果。
五、实训总结1. 哈夫曼编码原理- 哈夫曼编码是一种基于字符频率的变长编码方法,能够有效降低数据传输的冗余度。
2. 哈夫曼树构建- 哈夫曼树的构建是哈夫曼编码的关键步骤,通过优先队列(最小堆)实现。
3. 哈夫曼编码与译码- 哈夫曼编码和译码过程相对简单,但需要正确处理编码表和字符编码。
4. 实训收获- 通过本次实训,掌握了哈夫曼编码的基本原理和方法,熟悉了哈夫曼树的构建过程,并能够熟练地进行哈夫曼编码和译码操作。
哈夫曼编码解码实验报告
哈夫曼编码解码实验1.实验要求掌握二叉树的相关概念掌握构造哈夫曼树,进行哈夫曼编码。
对编码容通过哈夫曼树进行解码。
2.实验容通过二叉树构造哈夫曼树,并用哈夫曼树对读取的txt文件进行哈夫曼编码。
编码完成后通过哈夫曼树进行解码。
#include<stdio.h>#include<string.h>#define MAX 100//定义哈夫曼树的存储结构typedef struct{char data;int weight;int parent;int lch;int rch;}HuffNode;//定义哈夫曼编码的存储结构typedef struct{char bit[MAX];int start;}HuffCode;HuffNode ht[2*MAX];HuffCode hcd[MAX];int Coun[127]={0};int n;char s1[200000];char text[5000];//构造哈夫曼树void HuffmanTree(){int i,j,k,left,right,min1,min2;//printf("输入叶子的节点数:");//scanf("%d",&n);printf("字符数量=%d\n",n);for(i=1;i<=2*n-1;i++){ht[i].parent=ht[i].lch=ht[i].rch=0;}j=0;for(i=1;i<=n;i++){/*getchar();printf("输入第%d个叶子节点的值:",i);scanf("%c",&ht[i].data);printf("输入该节点的权值:");scanf("%d",&ht[i].weight);*/for(;j<127;j++){if(Coun[j]!=0){ht[i].data=j;//printf("%c",ht[i].data);ht[i].weight=Coun[j];//printf("%d",ht[i].weight);break;}}j++;}printf("\n");for(i=1;i<=n;i++){printf("%c",ht[i].data);}printf("\n");for(i=n+1;i<=2*n-1;i++){//在前n个结点中选取权值最小的两个结点构成一颗二叉树min1=min2=10000;//为min1和min2设置一个比所有权值都大的值left=right=0;for(k=1;k<=i-1;k++){if(ht[k].parent==0)//若是根结点//令min1和min2为最小的两个权值,left和right 为权值最小的两个结点位置if(ht[k].weight<min1){min2=min1;right=left;min1=ht[k].weight;left=k;}else if (ht[k].weight<min2){min2=ht[k].weight;right=k;}}ht[left].parent=i;ht[right].parent=i;ht[i].weight=ht[left].weight+ht[right].weight;ht[i].lch=left;ht[i].rch =right;}}//构造哈夫曼编码void HuffmanCode(){int i,c,k,f;HuffCode cd;for(i=1;i<=n;i++){cd.start=n;c=i;f=ht[i].parent;while(f!=0){if(ht[f].lch==c)cd.bit[cd.start]='0';elsecd.bit[cd.start]='1';cd.start--;c=f;f=ht[f].parent;}hcd[i]=cd;}printf("输出哈夫曼编码:\n");for(i=1;i<=n;i++){printf("%c:",ht[i].data);for(k=hcd[i].start+1;k<=n;k++)printf("%c",hcd[i].bit[k]);printf("\n");}}//对字母进行编码void Code()//将字符与相应的哈夫曼编码进行匹配,输出编码结果{int i=0,j,k,h=0;while(text[i]!='\0'){for(j=1;j<=n;j++){if(text[i]==ht[j].data){for(k=hcd[j].start+1;k<=n;k++){s1[h]=hcd[j].bit[k];h++;}break;}}i++;}//printf("编码\n");//puts(s1);//printf("\n");}//解码void HuffmanDecode(){printf("解码\n");int len,i,f;char C;//char S[MAXCODE];//scanf("%s",S);//使用gets()直接跳过len=strlen(s1);printf("s1:%d\n",len);f=2*n-1;for(i=0;i<len;i++){if(s1[i]=='0'){f=ht[f].lch;if(ht[f].lch==0&&ht[f].rch==0){C=ht[f].data;printf("%c",C);f=2*n-1;}}else if(s1[i]=='1'){f=ht[f].rch;if(ht[f].lch==0&&ht[f].rch==0){C=ht[f].data;printf("%c",C);f=2*n-1;}}}printf("\n");}//统计字母个数及其权值void Count(){int i,j,m;n=0;i=0;//printf("请仅输入小写字母\n");//例程本省存在一个BUG,只输入一个字母不能进行编码(并未解决)//scanf("%s",s);while(text[i]!='\0')//使用ASCII码表进行统计{m=text[i];//printf("%d\n",m);Coun[m]++;i++;}for(j=0;j<127;j++){if(Coun[j]!=0)n++;}}//mark Codevoid main(){int l=0;FILE *fp;fp=fopen("text.txt","r");if(fp==NULL){printf("文件打开失败\n");while(1);}while(!feof(fp)){text[l] = fgetc(fp);l++;}printf("输入文本\n");printf("%s\n",text);fclose(fp);Count();HuffmanTree();HuffmanCode();Code();HuffmanDecode();}文本文件文本输入进行哈夫曼编码对文本进行编码输出解码结果3.实验总结通过本次实验,对二叉树的应用有了相应的了解,掌握了如何构造哈夫曼编码,如何对编码结果进行解码。
哈夫曼编译码器 实习报告
实习报告哈夫曼编译码器班级:11052414姓名:沈晓斌(11054417)盛豪杰(11054418)一.需求分析1.问题描述用huffman编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传输数据预先编码,在接收端将传来的数据进行译码(复原)。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。
是为着这样的信息收发站写一个huffman编/译码系统。
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)。
将已在内存中的哈夫曼树以直观的方式(凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrin中。
3.测试数据(1)利用下面这道题中的数据调试程序。
某系统在通信联络中只可能出现八种字符,其概率分别为0.25,0.29,0.07,0.08,0.14,0.23,0.03,0.11,试设计哈夫曼编码。
(2)用下表给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:“THIS PROMGRAM IS MY FAVORITE”。
二.概要设计typedef struct{unsigned int weight;unsigned int parent, lchild, rchild;}HTNode, *HuffmanTree; //动态分配数组存储哈夫曼树HTNode HT[30]; //全局变量HT,二维数组HC储存哈夫曼编码int s1, s2; //定义全局变量char HC[10000][10000];void Select(int i) //从HT中选择权值最小的两个作为一个新的结点void HuffmanCoding(int *w)//w存放n个字符的权值(均>0),构造哈夫曼树HT,并求出n个字符的哈夫曼编码HC.void OpenCode(char a[]) //对输入的字符进行编码void OpenDecode(char a[])//对输入的编码进行译码主函数主函数主要设计的是一个分支语句,让用户挑选所实现的功能。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
哈夫曼编码译码器实验报告(免费)————————————————————————————————作者:————————————————————————————————日期:问题解析与解题方法问题分析:设计一个哈夫曼编码、译码系统。
对一个ASCII编码的文本文件中的字符进行哈夫曼编码,生成编码文件;反过来,可将编码文件译码还原为一个文本文件。
(1)从文件中读入任意一篇英文短文(文件为ASCII编码,扩展名为txt);(2)统计并输出不同字符在文章中出现的频率(空格、换行、标点等也按字符处理);(3)根据字符频率构造哈夫曼树,并给出每个字符的哈夫曼编码;(4)将文本文件利用哈夫曼树进行编码,存储成压缩文件(编码文件后缀名.huf)(5)用哈夫曼编码来存储文件,并和输入文本文件大小进行比较,计算文件压缩率;(6)进行译码,将huf文件译码为ASCII编码的txt文件,与原txt文件进行比较。
根据上述过程可以知道该编码译码器的关键在于字符统计和哈夫曼树的创建以及解码。
哈夫曼树的理论创建过程如下:一、构成初始集合对给定的n个权值{W1,W2,W3,...,Wi,...,Wn}构成n棵二叉树的初始集合F={T1,T2,T3,...,Ti,...,Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。
二、选取左右子树在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。
三、删除左右子树从F中删除这两棵树,并把这棵新的二叉树同样以升序排列加入到集合F中。
四、重复二和三两步,重复二和三两步,直到集合F中只有一棵二叉树为止。
因此,有如下分析:1.我们需要一个功能函数对ASCII码的初始化并需要一个数组来保存它们;2.定义代表森林的数组,在创建哈夫曼树的过程当中保存被选中的字符,即给定报文中出现的字符,模拟哈夫曼树选取和删除左右子树的过程;3.自底而上地创建哈夫曼树,保存根的地址和每个叶节点的地址,即字符的地址,然后自底而上检索,首尾对换调整为哈夫曼树实现哈弗曼编码;4.从哈弗曼编码文件当中读入字符,根据当前字符为0或者1的状况访问左子树或者右孩子,实现解码;5.使用文件读写操作哈夫曼编码和解码结果的写入;解题方法:结构体、数组、类的定义:1.定义结构体类型的signode 作为哈夫曼树的节点,定义结构体类型的hufnode 作为哈夫曼编码对照表的节点,定义HFM类实现对哈夫曼树的创建,利用其成员函数完成哈夫曼编码译码的工作。
2.定义signode 类型的全局数组SN[256](为方便调用,之后的forest[256],hufNode[256]均为全局数组), 保存ASCII编码的字符,是否在文章中出现(bool类型)以及出现次数(int类型,权重),左右孩子节点位置,父节点位置信息;3.为节省存储空间,定义signode * 类型的全局数组forest[256], 模拟森林,在创建哈夫曼树的过程中保存出现字符的指针,模拟哈夫曼树选取和删除左右子树的过程;4.定义hufnode 类型的全局数组hufNode[256],在编码时最为哈夫曼编码对照表的节点,char 型c保存字符,int code[100]保存其哈夫曼编码;5.定义HFM类,主要保存哈夫曼树的根节点指针,但其丰富的功能函数将实现哈夫曼编码译码的工作及其他功能;函数介绍:1.void init(signode * sig){……} 初始化数组SN[];2.void compress(){……}输出压缩对比情况的信息;3.void exchange(){……}用两层for循环实现hufNode[i]节点的成员哈夫曼编码数组code[]前后元素的对换,因为在之前的编码过程中由于是从叶节点追溯至根节点,存入code数组的哈夫曼编码与哈夫曼编码的概念反向,故而要调整;4.signode * getroot(){……}返回哈夫曼树的根节点指针;5.signode * HFM::creat(){……}创建哈夫曼树,首先用三个for循环查看forest数组,找到权值最小的两个字符,以int型的min1,min2记录其下标,定义signode * 类型指针pp指向新生成signode节点,用指针操作使pp指向的节点的权值为min1,min2权值之和,pp做孩子指向forest[min1],右孩子指向forest[min2],min1,min2的父指针指向pp,然后将pp存入min1的位置,min2之后的每一个节点依次往前移一个位置,实现从forest数组中清除min1,min2并加入pp的操作;6.void HFM::hufcode(){……}哈夫曼编码,用for循环控制查看hufNode 数组,其初始化已在creat()的开始完成,对每一个字符实现编码,用while循环从叶节点开始,如果该节点是其父节点的左孩子就将code[hufNode[i].size++]赋值0,否则赋为1,直至当前节点的父节点为空,while循环结束;7.void HFM::savewithhufcode(FILE * inf,FILE * outf){……}将读入的文章以哈夫曼编码的形式存储,其中inf为读入文件的指针,outf为写入文件的指针,首先调用rewind(inf)函数将光标放置在文章开头,防止文件未关闭导致的错误,每读一个字符就用for循环在hufNode 数组中查找,因为hufNode 数组就是保存出现的字符的,故一定可以找到,然后再用fputc函数将code[]数组的内容写入文件,直至读入文件结束;8.void HFM::inorder(signode * sig){……}迭代法遍历树,遍历到叶节点时执行hufNode[count++].sig=sig语句实现hufNode 数组指向文章中出现的字符;9.int HFM::maxc(){……} 计数变量,记录哈夫曼编码最大位数;10.void HFM::hufdecode(FILE* ipf,FILE* opf){……}解码,从哈夫曼编码到字符,输出到屏幕和指定的文件中;11.void input(FILE * f){……}初始读入文章,保存出现的字符记录修改其权重;数据结构选择与算法设计数据结构选择:signode:struct signode{ //signode节点,哈夫曼树节点//char c; //字符//int weight; //权重//bool b; //文章中是否出现//signode * parent;signode * left;signode * right;signode(){ //初始化//c=NULL;b=false;weight=0;parent=left=right=NULL;}};C weight bhufnode:struct hufnode{ //哈夫曼编码对照表节点// signode * sig;int code[100]; //保存哈夫曼编码//int size;bool b;hufnode(){sig=NULL;size=0;b=true;}};SigHFM:class HFM{ //哈夫曼类// private:signode * root; //哈夫曼树根// signode * pt; //编码时做哨兵指针// int alleaf; public: HFM(int all){root=pt=NULL;alleaf=all;} //all 是森林中树的个数// ~HFM(){} signode * getroot(){return root;} signode * creat(); //创建哈夫曼树// void hufcode(); //编码// void savewithhufcode(FILE * inf,FILE * outf); //用哈弗曼编码存储文件// void hufdecode(FILE* ipf,FILE* opf); //解码// void inorder(signode * sig); int maxc(); //求取哈弗曼编码最大长度// };算法设计:Root ptalleaf 初始化从f1读输出字创建哈inpu init huffman 哈夫曼编码并huffman.hufcod e();测试结果Doc 窗口:1. 2.哈 3.查输入数输入数compres huffman.huf文件读写(部分):总结程序分析:本次哈夫曼编码译码器的课程实验做得还算成功,不仅仅在于程序能够正常运行,实现应有的功能,关键在于过程,在于小组成员的分工合作和一起纠错排错的过程,在完成程序的过程中才能真正理解面向对象和模块化设计的思想,我们不仅仅是说要每人分几个函数,关键在于这些函数代表的是一个个功能模块,任何一个模块出现问题或者模块之间的衔接出现问题都将导致程序运行的失败。
哈夫曼编码译码器课程实验我主要负责完成编码译码器数据结构和功能模块框架的设计,结构体和类的定义,以及creat函数,hufcode函数,savewithhufcode函数的实现。
在初始设计的时候,我体会到书写流程图的重要性,只有又一个清晰的设计思路才能事半功倍,分工明确,避免无效劳动或者在错误的编程方向上走弯路,也让大家明白自己在程序设计中的位置和职责。
初始的创建是哈夫曼编码译码系统成功的关键,我在创建的过程当中多次使用树的先根,配合中根遍历操作,输出接点字符或者权重信息,作为检验,对验证和纠错起到了非常大的作用。
在适当的地方调用它们,运行时可以看到验证编写程序的正确性;通过本次实验,提高了自已调试程序的能力。
充分体会到了在程序执行时的提示性输出的重要性。
编写大一点的程序,应先写出算法,再写程序,一段一段调试;对于没有实现的操作用空操作代替,这样容易找出错误所在。
最忌讳将所有代码写完后再调试,这样若程序有错误,太难找。
需要特别强调的是:1.感觉文件操作自己并不是很熟练,尽管在向显示器输出的时候并没有什么错误但是读写文件的时候就没那么顺利了,比如说当编写savewithhufcode函数时读文件,却总不执行,后来通过断点测试发现每次fgetc()返回值总为-1,于是我考虑是否是文件没有打开或者文件结束的缘故,后来想通了是之前打开的文件光标读操作结束后仍在结尾故每次总返回-1,故调用rewind函数将光标位置移动到文章开始。
2. 用哈夫曼编码存储文件的时候还应注意数字0,1与字符0,1的不同,不应直接在fputc()函数中直接写入0,1那么将会是写入的文章中什么都没有,因为0在ASCII码中代表NULL。