哈夫曼树及其操作-数据结构实验报告(2)

合集下载

数据结构(C语言版)实验报告(哈夫曼树)

数据结构(C语言版)实验报告(哈夫曼树)

《数据结构与算法》实验报告一、需求分析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)利用教科书例6-2中的数据调试程序。

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

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

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

请用户键入一个选择功能符。

此功能执行完毕后再显示此菜单,直至某次用户选择了“Q”为止。

(3)在程序的一次执行过程中,第一次执行I、D或C命令之后,哈夫曼树已经在内存了,不必再读入。

数据结构哈夫曼编码实验报告

数据结构哈夫曼编码实验报告

数据结构哈夫曼编码实验报告一、实验目的:通过哈夫曼编、译码算法的实现,巩固二叉树及哈夫曼树相关知识的理解掌握,训练学生运用所学知识,解决实际问题的能力。

二、实验内容:已知每一个字符出现的频率,构造哈夫曼树,并设计哈夫曼编码。

1、从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树。

2、打印每一个字符对应的哈夫曼编码。

3、对从终端读入的字符串进行编码,并显示编码结果。

4、对从终端读入的编码串进行译码,并显示译码结果。

三、实验方案设计:(对基本数据类型定义要有注释说明,解决问题的算法思想描述要完整,算法结构和程序功能模块之间的逻辑调用关系要清晰,关键算法要有相应的流程图,对算法的时间复杂度要进行分析)1、算法思想:(1)构造两个结构体分别存储结点的字符及权值、哈夫曼编码值:(2)读取前n个结点的字符及权值,建立哈夫曼树:(3)根据哈夫曼树求出哈夫曼编码:2、算法时间复杂度:(1)建立哈夫曼树时进行n到1次合并,产生n到1个新结点,并选出两个权值最小的根结点:O(n²);(2)根据哈夫曼树求出哈夫曼编码:O(n²)。

(3)读入电文,根据哈夫曼树译码:O(n)。

四、该程序的功能和运行结果:(至少有三种不同的测试数据和相应的运行结果,充分体现该程序的鲁棒性)1、输入字符A,B,C,D,E,F及其相应权值16、12、9、30、6、3。

2、输入字符F,E,N,G,H,U,I及其相应权值30、12、23、22、12、7、9。

3、输入字符A,B,C,D,E,F,G,H,I,G及其相应权值19、23、25、18、12、67、23、9、32、33。

哈夫曼树的建立及操作

哈夫曼树的建立及操作

哈夫曼树的建立及操作哈夫曼树是一种用于数据压缩的树形数据结构,可以有效地压缩数据并减小存储空间。

本文将介绍哈夫曼树的建立方法和相关操作。

一、哈夫曼树的建立方法:1.首先,我们需要统计给定数据中每个字符出现的频率。

频率越高的字符将被赋予较短的编码,从而实现数据的压缩。

可以使用一个字典或哈希表来记录字符及其频率。

2.创建一个包含所有字符频率的节点列表。

每个节点包含一个字符及其对应的频率。

3.排序节点列表,按照频率从小到大的顺序进行排序。

4.创建一个空的二叉树,并将频率最低的两个节点作为子节点,合并为一个新的节点。

新节点的频率为两个子节点的频率之和。

将这个新节点插入到节点列表中。

5.从节点列表中移除原先的两个子节点,插入新节点。

保持列表的有序性。

6.重复步骤4和5,直到节点列表中只剩下一个节点。

7.最后剩下的节点即为哈夫曼树的根节点。

二、哈夫曼树的操作:1.获取哈夫曼编码:根据哈夫曼树的结构,可以通过遍历树的路径来获取每个字符的编码。

左子树表示0,右子树表示1、从根节点出发,依次遍历所有叶子节点,记录下每个字符对应的路径即可得到编码。

2.数据压缩:将原始数据中的每个字符替换为对应的哈夫曼编码,从而实现数据压缩。

根据频率,越常见的字符编码越短,可以大幅减小数据存储的空间。

3.数据解压:使用相同的哈夫曼树,将压缩后的二进制编码解码为原始字符,从而还原数据。

