完整word版哈夫曼编码译码器试验报告
哈夫曼编码译码实验报告
哈夫曼编码译码实验报告哈夫曼编码译码实验报告一、引言哈夫曼编码是一种用来对数据进行压缩的算法,它能够根据数据的频率分布来分配不同长度的编码,从而实现对数据的高效压缩。
本次实验旨在通过实际操作,深入理解哈夫曼编码的原理和实现方式,并通过编码和解码过程来验证其有效性。
二、实验目的1. 掌握哈夫曼编码的原理和算法;2. 学会使用编程语言实现哈夫曼编码和解码;3. 验证哈夫曼编码在数据压缩中的实际效果。
三、实验过程1. 数据准备在实验开始前,首先需要准备一段文本数据作为实验材料。
为了更好地展示哈夫曼编码的效果,我们选择了一篇新闻报道作为实验文本。
这篇报道涵盖了多个领域的信息,包括科技、经济、体育等,具有一定的复杂性。
2. 哈夫曼编码实现根据哈夫曼编码的原理,我们首先需要统计文本中每个字符的频率。
为了方便处理,我们将每个字符与其频率构建成一个字符-频率的映射表。
然后,我们根据频率构建哈夫曼树,将频率较低的字符作为叶子节点,频率较高的字符作为内部节点。
最后,根据哈夫曼树构建编码表,将每个字符映射到对应的二进制编码。
3. 哈夫曼解码实现在哈夫曼解码过程中,我们需要根据编码表将二进制编码转换回字符。
为了实现高效解码,我们可以将编码表转换为一个二叉树,其中每个叶子节点对应一个字符。
通过遍历二叉树,我们可以根据输入的二进制编码逐步还原出原始文本。
4. 编码和解码效果验证为了验证哈夫曼编码的有效性,我们需要对编码和解码的结果进行比较。
通过计算编码后的二进制数据长度和原始文本长度的比值,我们可以得到压缩率,进一步评估哈夫曼编码的效果。
四、实验结果经过实验,我们得到了以下结果:1. 哈夫曼编码表根据实验文本统计得到的字符-频率映射表,我们构建了哈夫曼树,并生成了相应的编码表。
编码表中每个字符对应的编码长度不同,频率较高的字符编码长度较短,频率较低的字符编码长度较长。
2. 编码结果将实验文本使用哈夫曼编码进行压缩后,得到了一串二进制数据。
《哈夫曼编码》实验报告
《哈夫曼编码》实验报告《哈夫曼编码》实验报告一、实验目的1、掌握哈夫曼编码原理;2、熟练掌握哈夫曼树的生成方法;3、理解数据编码压缩和译码输出编码的实现。
二、实验要求实现哈夫曼编码和译码的生成算法。
三、实验步骤编写代码如下:#include#include#include#define MAXLEN 100typedef struct{int weight;int lchild;int rchild;int parent;char key;}htnode;typedef htnode hfmt[MAXLEN];int n;void inithfmt(hfmt t){int i;printf("\n");printf("--------------------------------------------------------\n"); printf("**********************输入区**********************\n");printf("\n请输入n=");scanf("%d",&n);getchar();for(i=0;i<2*n-1;i++){t[i].weight=0;t[i].lchild=-1;t[i].rchild=-1;t[i].parent=-1;}printf("\n");}void inputweight(hfmt t){int w;int i;char k;for(i=0;i<n;i++)< bdsfid="112" p=""></n;i++)<>{printf("请输入第%d个字符:",i+1);scanf("%c",&k);getchar();t[i].key=k;printf("请输入第%d个字符的权值:",i+1);scanf("%d",&w);getchar();t[i].weight=w;printf("\n");}}void selectmin(hfmt t,int i,int *p1,int *p2){long min1=999999;long min2=999999;int j;for(j=0;j<=i;j++)if(t[j].parent==-1)if(min1>t[j].weight){min1=t[j].weight;*p1=j;}for(j=0;j<=i;j++)if(t[j].parent==-1)if(min2>t[j].weight && j!=(*p1))//注意 j!=(*p1)) { min2=t[j].weight;*p2=j;}}void creathfmt(hfmt t){int i,p1,p2;inithfmt(t);inputweight(t);for(i=n;i<2*n-1;i++){selectmin(t,i-1,&p1,&p2);t[p1].parent=i;t[p2].parent=i;t[i].lchild=p1;t[i].rchild=p2;t[i].weight=t[p1].weight+t[p2].weight;}}void printhfmt(hfmt t){int i;printf("------------------------------------------------------------------\n");printf("**************哈夫曼编数结构:*********************\n"); printf("\t\t权重\t父母\t左孩子\t右孩子\t字符\t");for(i=0;i<2*n-1;i++){printf("\n");printf("\t\t%d\t%d\t%d\t%d\t%c",t[i].weight,t[i].parent,t[i].lc hild,t [i].rchild,t[i].key);}printf("\n------------------------------------------------------------------\n");printf("\n\n");}void hfmtpath(hfmt t,int i,int j){int a,b;a=i;b=j=t[i].parent;if(t[j].parent!=-1){i=j;hfmtpath(t,i,j);}if(t[b].lchild==a)printf("0");elseprintf("1");}void phfmnode(hfmt t){int i,j,a;printf("\n---------------------------------------------\n"); printf("******************哈夫曼编码**********************"); for(i=0;i<n;i++)< bdsfid="190" p=""></n;i++)<>{j=0;printf("\n");printf("\t\t%c\t",t[i].key,t[i].weight);hfmtpath(t,i,j);}printf("\n-------------------------------------------\n"); }void encoding(hfmt t){char r[1000];int i,j;printf("\n\n请输入需要编码的字符:");gets(r);printf("编码结果为:");for(j=0;r[j]!='\0';j++)for(i=0;i<n;i++)< bdsfid="207" p=""></n;i++)<>if(r[j]==t[i].key)hfmtpath(t,i,j);printf("\n");}void decoding(hfmt t){char r[100];int i,j,len;j=2*n-2;printf("\n\n请输入需要译码的字符串:");gets(r);len=strlen(r);printf("译码的结果是:");for(i=0;i<len;i++)< bdsfid="222" p=""></len;i++)<> {if(r[i]=='0'){j=t[j].lchild;if(t[j].lchild==-1){printf("%c",t[j].key);j=2*n-2;}}else if(r[i]=='1'){j=t[j].rchild;if(t[j].rchild==-1){printf("%c",t[j].key);j=2*n-2;}}printf("\n\n");}int main(){int i,j;hfmt ht;char flag;printf("\n----------------------------------------------\n");printf("*******************编码&&译码&&退出***************");printf("\n【1】编码\t【2】\t译码\t【0】退出");printf("\n您的选择:");flag=getchar();getchar();while(flag!='0'){if(flag=='1')encoding(ht);else if(flag=='2')decoding(ht);elseprintf("您的输入有误,请重新输入。
哈弗曼编译器实验报告
实习报告题目:哈弗曼编译码器班级:电信系通信工程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语言的过程中,出现了很多的语法和逻辑上的错误,所以用了很多的时间调试,修改错误。
哈夫曼编译码器课程设计报告(完整版)
XXX学院本科数据结构课程设计总结报告设计题目:实验一、哈夫曼编/译码器学生姓名:XXX系别:XXX专业:XXX班级:XXX学号:XXX指导教师:XXX XXX2012年6 月21日xxx学院课程设计任务书题目一、赫夫曼编译码器专业、班级xxx学号xxx 姓名xxx主要内容、基本要求、主要参考资料等:1. 主要内容利用哈夫曼编码进行信息通信可大大提高信道利用率,缩短信息传输时间,降低传输成本。
要求在发送端通过一个编码系统对待传数据预先编码;在接收端将传来的数据进行译码(复原)。
对于双工信道(既可以双向传输信息的信道),每端都需要一个完整的编/译码系统。
试为这样的信息收发站写一个哈夫曼的编/译码系统。
2. 基本要求系统应具有以下功能:(1)C:编码(Coding)。
对文件tobetrans中的正文进行编码,然后将结果存入文件codefile中,将以此建好的哈夫曼树存入文件HuffmanTree中(2)D:解码(Decoding)。
利用已建好的哈夫曼树将文件codefile中的代码进行译码,结果存入textfile中。
(3)P:打印代码文件(Print)。
将文件codefile以紧凑格式显示在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件codeprint中。
(4)T:打印哈夫曼树(Tree Printing)。
将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件treeprint中。
3. 参考资料:数据结构(C语言版)严蔚敏、吴伟民编著;数据结构标准教程胡超、闫宝玉编著完成期限:2012年6月21 日指导教师签名:课程负责人签名:2012年 6月 21 日一、设计题目(任选其一)实验一、哈夫曼编/译码器二、实验目的1巩固和加深对数据结构的理解,提高综合运用本课程所学知识的能力;2 深化对算法课程中基本概念、理论和方法的理解;3 巩固构造赫夫曼树的算法;4 设计试验用程序实验赫夫曼树的构造。
哈夫曼编译码器实验报告
哈夫曼编码/译码器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) 用下表给出的字符集和频度的实际统计数据建立赫夫曼树,并实现以下报文的编码和译码:“4.实现提示(1) 编码结果以文本方式存储在文件Codefile中。
(2) 用户界面可以设计为“菜单”方式:显示上述功能符号,再加上“Q”,表示退出运行Quit。
请用户键入一个选择功能符。
此功能执行完毕后再显示此菜单,直至某次用户选择了“Q”为止。
哈夫曼编码译码器实验报告
哈夫曼编码译码器实验报告实验名称:哈夫曼编码译码器实验一、实验目的: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的两个节点。
哈夫曼编译码器课程设计报告(完整版)
XXX学院本科数据结构课程设计总结报告设计题目:实验一、哈夫曼编/译码器学生:XXX系别:XXX专业:XXX班级:XXX学号:XXX指导教师:XXX XXX2012年6 月21日xxx学院课程设计任务书题目一、赫夫曼编译码器专业、班级xxx学号xxx xxx主要容、基本要求、主要参考资料等:1. 主要容利用哈夫曼编码进行信息通信可大大提高信道利用率,缩短信息传输时间,降低传输成本。
要求在发送端通过一个编码系统对待传数据预先编码;在接收端将传来的数据进行译码(复原)。
对于双工信道(既可以双向传输信息的信道),每端都需要一个完整的编/译码系统。
试为这样的信息收发站写一个哈夫曼的编/译码系统。
2. 基本要求系统应具有以下功能:(1)C:编码(Coding)。
对文件tobetrans中的正文进行编码,然后将结果存入文件codefile中,将以此建好的哈夫曼树存入文件HuffmanTree中(2)D:解码(Decoding)。
利用已建好的哈夫曼树将文件codefile中的代码进行译码,结果存入textfile中。
(3)P:打印代码文件(Print)。
将文件codefile以紧凑格式显示在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件codeprint中。
(4)T:打印哈夫曼树(Tree Printing)。
将已在存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件treeprint中。
3. 参考资料:数据结构(C语言版)严蔚敏、吴伟民编著;数据结构标准教程胡超、闫宝玉编著完成期限:2012年6月21 日指导教师签名:课程负责人签名:2012年 6月 21 日一、设计题目(任选其一)实验一、哈夫曼编/译码器二、实验目的1巩固和加深对数据结构的理解,提高综合运用本课程所学知识的能力;2 深化对算法课程中基本概念、理论和方法的理解;3 巩固构造赫夫曼树的算法;4 设计试验用程序实验赫夫曼树的构造。
哈夫曼编码译码器---课程设计报告.docx
目录目⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯ (2)1 程的目的和意⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯32 需求分析⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯43 概要⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯4 4⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯.85 分析和果⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯.11 6⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯127致⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯138附⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯13参考文献⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯..201课程设计目的与意义在当今信息爆炸时代,如何采用有效的数据压缩技术来节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视。
哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。
哈夫曼编码的应用很广泛,利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。
树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“ 1”的序列作为和各个对应的字符的编码,这就是哈夫曼编码。
通常我们把数据压缩的过程称为编码,解压缩的过程称为解码。
电报通信是传递文字的二进制码形式的字符串。
但在信息传递时,总希望总长度尽可能最短,即采用最短码。
作为计算机专业的学生,我们应该很好的掌握这门技术。
在课堂上,我们能过学到许多的理论知识,但我们很少有过自己动手实践的机会!课程设计就是为解决这个问题提供了一个平台。
在课程设计过程中,我们每个人选择一个课题,认真研究,根据课堂讲授内容,借助书本,自己动手实践。
这样不但有助于我们消化课堂所讲解的内容,还可以增强我们的独立思考能力和动手能力;通过编写实验代码和调试运行,我们可以逐步积累调试 C 程序的经验并逐渐培养我们的编程能力、用计算机解决实际问题的能力。
哈夫曼编码译码器实验报告
问题解析与解题方法问题分析:设计一个哈夫曼编码、译码系统。
对一个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类实现对哈夫曼树的创建,利用其成员函数完成哈夫曼编码译码的工作。
编码译码实验报告
一、实验目的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、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
中北大学数据结构课程设计说明书学生姓名: 郝晨栋学号: 1021010933软件学院学院:软件开发与测试: 专业哈夫曼编码/目题: 译码器康珺教指导师2011年12月20日目录1 问题描述.............................................................. 错误!未定义书签。
2 需求分析.............................................................. 错误!未定义书签。
3 概要设计 (1)3.1抽象数据类型定义 (1)3.2总体框图以及功能描述 (2)4 详细设计 (2)4.1数据类型的定义 (2)4.2主要模块的算法描述 (3)5 测试分析................................................................................................46 课程设计总结 (6)附录(源程序清单) (7)- 1 -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位。
但是在传送过程中,总希望长度能够尽可能的短,于是我们想采用长度不等的编码。
但是这种编码必须遵循:任何一个字符的编码都不是另一个字符编码的前缀。
对此软件的要求:能够正确的使得对于输入的字符进行编码以及译码,并且是的在译码过程中不会出错,同时能够将编码以及译码的结果正确的存入文件当中。
3 概要设计3.1抽象数据类型定义ADT BinaryTree{数据对象:D={ai|ai∈ElemSet,i=1,2,...,n, n≥0}数据关系:若D为空集,则称为空树。
若D仅为一个数据元素,则R为空集,否则R={H},H是如下的二元关系:(1)再D中存在唯一的称为根的数据元素root,它在关系H下无前驱。
(2)若D-{root}<>空集,则存在一个划分D1,D2,···,Dm(m>0)。
(3)对应于D-{root}的划分,H-{<root,X1},···,<root,Xm>} 有唯一的一个划分H1,H2,···,Hm(m>0)。
基本操作:InitTree(&T)操作结果:构造空树T。
DestroyTree(&T)初始条件:树T已存在。
操作结果:树T被销毁。
ClearTree(&T)初始条件:树T已存在。
操作结果:将树T清为空栈。
TreeEmpty(T)初始条件:树T已存在。
操作结果:若树T为空,则返回TRUE,否则FALSE。
TreeDepth(T)初始条件:树T已存在。
操作结果:返回T的深度。
Root(T)初始条件:树T已存在。
操作结果:返回树T的根。
- 1 -3.2总体框图以及功能描述4 详细设计4.1数据类型的定义(1)哈夫曼树节点类型struct hufmtreenode{ //哈弗曼树结点数据类型char data;float weight; //结点权值int parent,lchild,rchild; //父结点,左、右孩子结点};(2)哈夫曼树类型struct hufmtree{ //哈弗曼树数据类型hufmtreenode *node; //结点数组(根据n的值动态分配) int n; //叶子结点数};(3)哈夫曼编码数据类型struct Codetype{ //哈弗曼编码数据类型char *bits; //编码流数组,int start;// 编码实际在编码流数组里的开始位置}- 2 -4.2主要模块的算法描述(1)主函数:void main(){??牰湩晴尨哈夫曼编码译码系统 \n);tree=CreateHuffmanTreeFromSourceFile();//读取文件建立哈树tree=CreateHuffmanTreeByInput(); // 手动输入建立哈夫曼树HuffmanCode(tree); //打印字符集的哈夫曼编码对文本文件编码tree=Encoding(tree); //对代码文件译码 Decoding(tree); // }(2)构造哈夫曼树hufmtree* BuildHuffmanTree(hufmtree *tree){//构建叶子结点已初始化的哈夫曼树For(p=HT,i=1;i<=n;++i,++p,++w)*p={0,0,0,0};For(;i<=m;++i,++p)*p={0,0,0,0);For(i=n+1;i<=m;i++){Select(HT,i-1,s1,s2);HT[s1].parent=i; HT[s2].parent=i;HT[s1].parent=s1; HT[s1].parent=s2;- 3 -HT[i].weight=HT[s1].weight+HT[s2].weight; }}(3)利用哈夫曼编码算法哈夫曼编码HuffmanCode(tree){hc=(HuffmanCode)malloc((n+1*sizeof(char *))cd=(char *)malloc(n*sizeof(char));cd[n-1]=\for(c=i;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';HC[i]=(car *)malloc((n-start)*sizeof(char));Strcpy(HC[i],&cd[start]);}5 测试分析(1)打开源文件统计各字符及权值信息并存入data.txt文件中- 4 -(2)将统计出的权值信息进行哈夫曼编码(3)将编码内容存入CodeFile.txt文件中(4)将CodeFile.txt文件中的内容译码(5)成功译码把原字符信息存入DeCodeFile.txt文件中- 5 -(6)输入各字符及其权值(7)将各字符的权值信息进行哈夫曼编码(7)根据编码再进行译码工作6 课程设计总结课程设计是培养学生综合运用所学知识,发现,提出,分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程.随着科学技术发展的日新日异,当今计算机应用在生活中可以说得是无处不在。
因此作为二十一世纪的大学来说掌握计算机开发技术是十分重要的。
回顾起此次课程设计,至今我仍感慨颇多,的确,自从拿到题目到完成整个编程,从理论到实践,在整整一个星期的日子里,可以学到很多很多的的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。
通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有- 6 -理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。
在设计的过程中遇到问题,这毕竟独立做的,难免会遇到过各种各样的问题,同时在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固,比如说结构体……通过这次课程设计之后,一定把以前所学过的知识重新温故。
这次课程设计终于顺利完成了,在设计中遇到了很多编程问题,最后在谢老师的辛勤指导下,终于游逆而解。
同时,在李玉蓉老师的《软件工程导论》课上我学得到很多实用的知识,在次我表示感谢!同时,对给过我帮助的所有同学和各位指导老师再次表示忠心的感谢!附录(源程序清单)#include <stdio.h>#include <conio.h>#include <stdlib.h>#define MAXVAL 10000.0struct hufmtreenode{//哈弗曼树结点数据类型char data;double weight;//结点权值int parent,lchild,rchild;//父结点,左、右孩子结点};struct hufmtree{//哈弗曼树数据类型结点数组(根据hufmtreenode*node;// n的值动态分配) int n;// 叶子结点数};struct Codetype{//哈弗曼编码数据类型为为哈夫曼树中叶子结点的数目,编码的长n编码流数组, char *bits;//度不可能超过nint start;//编码实际在编码流数组里的开始位置- 7 -};void SortHufmtree(hufmtree *tree){//将哈夫曼树n个叶子结点由大到小排序int i,j,k;hufmtreenode temp;if (tree==NULL)return;for (i=0;i<tree->n;i++){k=i;for(j=i+1;j<tree->n;j++)if (tree->node[j].weight>tree->node[k].weight)k=j;if (k!=i){temp=tree->node[i];tree->node[i]=tree->node[k];tree->node[k]=temp;}}}Codetype* HuffmanCode(hufmtree *tree){//哈弗曼编码的生成int i,j,p,k; Codetype *code;if (tree==NULL)return NULL;code=(Codetype*)malloc(tree->n*sizeof(Codetype));for (i=0;i<tree->n;i++){printf(%c ,tree->node[i].data);//打印字符信息- 8 -code[i].bits=(char*)malloc(tree->n*sizeof(char));code[i].start=tree->n-1;j=i;p=tree->node[i].parent;while(p!=-1){if (tree->node[p].lchild==j)code[i].bits[code[i].start]='0';elsecode[i].bits[code[i].start]='1';code[i].start--;j=p;p=tree->node[p].parent;}打印字符编码 for (k=code[i].start+1;k<tree->n;k++)//printf(%c,code[i].bits[k]);printf(\);}return code;}hufmtree* BuildHuffmanTree(hufmtree *tree){//构建叶子结点已初始化的哈夫曼树//tree中所有叶子结点已初始化int i,j,p1,p2,m;float small1,small2;m=2*(tree->n)-1;for (i=tree->n;i<m;i++)// 初始化所有非叶子结点{tree->node[i].parent=-1;tree->node[i].lchild=-1;- 9 -tree->node[i].rchild=-1;tree->node[i].weight=0.0;}for (i=tree->n;i<m;i++)//构建哈夫曼树{small1=small2=MAXVAL;for (j=0;j<=i-1;j++){if (tree->node[j].parent==-1 &&tree->node[j].weight<=small1){small1=tree->node[j].weight;p1=j;}}for (j=0;j<=i-1;j++){if (tree->node[j].parent==-1 && tree->node[j].weight<=small2&& (j!=p1)){small2=tree->node[j].weight;p2=j;}}tree->node[p1].parent=tree->node[p2].parent=i;tree->node[i].weight=tree->node[p1].weight+tree->node[p2].weight; tree->node[i].lchild=p1;tree->node[i].rchild=p2;- 10 -}return tree;}hufmtree* CreateHuffmanTreeFromSourceFile(){//通过解析源文件建立哈夫曼树FILE *textfile,*datafile;char ch,sourcefilename[100];int i,j=0,n=0;float count[128]; // 用于统计字符在源文件中出现的次数,27表示26个英文字母和1个空格字符hufmtree *tree;// 打开一个源文件:\n); printf(\请输入源文件所在路径scanf(%s,sourcefilename);if ((textfile=fopen(sourcefilename,))==NULL){%s\n,sourcefilename); printf(\找不到文件return NULL;}for(i=0;i<128;i++)count[i]=0;对源文件中各字符的个数统计//ch=fgetc(textfile); while(!feof(textfile)){for(i=0;i<128;i++)if (ch==char(i)){count[i]++;- 11 -break;}ch=fgetc(textfile);}//将统计结果写入权值信息文件 data.txt中,并构建哈夫曼树datafile=fopen(:\\data.txt,w);for (i=0;i<128;i++)if (count[i]!=0)n++;fprintf(datafile,%d\n,n);tree=(hufmtree*)malloc(sizeof(hufmtree));tree->node=(hufmtreenode*)malloc((2*n-1)*sizeof(hufmtreenode)); tree->n=n;printf(\源文件的字符集及其权值信息如下: \n);for(i=0;i<128;i++)if (count[i]!=0){//fprintf(datafile,%c%f\n,char(i),count[i]);fprintf(datafile,%c %.0f\n,char(i),count[i]);printf(%c %.0f\n,char(i),count[i]);tree->node[j].data=char(i);tree->node[j].weight=count[i];tree->node[j].parent=-1;tree->node[j].lchild=-1;tree->node[j].rchild=-1;j++;- 12 -}SortHufmtree(tree);BuildHuffmanTree(tree);fclose(textfile);fclose(datafile);printf(\哈夫曼树建立完毕,已将权值信息保存至data.txt\n);return tree;}hufmtree* CreateHuffmanTreeByInput(){//通过用户输入建立哈夫曼树int n;hufmtree *tree;int i,m;FILE *datafile;tree=(hufmtree*)malloc(sizeof(hufmtree)); datafile=fopen(:\\data.txt,w);,同时进行哈夫曼树初data.txt //由用户输入字符与权值信息并将其写入始化牰湩晴尨请输入字符数:);scanf(%d,&n);if (n<=0){printf(\您的输入有误。