4. 哈夫曼树的存储和传输:为了实现数据的压缩和解压缩,哈夫曼树需要存储和传输。

可以使用二进制格式存储树的结构和频率信息,并在解压缩时重新构建树。

还可以考虑使用霍夫曼编码的变种,如Adaptive Huffman Coding(自适应哈夫曼编码),使得树结构可以随着数据的变化进行更高效的编码和解码。

总结:哈夫曼树是一种用于数据压缩的树形数据结构,可以通过统计字符频率来生成树,并生成对应的编码。

通过编码,可以实现原始数据的高效压缩和解压缩。

在实际应用中,哈夫曼树被广泛应用于数据压缩,如文件压缩、图像压缩等。

哈夫曼树_实验报告

哈夫曼树_实验报告

一、实验目的1. 理解哈夫曼树的概念及其在数据结构中的应用。

2. 掌握哈夫曼树的构建方法。

3. 学习哈夫曼编码的原理及其在数据压缩中的应用。

4. 提高编程能力,实现哈夫曼树和哈夫曼编码的相关功能。

二、实验原理哈夫曼树(Huffman Tree)是一种带权路径长度最短的二叉树,又称为最优二叉树。

其构建方法如下:1. 将所有待编码的字符按照其出现的频率排序,频率低的排在前面。

2. 选择两个频率最低的字符,构造一棵新的二叉树,这两个字符分别作为左右子节点。

3. 计算新二叉树的频率,将新二叉树插入到排序后的字符列表中。

4. 重复步骤2和3,直到只剩下一个节点,这个节点即为哈夫曼树的根节点。

哈夫曼编码是一种基于哈夫曼树的编码方法,其原理如下:1. 从哈夫曼树的根节点开始,向左子树走表示0,向右子树走表示1。

2. 每个叶子节点对应一个字符,记录从根节点到叶子节点的路径,即为该字符的哈夫曼编码。

三、实验内容1. 实现哈夫曼树的构建。

2. 实现哈夫曼编码和译码功能。

3. 测试实验结果。

四、实验步骤1. 创建一个字符数组,包含待编码的字符。

2. 创建一个数组,用于存储每个字符的频率。

3. 对字符和频率进行排序。

4. 构建哈夫曼树,根据排序后的字符和频率,按照哈夫曼树的构建方法,将字符和频率插入到哈夫曼树中。

5. 实现哈夫曼编码功能,遍历哈夫曼树,记录从根节点到叶子节点的路径,即为每个字符的哈夫曼编码。

6. 实现哈夫曼译码功能,根据哈夫曼编码,从根节点开始,按照0和1的路径,找到对应的叶子节点,即为解码后的字符。

7. 测试实验结果,验证哈夫曼编码和译码的正确性。

五、实验结果与分析1. 构建哈夫曼树根据实验数据,构建的哈夫曼树如下:```A/ \B C/ \ / \D E F G```其中,A、B、C、D、E、F、G分别代表待编码的字符。

2. 哈夫曼编码根据哈夫曼树,得到以下字符的哈夫曼编码:- A: 00- B: 01- C: 10- D: 11- E: 100- F: 101- G: 1103. 哈夫曼译码根据哈夫曼编码,对以下编码进行译码:- 00101110111译码结果为:BACGACG4. 实验结果分析通过实验,验证了哈夫曼树和哈夫曼编码的正确性。

数据结构 哈夫曼编码实验报告

数据结构 哈夫曼编码实验报告

数据结构哈夫曼编码实验报告数据结构哈夫曼编码实验报告1. 实验目的本实验旨在通过实践理解哈夫曼编码的原理和实现方法,加深对数据结构中树的理解,并掌握使用Python编写哈夫曼编码的能力。

2. 实验原理哈夫曼编码是一种用于无损数据压缩的算法,通过根据字符出现的频率构建一棵哈夫曼树,并根据哈夫曼树对应的编码。

根据哈夫曼树的特性,频率较低的字符具有较长的编码,而频率较高的字符具有较短的编码,从而实现了对数据的有效压缩。

实现哈夫曼编码的主要步骤如下:1. 统计输入文本中每个字符的频率。

2. 根据字符频率构建哈夫曼树,其中树的叶子节点代表字符,内部节点代表字符频率的累加。

3. 遍历哈夫曼树,根据左右子树的关系对应的哈夫曼编码。

4. 使用的哈夫曼编码对输入文本进行编码。

5. 将编码后的二进制数据保存到文件,同时保存用于解码的哈夫曼树结构。

6. 对编码后的文件进行解码,还原原始文本。

3. 实验过程3.1 统计字符频率首先,我们需要统计输入文本中每个字符出现的频率。

可以使用Python中的字典数据结构来记录字符频率。

遍历输入文本的每个字符,将字符添加到字典中,并递增相应字符频率的计数。

```pythondef count_frequency(text):frequency = {}for char in text:if char in frequency:frequency[char] += 1else:frequency[char] = 1return frequency```3.2 构建哈夫曼树根据字符频率构建哈夫曼树是哈夫曼编码的核心步骤。

我们可以使用最小堆(优先队列)来高效地构建哈夫曼树。

首先,将每个字符频率作为节点存储到最小堆中。

然后,从最小堆中取出频率最小的两个节点,将它们作为子树构建成一个新的节点,新节点的频率等于两个子节点频率的和。

将新节点重新插入最小堆,并重复该过程,直到最小堆中只剩下一个节点,即哈夫曼树的根节点。

数据结构哈夫曼树的实验报告

数据结构哈夫曼树的实验报告

软件学院设计性实验报告理解哈夫曼树的特征及其应用;在对哈夫曼树进行理解的基础上,构造哈夫曼树,并用构造的哈夫曼树进行编码和译码;通过该实验,使学生对数据结构的应用有更深层次的理解。

二、实验仪器或设备学院提供公共机房,1台/学生微型计算机。

三、总体设计(设计原理、设计方案及流程等)1.问题描述:利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。

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

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

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

2.一个完整的系统应具有以下功能:1)初始化(Initialzation)。

从数据文件DataFile.dat中读入字符及每个字符的权值,建立哈夫曼树HuffTree;2)编码(EnCoding)。

用已建好的哈夫曼树,对文件ToBeTran.dat中的文本进行编码形成报文,将报文写在文件Code.txt中;3)译码(Decoding)。

利用已建好的哈夫曼树,对文件CodeFile.dat中的代码进行解码形成原文,结果存入文件Textfile.txt中;4)输出(Output): 输出DataFile.dat中出现的字符以及各字符出现的频度(或概率);输出ToBeTran.dat及其报文Code.txt;输出CodeFile.dat及其原文Textfile.txt;要求:所设计的系统应能在程序执行的过程中,根据实际情况(不同的输入)建立DataFile.dat、ToBeTran.dat和CodeFile.dat三个文件,以保证系统的通用性。

四、实验步骤(包括主要步骤、代码分析等)1)编写C语言程序#include<string.h>#include<malloc.h>#include<stdio.h>#include<iostream.h>#include<math.h>#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1typedef struct{char data;int weight;int parent,lchild,rchild;}HTNode,*HuffmanTree;typedef char **HuffmanCode;void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,char *d,int *w,int n) //构造哈弗曼函数HT,构造编码HC{void select(HuffmanTree HT,int n,int &s1,int &s2);int m,c,f,j;HuffmanTree p;int i,s1,s2,start;char *cd;m=2*n-1; //m为结点数,n为叶子数HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));p=HT;p++;for(i=1;i<=n;i++,p++) //将叶子的值输入HT中{p->data=d[i]; //={*d,*w,0,0,0};p->weight=w[i];p->parent=0;p->lchild=0;p->rchild=0;}for (i=n+1;i<=m;i++,p++) //={'#',0,0,0,0} {p->data='#';p->weight=0;p->parent=0;p->lchild=0;p->rchild=0;}s1=1;s2=2;for(i=n+1;i<=m;i++) //构建哈夫曼树{select(HT,i-1,s1,s2);HT[i].lchild=s1;HT[i].rchild=s2;HT[i].weight=HT[s1].weight+HT[s2].weight;HT[s1].parent=i;HT[s2].parent=i;}HC=(HuffmanCode)malloc((n+1)*sizeof(HuffmanTree)); //开辟空间,编码cd=(char *)malloc(n*sizeof(char));cd[n-1]='\0';for (i=1;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';elsecd[--start]='1';}HC[i]=(char*)malloc((n-start)*sizeof(char));strcpy(HC[i],&cd[start]);printf("%c的编码是:",HT[i]);puts(HC[i]);}free(cd);}void select(HuffmanTree HT,int n,int &s1,int &s2) //求最小两数{int i,t;s1=1;s2=2;while(HT[s1].parent!=0)s1++;while((HT[s2].parent!=0)||(s1==s2))s2++;/*for(i=1;i<=n;i++){if(HT[s1].weight>HT[i].weight&&HT[i].parent==0&&s2!=i)s1=i;}if(HT[s1].weight>HT[s2].weight){t=s1;s1=s2;s2=t;}for(i=1;i<=n;i++){if(s1!=i){if(HT[s2].weight>HT[i].weight&&HT[i].parent==0)s2=i;}}*/for(i=1;i<=n;i++){if(s1!=i&&i!=s2){if(HT[i].weight<HT[s1].weight&&HT[i].parent==0&&i!=s2) {if(HT[s1].weight<HT[s2].weight) s2=s1;s1=i;}elseif(HT[i].weight<HT[s2].weight&&HT[i].parent==0&&s1!=i) s2=i;}}}void translation(HuffmanTree HT,int num){char str[20];int i,t=num;printf("请输入由0或1组成的编码:");cin>>str;//t=HT; //t为树的指向各节点的指针for(i=0;i<(strlen(str));i++){if(str[i]=='0')t=HT[t].lchild;elseif(str[i]=='1')t=HT[t].rchild;else{printf("编码输入错误");break;}if(!(HT[t].lchild&&HT[t].rchild)){printf("%c",HT[t].data);t=num;}}printf("\n");}void main(){void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,char d[],int w[],int n);void translation(HuffmanTree HT,int num);HuffmanTree HT=NULL;HuffmanCode HC=NULL;char data,n,*p,*d;int *w,wei,i,num;printf("please intput character number:");scanf("%d",&n);d=(char*)malloc((n+1)*sizeof(char));w=(int *)malloc((n+1)*sizeof(int));printf("请输入Huffman树中的字符:\n");for(i=1;i<=n;i++){cin>>data;d[i]=data;}printf("请输入%d次位权\n:",n);for (i=1;i<=n;i++){cin>>wei;w[i]=wei;}num=2*n-1;HuffmanCoding(HT,HC,d,w,n);translation(HT,num);}2)程序分析此实验是构造哈夫曼树,求出哈夫曼编码然后输出构造哈夫曼树的算法操作时选出两棵根节点的权值最小的一颗树的左右子树,且置新树的根节点的权值为其左右子树上根节点的权值之和,根据哈夫曼树求出带权路径的算法操作是用递归调用的方法。

数据结构哈夫曼树实验报告

数据结构哈夫曼树实验报告

数据结构哈夫曼树实验报告一、实验内容本次实验的主要内容是哈夫曼树的创建和编码解码。

二、实验目的1. 理解并掌握哈夫曼树的创建过程;2. 理解并掌握哈夫曼编码的原理及其实现方法;3. 掌握哈夫曼树的基本操作,如求哈夫曼编码和哈夫曼解码等;4. 学习如何组织程序结构,运用C++语言实现哈夫曼编码和解码。

三、实验原理哈夫曼树的创建:哈夫曼树的创建过程就是一个不断合并权值最小的两个叶节点的过程。

具体步骤如下:1. 将所有节点加入一个无序的优先队列里;2. 不断地选出两个权值最小的节点,并将它们合并成为一个节点,其权值为这两个节点的权值之和;3. 将新的节点插入到队列中,并继续执行步骤2,直到队列中只剩下一棵树,这就是哈夫曼树。

哈夫曼编码:哈夫曼编码是一种无损压缩编码方式,它根据字符出现的频率来构建编码表,并通过编码表将字符转换成二进制位的字符串。

具体实现方法如下:1. 统计每个字符在文本中出现的频率,用一个数组记录下来;2. 根据字符出现的频率创建哈夫曼树;3. 从根节点开始遍历哈夫曼树,给左分支打上0的标记,给右分支打上1的标记。

遍历每个叶节点,将对应的字符及其对应的编码存储在一个映射表中;4. 遍历文本中的每个字符,查找其对应的编码表,并将编码字符串拼接起来,形成一个完整的编码字符串。

哈夫曼解码就是将编码字符串还原为原始文本的过程。

具体实现方法如下:1. 从根节点开始遍历哈夫曼树,按照编码字符串的位数依次访问左右分支。

如果遇到叶节点,就将对应的字符记录下来,并重新回到根节点继续遍历;2. 重复步骤1,直到编码字符串中的所有位数都被遍历完毕。

四、实验步骤1. 定义编码和解码的结构体以及相关变量;3. 遍历哈夫曼树,得到每个字符的哈夫曼编码,并将编码保存到映射表中;4. 将文本中的每个字符用其对应的哈夫曼编码替换掉,并将编码字符串写入到文件中;5. 使用哈夫曼编码重新构造文本,并将结果输出到文件中。

五、实验总结通过本次实验,我掌握了哈夫曼树的创建和哈夫曼编码的实现方法,也学会了如何用C++语言来组织程序结构,实现哈夫曼编码和解码。

哈夫曼树编码实训报告

哈夫曼树编码实训报告

一、实训目的本次实训旨在通过实际操作,让学生掌握哈夫曼树的基本概念、构建方法以及编码解码过程,加深对数据结构中树型结构在实际应用中的理解。

通过本次实训,学生能够:1. 理解哈夫曼树的基本概念和构建原理;2. 掌握哈夫曼树的编码和解码方法;3. 熟悉Java编程语言在哈夫曼树编码中的应用;4. 提高数据压缩和传输效率的认识。

二、实训内容1. 哈夫曼树的构建(1)创建叶子节点:根据给定的字符及其权值,创建叶子节点,并设置节点信息。

(2)构建哈夫曼树:通过合并权值最小的两个节点,不断构建新的节点,直到所有节点合并为一棵树。

2. 哈夫曼编码(1)遍历哈夫曼树:从根节点开始,按照左子树为0、右子树为1的规则,记录每个叶子节点的路径。

(2)生成编码:将遍历过程中记录的路径转换为二进制编码,即为哈夫曼编码。

3. 哈夫曼解码(1)读取编码:将编码字符串按照二进制位读取。

(2)遍历哈夫曼树:从根节点开始,根据读取的二进制位,在哈夫曼树中寻找对应的节点。

(3)输出解码结果:当找到叶子节点时,输出对应的字符,并继续读取编码字符串。

三、实训过程1. 准备工作(1)创建一个Java项目,命名为“HuffmanCoding”。

(2)在项目中创建以下三个类:- HuffmanNode:用于存储哈夫曼树的节点信息;- HuffmanTree:用于构建哈夫曼树、生成编码和解码;- Main:用于实现主函数,接收用户输入并调用HuffmanTree类进行编码和解码。

2. 编写代码(1)HuffmanNode类:```javapublic class HuffmanNode {private char data;private int weight;private HuffmanNode left;private HuffmanNode right;public HuffmanNode(char data, int weight) {this.data = data;this.weight = weight;}}```(2)HuffmanTree类:```javaimport java.util.PriorityQueue;public class HuffmanTree {private HuffmanNode root;public HuffmanNode buildHuffmanTree(char[] data, int[] weight) {// 创建优先队列,用于存储叶子节点PriorityQueue<HuffmanNode> queue = new PriorityQueue<>();for (int i = 0; i < data.length; i++) {HuffmanNode node = new HuffmanNode(data[i], weight[i]);queue.offer(node);}// 构建哈夫曼树while (queue.size() > 1) {HuffmanNode left = queue.poll();HuffmanNode right = queue.poll();HuffmanNode parent = new HuffmanNode('\0', left.weight + right.weight);parent.left = left;parent.right = right;queue.offer(parent);}root = queue.poll();return root;}public String generateCode(HuffmanNode node, String code) {if (node == null) {return "";}if (node.left == null && node.right == null) {return code;}generateCode(node.left, code + "0");generateCode(node.right, code + "1");return code;}public String decode(String code) {StringBuilder result = new StringBuilder();HuffmanNode node = root;for (int i = 0; i < code.length(); i++) {if (code.charAt(i) == '0') {node = node.left;} else {node = node.right;}if (node.left == null && node.right == null) { result.append(node.data);node = root;}}return result.toString();}}```(3)Main类:```javaimport java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.println("请输入字符串:");String input = scanner.nextLine();System.out.println("请输入字符及其权值(例如:a 2 b 3 c 5):"); String[] dataWeight = scanner.nextLine().split(" ");char[] data = new char[dataWeight.length / 2];int[] weight = new int[dataWeight.length / 2];for (int i = 0; i < dataWeight.length; i += 2) {data[i / 2] = dataWeight[i].charAt(0);weight[i / 2] = Integer.parseInt(dataWeight[i + 1]);}HuffmanTree huffmanTree = new HuffmanTree();HuffmanNode root = huffmanTree.buildHuffmanTree(data, weight); String code = huffmanTree.generateCode(root, "");System.out.println("编码结果:" + code);String decoded = huffmanTree.decode(code);System.out.println("解码结果:" + decoded);scanner.close();}}```3. 运行程序(1)编译并运行Main类,输入字符串和字符及其权值。

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

电子科技大学实验报告课程名称:数据结构与算法学生姓名:陈*浩学号:************* 点名序号: *** 指导教师:钱** 实验地点:基础实验大楼实验时间:2014-2015-2学期信息与软件工程学院实验报告(二)学生姓名:陈**浩学号:*************指导教师:钱**实验地点:科研教学楼A508实验时间:一、实验室名称:软件实验室二、实验项目名称:数据结构与算法—树三、实验学时:4四、实验原理:霍夫曼编码(Huffman Coding)是一种编码方式,是一种用于无损数据压缩的熵编码(权编码)算法。

1952年,David A. Huffman在麻省理工攻读博士时所发明的。

在计算机数据处理中,霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码,这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。

例如,在英文中,e的出现机率最高,而z的出现概率则最低。

当利用霍夫曼编码对一篇英文进行压缩时,e极有可能用一个比特来表示,而z则可能花去25个比特(不是26)。

用普通的表示方法时,每个英文字母均占用一个字节(byte),即8个比特。

二者相比,e使用了一般编码的1/8的长度,z则使用了3倍多。

倘若我们能实现对于英文中各个字母出现概率的较准确的估算,就可以大幅度提高无损压缩的比例。

霍夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。

所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。

树的路径长度是从树根到每一结点的路径长度之和,记为WPL=(W1*L1+W2*L2+W3*L3+...+Wn*Ln),N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,...n)。

可以证明霍夫曼树的WPL是最小的。

五、实验目的:本实验通过编程实现赫夫曼编码算法,使学生掌握赫夫曼树的构造方法,理解树这种数据结构的应用价值,并能熟练运用C语言的指针实现构建赫夫曼二叉树,培养理论联系实际和自主学习的能力,加强对数据结构的原理理解,提高编程水平。

六、实验内容:(1)实现输入的英文字符串输入,并设计算法分别统计不同字符在该字符串中出现的次数,字符要区分大小写;(2)实现赫夫曼树的构建算法;(3)遍历赫夫曼生成每个字符的二进制编码;(4)显示输出每个字母的编码。

七、实验器材(设备、元器件):PC机一台,装有C或C++语言集成开发环境。

八、数据结构与程序:/********************************************************************* *程序名称:哈夫曼树的相关操作 *** *程序内容:生成哈夫曼树及其编码表、对字符串进行编码等 *** *编写作者:陈家浩 *** *完成时间: ********************************************************************/#include <>#include <>#include <>#define MAXSIZE 10000char file_address[100]; eight, codesheet[i].pcode);printf("--------------------\n");destroy_codesheet( codesheet, leaves_num); eight = pht[i].weight;}for( i = 0; i < leaves_num; ++i ){cursor = leaves_num;cid = i;pid = pht[cid].parent;while( pid!= -1 ) child == cid)pch[--cursor] = '0'; arent;}len = leaves_num - cursor + 1;sheet[i].pcode = ( char * )malloc( len );if( !sheet[i].pcode ){printf("为节点%d的编码申请内存空间失败!", i);exit(0);}memset( sheet[i].pcode, 0, len );strncpy( sheet[i].pcode, &pch[cursor], strlen(&pch[cursor]) );}free(pch);return sheet;}eight = (i < n) weights[i] : 0;pht[i].lchild = -1;pht[i].rchild = -1;pht[i].parent = -1;}for( i = n; i < a; ++i ){select_mintree( pht, (i-1), &minA, &minB );pht[minA].parent = i;pht[minB].parent = i;pht[i].lchild = minA;pht[i].rchild = minB;pht[i].weight = pht[minA].weight + pht[minB].weight;}return pht;}arent == -1){if( pht[id].weight < maxa ){min2 = min1;min1 = id;maxa = pht[id].weight;}else if(pht[id].weight < maxb ){min2 = id;maxb = pht[id].weight;}}}*minA = min1;*minB = min2;return;}code);free(sheet);return;}//************************************************************* // ** **读取文本文件//************************************************************* int read_file(char file_address[100], char *message){int str_len; //字符串长度FILE * pFile = NULL;pFile = fopen( file_address, "r"); //打开文件if(!pFile){printf("打开文件失败!\n");exit(0);}else{printf("打开文件成功!\n");}memset(message, 0, MAXSIZE); //清除缓冲if( fgets( message, MAXSIZE, pFile ) == NULL){printf( "fgets error\n" );exit(0);}else{printf( "成功读取文件,内容如下:\n%s\n", message);}str_len = strlen(message);fclose(pFile);return str_len;}//*************************************************************// ** **统计字符出现的频率//*************************************************************int calc_freq(char text[], int **freq, char **dict, int n)//n为字符串长度{int i, k;int char_num = 0;int * chars; //不同种类的字符char * fre; //字符的出现频率int times[256] = {0};for(i = 0; i < n; ++i) //各个字符出现的频率times[text[i]]++;for(i = 0; i < 256; i++) //不同字符的个数if( times[i] > 0 )char_num++;chars = (int*)malloc(sizeof(int)*char_num);if( !chars ){printf("为频率数组分配空间失败!\n");exit(0);}fre = (char *)malloc(sizeof(char)*char_num);if( !fre ){printf("为字符数组分配空间失败!\n");exit(0);}k = 0;for(i = 0; i < 256; ++i){if( times[i] > 0 ){chars[k] = times[i];fre[k] = (char)i;k++;}}*freq = chars;*dict = fre;return char_num;//不同种类的字符个数}九、程序运行结果:一、手动输入信息二、从文件读取信息十、实验结论:本实验通过编程实现赫夫曼编码算法,在实验中掌握了赫夫曼树的构造方法,理解了树这种数据结构的应用价值,并且已经能够熟练运用指针实现构建赫夫曼二叉树,理论联系实际和自主学习的能力得到了培养,对数据结构的原理理解更加深刻,也提高了编程水平。

十一、总结及心得体会:1、虽然算法很多事现有的,可以用来做参考,不宜照抄。

2、使用指针存储信息之前应为其分配内存空间;3、scanf()函数读取到空格会自动停止,而gets()函数读取到回车即停止;4、需要读取单个字符时要考虑到键盘的缓冲区;5、双重指针的问题应特别注意;6、文件地址如果输入错误的解决方案没有考虑到;7、申请了内存的空间应该在程序结束时进行释放,否则可能造成空间浪费;8、应养成对代码进行注释的习惯,不久之后可能自己的程序自己都不知道是什么意思;9、实验是培养独立思考、作业的过程,要多思考,不应过多依赖他人。

相关文档
最新文档