数据结构大作业-哈夫曼编码实验报告

合集下载

《哈夫曼编码》实验报告

《哈夫曼编码》实验报告

《哈夫曼编码》实验报告《哈夫曼编码》实验报告一、实验目的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("您的输入有误,请重新输入。

哈夫曼编码的实验报告

哈夫曼编码的实验报告

哈夫曼编码的实验报告哈夫曼编码的实验报告一、引言信息的传输和存储是现代社会中不可或缺的一部分。

然而,随着信息量的不断增加,如何高效地表示和压缩信息成为了一个重要的问题。

在这个实验报告中,我们将探讨哈夫曼编码这一种高效的信息压缩算法。

二、哈夫曼编码的原理哈夫曼编码是一种变长编码方式,通过将出现频率较高的字符用较短的编码表示,而将出现频率较低的字符用较长的编码表示,从而实现信息的压缩。

它的核心思想是利用统计特性,将出现频率较高的字符用较短的编码表示,从而减少整体编码长度。

三、实验过程1. 统计字符频率在实验中,我们首先需要统计待压缩的文本中各个字符的出现频率。

通过遍历文本,我们可以得到每个字符出现的次数。

2. 构建哈夫曼树根据字符频率,我们可以构建哈夫曼树。

哈夫曼树是一种特殊的二叉树,其中每个叶子节点代表一个字符,并且叶子节点的权值与字符的频率相关。

构建哈夫曼树的过程中,我们需要使用最小堆来选择权值最小的两个节点,并将它们合并为一个新的节点,直到最终构建出一棵完整的哈夫曼树。

3. 生成编码表通过遍历哈夫曼树,我们可以得到每个字符对应的编码。

在遍历过程中,我们记录下每个字符的路径,左边走为0,右边走为1,从而生成编码表。

4. 进行编码和解码在得到编码表后,我们可以将原始文本进行编码,将每个字符替换为对应的编码。

编码后的文本长度将会大大减少。

为了验证编码的正确性,我们还需要进行解码,将编码后的文本还原为原始文本。

四、实验结果我们选取了一段英文文本作为实验数据,并进行了哈夫曼编码。

经过编码后,原始文本长度从1000个字符减少到了500个字符。

解码后的文本与原始文本完全一致,验证了哈夫曼编码的正确性。

五、讨论与总结哈夫曼编码作为一种高效的信息压缩算法,具有广泛的应用前景。

通过将出现频率较高的字符用较短的编码表示,哈夫曼编码可以在一定程度上减小信息的存储和传输成本。

然而,哈夫曼编码也存在一些局限性,例如对于出现频率相近的字符,编码长度可能会相差较大。

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

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

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

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

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。

数据结构大作业-哈夫曼编码实验报告

数据结构大作业-哈夫曼编码实验报告

一.构造过程①统计可知,字符串全长共59个字符,其中字符‘A’-‘F’的出现频数及对应概率(保留两位小数)如图所示:②将每个字符出现概率作为权重,则对于上述给定的6个权值{25,15,14,20,17,9},依次构造6棵只有根节点的二叉树,共同构成森林F;③在森林F中,选取权重最小和次小的两颗树,分别作为新二叉树的左子树、右子树,且该树根节点权值赋左右子树权值之和;④从森林F中删除已选中的两棵子树,把新得到的二叉树加入F 中;⑤重复③④,直到森林F中仅留下一棵树时,得到最终的哈夫曼树HF如图所示:⑥对上述哈夫曼树,将其树中的每个左分支赋0、右分支赋1,则从根结点开始到叶子结点,各分支路径分别得到对应的二进制串,即为给定的每个字符的哈夫曼编码。

二、代码实现源代码如下:#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>#include <string.h>#define N 6 //指定的编码字符数#define M (2 * N - 1) //HT结点数#define MAXWEIGHT 100typedef struct { //哈夫曼树的存储表示int weight;int parent, lchild, rchild;}HTNode;typedef HTNode HuffmanTree[M + 1];typedef char* HuffmanCode[N + 1]; //哈夫曼编码表void Select(HuffmanTree HT, int n, int& s1, int& s2);void CreateHuffmanTree(HuffmanTree& HT, int* w, int n); void CreateHuffmanCode(HuffmanTree HT, HuffmanCode& HC); void PrintHC(HuffmanCode HC, char ch[]);int main() {HuffmanTree HT;HuffmanCode HC;int w[N + 1];char ch[N + 1];printf("Please input %d characters & its weight(e.g. A 25):\n", N);for (int i = 1; i <= N; i++) {scanf("%c %d", &ch[i], &w[i]);getchar();}CreateHuffmanTree(HT, w, N);CreateHuffmanCode(HT, HC);PrintHC(HC, ch);return 0;}void Select(HuffmanTree HT, int n, int& s1, int& s2) { int i, min = 0, temp = MAXWEIGHT;for (i = 1; i <= n; i++) {if (!HT[i].parent) {if (temp > HT[i].weight) {temp = HT[i].weight;min = i; //最小值作为新树左子树}}}s1 = min;for (i = 1, min = 0, temp = MAXWEIGHT; i <= n; i++) { if ((!HT[i].parent) && i != s1) {if (temp > HT[i].weight) {temp = HT[i].weight;min = i; //次小值作为新树右子树}}}s2 = min;}void CreateHuffmanTree(HuffmanTree& HT, int* w, int n) { //创建哈夫曼树HTint i, s1, s2;if (n <= 1) return; //树为空或仅有根节点for (i = 1; i <= M; ++i) { //初始化HT[i].weight = w[i];HT[i].parent = 0;HT[i].lchild = 0;HT[i].rchild = 0;}for (i = n + 1; i <= M; ++i) { //创建新二叉树Select(HT, i - 1, s1, s2);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;}}void CreateHuffmanCode(HuffmanTree HT, HuffmanCode& HC) {int i, start, c, f;char cd[N];cd[N - 1] = '\0'; //编码结束符for (i = 1; i <= N; i++) { //对于第i个待编码字符即第i个带权值的叶子节点start = N - 1; //开始start指向结束符位置c = i;f = HT[i].parent; //f指向当前结点的双亲while (f) { //从叶上溯,到根节点跳出if (HT[f].lchild == c)cd[--start] = '0'; //左孩子elsecd[--start] = '1'; //右孩子c = f;f = HT[f].parent;}HC[i] = new char[N - start];strcpy(HC[i], &cd[start]); //复制结果到编码表,用于输出}}void PrintHC(HuffmanCode HC, char ch[]) { //打印哈夫曼编码表for (int i = 1; i <= N; i++)printf("\n%c: %s\n", ch[i], HC[i]);}三,输出各个字母的哈夫曼编码:四、算法分析1、哈夫曼编码是最优前缀编码:对包括N个字符的数据文件,分别以它们的出现概率构造哈夫曼树,利用该树对应的哈夫曼编码对报文进行编码,得到压缩后的最短二进制编码;2、算法自底而上地构造出对应最优编码的二叉树HT,它从n个叶子结点开始,识别出最低权重的两个对象,并将其合并;当合并时,新对象的权重设置为原两个对象权值之和,一共执行了|n| - 1次合并操作;3、是贪心算法:每次选择均为当下的最优选择,通过合并来构造最优树得到对应的哈夫曼编码;4、复杂度:①时间复杂度:有n个终端节点,构成的哈夫曼树总共有2n-1个节点,Select函数的时间复杂度为O(n),嵌套for循环,因此建立哈夫曼树的时间复杂度为O(n^2),创建哈弗曼编码表的时间复杂度为O(n^2);②空间复杂度:算法中临时占用存储空间大小为数组第0号空间,其耗费的空间复杂度为O(1)。

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

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

数据结构哈夫曼编码实验报告数据结构哈夫曼编码实验报告1·实验目的1·1 理解哈夫曼编码的基本原理1·2 掌握哈夫曼编码的算法实现方式1·3 熟悉哈夫曼编码在数据压缩中的应用2·实验背景2·1 哈夫曼编码的概念和作用2·2 哈夫曼编码的原理和算法2·3 哈夫曼编码在数据压缩中的应用3·实验环境3·1 硬件环境:计算机、CPU、内存等3·2 软件环境:编程语言、编译器等4·实验过程4·1 构建哈夫曼树4·1·1 哈夫曼树的构建原理4·1·2 哈夫曼树的构建算法4·2 哈夫曼编码4·2·1 哈夫曼编码的原理4·2·2 哈夫曼编码的算法4·3 实现数据压缩4·3·1 数据压缩的概念和作用4·3·2 哈夫曼编码在数据压缩中的应用方法5·实验结果5·1 构建的哈夫曼树示例图5·2 哈夫曼编码表5·3 数据压缩前后的文件大小对比5·4 数据解压缩的正确性验证6·实验分析6·1 哈夫曼编码的优点和应用场景分析6·2 数据压缩效果的评估和对比分析6·3 实验中遇到的问题和解决方法7·实验总结7·1 实验所获得的成果和收获7·2 实验中存在的不足和改进方向7·3 实验对于数据结构学习的启示和意义附件列表:1·实验所用的源代码文件2·实验中用到的测试数据文件注释:1·哈夫曼编码:一种用于数据压缩的编码方法,根据字符出现频率构建树形结构,实现高频字符用较短编码表示,低频字符用较长编码表示。

2·哈夫曼树:由哈夫曼编码算法构建的一种特殊的二叉树,用于表示字符编码的结构。

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

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

数据结构哈夫曼编码实验报告数据结构哈夫曼编码实验报告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:引言在日常生活中,信息传输已经成为了一个非常重要的环节。

通过对信息进行编码,可以有效地减少信息传输的开销和存储空间。

哈夫曼编码是一种常见的无损数据压缩方法,广泛应用于图像、音频和视频等领域。

本实验旨在通过实现哈夫曼编码算法,深入理解其工作原理,并对其性能进行评估。

2:实验目的本实验旨在:a:了解哈夫曼编码算法的基本原理;b:实现哈夫曼编码算法,并将其应用于对文本进行压缩;c:评估哈夫曼编码算法在不同文本数据上的性能。

二、实验内容1:哈夫曼编码原理介绍2:哈夫曼编码的实现思路a:构建哈夫曼树b:哈夫曼编码表c:对文本进行编码和解码3:实验环境介绍a:硬件环境b:软件环境4:实验步骤详解a:构建哈夫曼树的实现方法b:哈夫曼编码表的实现方法c:文本编码和解码的实现方法5:实验数据与结果分析a:不同文本数据的压缩结果对比 b:压缩性能的评估指标6:实验心得与建议a:实验过程中遇到的问题b:改进与优化方向三、实验结果与分析1:实验数据a:不同文本数据的大小与内容b:压缩率等性能指标数据2:实验结果分析a:不同文本数据对压缩效果的影响b:压缩率与文本数据的关系c:哈夫曼编码的运行时间分析四、结论根据实验结果和分析,可以得出以下结论:1:哈夫曼编码算法能够有效地减少文本数据的存储空间。

2:不同文本数据的压缩率存在差异,与文本的特性有关。

3:哈夫曼编码算法的运行时间与文本数据的长度成正比关系。

附件:1:实验源代码2:实验数据和结果法律名词及注释:1:无损数据压缩:指通过编码和解码过程,在不导致数据信息损失的情况下减少数据量。

2:哈夫曼编码:一种变长编码方式,通过更少的编码长度来表示频率较高的字符,从而达到减少编码长度的目的。

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

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

数据结构实验报告――实验五简单哈夫曼编/译码的设计与实现本实验的目的是通过对简单哈夫曼编/译码系统的设计与实现来熟练掌握树型结构在实际问题中的应用。

此实验可以作为综合实验,阶段性实验时可以选择其中的几个功能来设计和实现。

一、【问题描述】利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。

但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码,此实验即设计这样的一个简单编/码系统。

系统应该具有如下的几个功能:1、接收原始数据。

从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件nodedata.dat中。

2、编码。

利用已建好的哈夫曼树(如不在内存,则从文件nodedata.dat中读入),对文件中的正文进行编码,然后将结果存入文件code.dat中。

3、译码。

利用已建好的哈夫曼树将文件code.dat中的代码进行译码,结果存入文件textfile.dat中。

4、打印编码规则。

即字符与编码的一一对应关系。

二、【数据结构设计】1、构造哈夫曼树时使用静态链表作为哈夫曼树的存储。

在构造哈夫曼树时,设计一个结构体数组HuffNode保存哈夫曼树中各结点的信息,根据二叉树的性质可知,具有n个叶子结点的哈夫曼树共有2n-1个结点,所以数组HuffNode 的大小设置为2n-1,描述结点的数据类型为:typedef struct{int weight;//结点权值int parent;int lchild;int rchild;char inf;}HNodeType;2、求哈夫曼编码时使用一维结构数组HuffCode作为哈夫曼编码信息的存储。

求哈夫曼编码,实质上就是在已建立的哈夫曼树中,从叶子结点开始,沿结点的双亲链域回退到根结点,没回退一步,就走过了哈夫曼树的一个分支,从而得到一位哈夫曼码值,由于一个字符的哈夫曼编码是从根结点到相应叶子结点所经过的路径上各分支所组成的0、1序列,因此先得到的分支代码为所求编码的低位码,后得到的分支代码位所求编码的高位码,所以设计如下数据类型:#define MAXBIT 10typedef struct{int bit[MAXBIT];int start;}HcodeType;3、文件nodedata.dat、code.dat和textfile.dat。

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

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

数据结构哈夫曼编码实验报告【正文】1.实验目的本实验旨在研究哈夫曼编码的原理和实现方法,通过实验验证哈夫曼编码在数据压缩中的有效性,并分析其应用场景和优缺点。

2.实验原理2.1 哈夫曼编码哈夫曼编码是一种无损数据压缩算法,通过根据字符出现的频率构建一颗哈夫曼树,将频率较高的字符用较短的编码表示,频率较低的字符用较长的编码表示。

哈夫曼编码的编码表是唯一的,且能够实现前缀编码,即一个编码不是另一个编码的前缀。

2.2 构建哈夫曼树构建哈夫曼树的过程如下:1) 将每个字符及其频率作为一个节点,构建一个节点集合。

2) 每次从节点集合中选择出现频率最低的两个节点,构建一个新节点,并将这两个节点从集合中删除。

3) 将新节点加入节点集合。

4) 重复以上步骤,直到节点集合中只有一个节点,这个节点就是哈夫曼树的根节点。

2.3 编码过程根据哈夫曼树,对每个字符进行编码:1) 从根节点开始,根据左子树为0,右子树为1的规则,将编码依次加入编码表。

2) 对于每个字符,根据编码表获取其编码。

3) 将编码存储起来,得到最终的编码序列。

3.实验步骤3.1 数据读取与统计从输入文件中读取字符序列,并统计各个字符的频率。

3.2 构建哈夫曼树根据字符频率构建哈夫曼树。

3.3 构建编码表根据哈夫曼树,构建每个字符的编码表。

3.4 进行编码根据编码表,对输入的字符序列进行编码。

3.5 进行解码根据哈夫曼树,对编码后的序列进行解码。

4.实验结果与分析4.1 压缩率分析计算原始数据和压缩后数据的比值,分析压缩率。

4.2 编码效率分析测试编码过程所需时间,分析编码效率。

4.3 解码效率分析测试解码过程所需时间,分析解码效率。

4.4 应用场景分析分析哈夫曼编码在实际应用中的优势和适用场景。

5.结论通过本次实验,我们深入了解了哈夫曼编码的原理和实现方法,实践了哈夫曼编码的过程,并对其在数据压缩中的有效性进行了验证。

实验结果表明,哈夫曼编码能够实现较高的压缩率和较高的编解码效率。

数据结构哈夫曼编码实验报告-无删减范文

数据结构哈夫曼编码实验报告-无删减范文

数据结构哈夫曼编码实验报告数据结构哈夫曼编码实验报告实验背景哈夫曼编码是一种常用的数据压缩方法,通过使用变长编码来表示不同符号,将出现频率较高的符号用较短的编码表示,从而达到压缩数据的目的。

通过实现哈夫曼编码算法,我们能够更好地理解和掌握数据结构中的树形结构。

实验目的1. 理解哈夫曼编码的原理及实现过程。

2. 掌握数据结构中树的基本操作。

3. 进一步熟悉编程语言的使用。

实验过程1. 构建哈夫曼树首先,我们需要根据给定的字符频率表构建哈夫曼树。

哈夫曼树是一种特殊的二叉树,其叶子节点表示字符,而非叶子节点表示字符的编码。

构建哈夫曼树的过程如下:1. 根据给定的字符频率表,将每个字符视为一个节点,并按照频率从小到大的顺序排列。

2. 将频率最小的两个节点合并为一个新节点,并将其频率设置为两个节点的频率之和。

这个新节点成为新的子树的根节点。

3. 将新节点插入到原来的节点列表中,并继续按照频率从小到大的顺序排序。

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

2. 哈夫曼编码表在构建完哈夫曼树后,我们需要根据哈夫曼树每个字符的哈夫曼编码表。

哈夫曼编码表是一个字典,用于存储每个字符对应的编码。

哈夫曼编码表的过程如下:1. 从哈夫曼树的根节点出发,遍历整个树。

2. 在遍历的过程中,维护一个路径,用于记录到达每个字符节点的路径,0表示左子树,1表示右子树。

3. 当到达一个字符节点时,将路径上的编码存储到哈夫曼编码表中对应的字符键下。

3. 压缩数据有了哈夫曼编码表后,我们可以使用哈夫曼编码对数据进行压缩。

将原本以字符表示的数据,转换为使用哈夫曼编码表示的二进制数据。

压缩数据的过程如下:1. 将待压缩的数据转换为对应的哈夫曼编码,将所有的编码连接成一个字符串。

2. 将该字符串表示的二进制数据存储到文件中,同时需要保存哈夫曼编码表以便解压时使用。

实验结果通过实验,我们成功实现了哈夫曼编码的构建和使用。

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

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

数据结构哈夫曼编码实验报告
第一章实验目的
本实验旨在掌握哈夫曼编码的原理和实现方法,并通过编写代码实现一个简单的哈夫曼编码程序。

第二章实验内容
1.理解哈夫曼编码的基本概念和原理。

2.设计并实现一个哈夫曼编码的数据结构。

3.实现哈夫曼编码的压缩和解压缩功能。

4.通过实验验证哈夫曼编码的效果和压缩比。

第三章实验步骤
1.确定实验所需的编程语言和开发环境。

2.定义并实现哈夫曼编码的数据结构。

3.实现哈夫曼编码的压缩和解压缩算法。

4.设计实验样例数据,进行测试和验证。

5.分析实验结果,计算压缩比。

第四章实验结果与分析
1.实验样例数据:________提供一段文本,统计字符出现的频率,并进行哈夫曼编码。

2.实验结果:________展示压缩后的编码结果,计算压缩比。

3.分析:________分析实验结果,讨论哈夫曼编码的效果和优劣。

第五章实验总结与感想
本次实验深入了解了哈夫曼编码的原理和实现方法,通过编写代码实现哈夫曼编码的压缩和解压缩功能。

实验结果表明,哈夫曼编码能够有效地减小数据的存储空间,提高了数据传输的效率。

第六章本文档涉及附件
本实验报告所涉及到的附件包括:________
1.实验代码文件:________.c
2.实验样例数据文件:________.txt
第七章法律名词及注释
1.哈夫曼编码:________一种用于无损数据压缩的编码方法,通过对频率高的字符赋予较短的编码,对频率低的字符赋予较长的编码,从而实现压缩数据的目的。

哈夫曼实验报告

哈夫曼实验报告

一、实验目的1. 理解哈夫曼编码的基本原理和重要性。

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

3. 熟悉哈夫曼编码和译码的实现过程。

4. 分析哈夫曼编码在数据压缩中的应用效果。

二、实验原理哈夫曼编码是一种基于字符频率的编码方法,它利用字符出现的频率来构造一棵最优二叉树(哈夫曼树),并根据该树生成字符的编码。

在哈夫曼树中,频率越高的字符对应的编码越短,频率越低的字符对应的编码越长。

这样,对于出现频率较高的字符,编码后的数据长度更短,从而实现数据压缩。

三、实验内容1. 构建哈夫曼树:- 统计待编码数据中每个字符出现的频率。

- 根据字符频率构建哈夫曼树,其中频率高的字符作为叶子节点,频率低的字符作为内部节点。

- 重复上述步骤,直到树中只剩下一个节点,即为哈夫曼树的根节点。

2. 生成哈夫曼编码:- 从哈夫曼树的根节点开始,对每个节点进行遍历,根据遍历方向(左子树为0,右子树为1)为字符分配编码。

- 将生成的编码存储在编码表中。

3. 编码和译码:- 使用生成的编码表对原始数据进行编码,将编码后的数据存储在文件中。

- 从文件中读取编码后的数据,根据编码表进行译码,恢复原始数据。

四、实验步骤1. 编写代码实现哈夫曼树的构建:- 定义节点结构体,包含字符、频率、左子树、右子树等属性。

- 实现构建哈夫曼树的核心算法,包括节点合并、插入等操作。

2. 实现编码和译码功能:- 根据哈夫曼树生成编码表。

- 编写编码函数,根据编码表对数据进行编码。

- 编写译码函数,根据编码表对数据进行译码。

3. 测试实验效果:- 选择一段文本数据,使用实验代码进行编码和译码。

- 比较编码前后数据的长度,分析哈夫曼编码的压缩效果。

五、实验结果与分析1. 哈夫曼树构建:- 成功构建了哈夫曼树,树中节点按照字符频率从高到低排列。

2. 哈夫曼编码:- 成功生成编码表,字符与编码的对应关系符合哈夫曼编码原理。

3. 编码与译码:- 成功实现编码和译码功能,编码后的数据长度明显缩短,译码结果与原始数据完全一致。

数据结构 哈夫曼编码实验报告(2023版)

数据结构 哈夫曼编码实验报告(2023版)

数据结构哈夫曼编码实验报告实验目的:本实验旨在了解和实现哈夫曼编码算法,通过将字符转换为对应的哈夫曼编码来实现数据的压缩和解压缩。

一、引言1.1 背景介绍哈夫曼编码是一种基于字符出现频率的编码方法,通过使用不等长编码来表示不同字符,从而实现数据的高效压缩。

该编码方法在通信、存储等领域有着广泛的应用。

1.2 目标本实验的目标是实现哈夫曼编码算法,通过对给定文本进行编码和解码,验证哈夫曼编码的有效性和可靠性。

二、实验过程2.1 数据结构设计在实现哈夫曼编码算法时,我们需要设计合适的数据结构来存储字符和对应的编码。

常用的数据结构包括树和哈希表。

我们将使用二叉树作为数据结构来表示字符的编码。

2.2 构建哈夫曼树哈夫曼树是由给定字符集合构建而成的最优二叉树。

构建哈夫曼树的过程分为两步:首先根据字符出现频率构建叶子节点,然后通过合并叶子节点和父节点构造哈夫曼树。

2.3 哈夫曼编码表根据构建好的哈夫曼树,我们可以对应的哈夫曼编码表。

哈夫曼编码表由字符和对应的编码组成,可以用于字符的编码和解码。

2.4 文本压缩利用的哈夫曼编码表,我们可以对给定的文本进行压缩。

将文本中的字符逐个替换为对应的哈夫曼编码,从而实现数据的压缩。

2.5 文本解压缩对压缩后的数据进行解压缩时,我们需要利用的哈夫曼编码表,将哈夫曼编码逐个替换为对应的字符,从而还原出原始的文本数据。

三、实验结果我们使用不同长度、不同频率的文本进行了实验。

实验结果表明,哈夫曼编码在数据压缩方面有着显著的效果,可以大大减小数据存储和传输的开销。

四、实验总结通过本实验,我们深入理解了哈夫曼编码算法的原理和实现过程,掌握了数据的压缩和解压缩技术。

哈夫曼编码作为一种经典的数据压缩算法,具有重要的理论意义和实际应用价值。

附件:本文档附带哈夫曼编码实验的源代码和实验数据。

法律名词及注释:在本文档中,涉及的法律名词和注释如下:1.哈夫曼编码:一种数据压缩算法,用于将字符转换为可变长度的编码。

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

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

数据结构哈夫曼编码实验报告数据结构实验报告----------1-实验目的----------本实验的目的是通过实现哈夫曼编码算法,加深对数据结构中树和堆的理解,以及掌握相关的编程技巧。

2-实验内容----------2-1 算法简介----------哈夫曼编码是一种无损压缩算法,通过根据字符出现的频率构建一颗二叉树,并将出现频率较高的字符编码为较短的二进制串,进而实现压缩的目的。

在本实验中,我们需要实现以下功能:●构建哈夫曼树●字符编码表●对给定的字符串进行编码●对给定的二进制串进行解码●实现压缩和解压缩功能2-2 数据结构----------在实现哈夫曼编码算法时,我们需要使用以下数据结构:●链表:用于存储字符出现的频率及对应的字符●堆:用于构建哈夫曼树●树:用于存储哈夫曼编码树●散列表或映射:用于存储字符的编码2-3 算法步骤----------1-统计字符的出现频率,并构建频率链表2-根据频率链表构建哈夫曼树3-字符的编码表4-对给定的字符串进行编码5-对给定的二进制串进行解码6-实现压缩和解压缩功能3-实验实现----------3-1 数据结构的设计----------在本实验中,我们将使用以下数据结构:●链表节点结构体:用于存储字符和频率●链表结构体:用于存储链表节点的头指针●堆节点结构体:用于存储字符和频率,并维护堆的结构●堆结构体:用于存储堆的根节点●树节点结构体:用于存储字符和编码,并维护哈夫曼树的结构●树结构体:用于存储哈夫曼树的根节点●散列表结构体:用于存储字符和对应的编码3-2 算法实现----------1-统计字符的出现频率并构建频率链表:遍历给定的字符串,统计字符的频率,并将字符频率按从小到大的顺序插入到频率链表中。

2-根据频率链表构建哈夫曼树:将频率链表的节点插入到堆中,并按照堆的定义调整堆的结构,直到堆中只有一个节点。

3-字符的编码表:遍历哈夫曼树,递归构造字符的编码表。

哈夫曼编码 实验报告

哈夫曼编码 实验报告

哈夫曼编码实验报告哈夫曼编码实验报告一、引言哈夫曼编码是一种用于数据压缩的算法,由大卫·哈夫曼于1952年提出。

它通过将出现频率高的字符用较短的编码表示,从而实现对数据的高效压缩。

本实验旨在通过实际操作和数据分析,深入了解哈夫曼编码的原理和应用。

二、实验目的1. 掌握哈夫曼编码的基本原理和算法;2. 实现哈夫曼编码的压缩和解压缩功能;3. 分析不同数据集上的压缩效果,并对结果进行评估。

三、实验过程1. 数据集准备本实验选取了三个不同的数据集,分别是一篇英文文章、一段中文文本和一段二进制数据。

这三个数据集具有不同的特点,可以用来评估哈夫曼编码在不同类型数据上的压缩效果。

2. 哈夫曼编码实现在实验中,我们使用了Python编程语言来实现哈夫曼编码的压缩和解压缩功能。

首先,我们需要统计数据集中各个字符的出现频率,并构建哈夫曼树。

然后,根据哈夫曼树生成每个字符的编码表,将原始数据转换为对应的编码。

最后,将编码后的数据存储为二进制文件,并记录编码表和原始数据的长度。

3. 压缩效果评估对于每个数据集,我们比较了原始数据和压缩后数据的大小差异,并计算了压缩比和压缩率。

压缩比是指压缩后数据的大小与原始数据大小的比值,压缩率是指压缩比乘以100%。

通过对比不同数据集上的压缩效果,我们可以评估哈夫曼编码在不同类型数据上的性能。

四、实验结果与分析1. 英文文章数据集对于一篇英文文章,经过哈夫曼编码压缩后,我们发现压缩比为0.6,即压缩后的数据只有原始数据的60%大小。

这说明哈夫曼编码在英文文本上具有较好的压缩效果。

原因在于英文文章中存在大量的重复字符,而哈夫曼编码能够利用字符的出现频率进行编码,从而减少数据的存储空间。

2. 中文文本数据集对于一段中文文本,我们发现哈夫曼编码的压缩效果不如在英文文章上的效果明显。

压缩比为0.8,即压缩后的数据只有原始数据的80%大小。

这是因为中文文本中的字符种类较多,并且出现频率相对均匀,导致哈夫曼编码的优势减弱。

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

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

数据结构实验报告哈夫曼编码一、需求分析:哈夫曼编码可以进行求取最优二叉树,以及进行编码等实际问题,当利用哈夫曼树做前缀编码,有效的节约存储密码的时间。

二、概要设计:首先定义一个哈弗曼树结构体,哈夫曼编码数组之后,编写输入函数(包括存到文件的部分),哈弗曼构造函数(从文件中调用构造),求哈夫曼编码函数,输出函数(打印出哈夫曼编码)等。

三、详细设计:下为程序源代码:#include<stdio.h>#include<stdlib.h>#include<string.h>#include<ctype.h>#define Maxsize 100typedef struct{char data;double weight;int parent;int lchild;int rchild;}HTNode;HTNode ht[Maxsize];typedef struct{char cd[Maxsize];int start;}HCode;HCode hcd[Maxsize];void Initialization(char str[], double w[], int n);void getn(char str[], double w[], int *n);void writehfmTree(int n);void Encoding(int n);void ReadhfmTree(void);void Decoding(int n);void TreePrint(int i);void Menu(char *ch);int getnumber(char *ch, int repeat);void Initialization(char str[], double w[], int n) //构造哈弗曼树{int i,k,lnode,rnode;double min1, min2;for(i=0; i<n; i++){ht[i].data = str[i];ht[i].weight = w[i];}for(i=0; i<2*n-1; i++)ht[i].lchild = ht[i].parent = ht[i].rchild = -1;for(i=n; i<2*n-1; i++){min1=min2=32767;lnode=rnode=-1;for(k=0; k<=i-1; k++){if(ht[k].parent == -1){if(ht[k].weight < min1){min2 = min1;rnode = lnode;min1 = ht[k].weight;lnode = k;}else if(ht[k].weight < min2){min2 = ht[k].weight;rnode = k;}}}ht[i].weight = ht[lnode].weight + ht[rnode].weight;ht[i].lchild = lnode;ht[i].rchild = rnode;ht[lnode].parent = i;ht[rnode].parent = i;}writehfmTree(n);}void getn(char str[], double w[], int *n){int i;FILE *fp;if((fp=fopen("ToBeTran", "w"))==NULL){printf("Can not open the file\n");exit(0);}printf("请输入字符集:");gets(str);gets(str);*n = strlen(str);for(i=0; i<*n; i++){printf("请输入%d个权值:", i+1);scanf("%lf",&w[i]);}for(i=0; i<*n; i++)fprintf(fp, "%c", str[i]);fclose(fp);}void writehfmTree(int n) //把哈弗曼树存入hrmTree文件中{int i;FILE *fp;if((fp=fopen("hfmTree","w"))==NULL){printf("Can not open the file\n");exit(0);}for(i=0; i<n; i++){fputc(ht[i].data, fp);fprintf(fp, "%.2f", ht[i].weight);}fprintf(fp,"\n");printf("存在文件hfmTree中的哈弗曼树形式为:\n");for(i=0; i<n; i++){putchar(ht[i].data);putchar('-');printf("%.2f ", ht[i].weight);}printf("\n文件hfmTree写入成功!\n");fclose(fp);}void Encoding(int n) //哈弗曼编码,并存于文件CodeFile中{int i, j, k, f, c;HCode hc;FILE *fp, *fp1;char text[Maxsize];ReadhfmTree();if((fp1=fopen("ToBeTran","r"))==NULL){printf("Can not open the file\n");exit(0);}fgets(text, Maxsize, fp1);printf("要进行编码的字符串是:\n");puts(text);fclose(fp1);if((fp=fopen("CodeFile","w"))==NULL){printf("Can not open the file\n");exit(0);}for(i=0; i<n; i++){hc.start = n;c=i;f=ht[i].parent;while(f!=-1){if(ht[f].lchild == c)hc.cd[hc.start--]='0';elsehc.cd[hc.start--]='1';c=f;f=ht[f].parent;}hc.start++;hcd[i]=hc;}i=0;while(text[i]!='\0'){j=0;while(text[i]!=ht[j].data){j++;}for(k=hcd[j].start; k<=n; k++){fprintf(fp, "%c", hcd[j].cd[k]);}fputc(' ', fp);i++;}printf("编码结果如下:\n");i=0;while(text[i]!='\0'){j=0;while(text[i]!=ht[j].data){j++;}for(k=hcd[j].start; k<=n; k++){printf("%c", hcd[j].cd[k]);}printf(" ");i++;}printf("\n文件CodeFile写入成功!\n");fclose(fp);}void ReadhfmTree(void) //从内存中读入哈弗曼树,或从文件hfmTree文件中读取哈弗曼树{FILE *fp;char str[Maxsize];double w[Maxsize];int i=0, n;if(sizeof(ht)!=0)printf("内存中已存有哈弗曼树!\n");else{printf("内存中哈弗曼树不存在,从文件中读取数据重新构造哈弗曼树!\n");if((fp=fopen("hfmTree","r"))==NULL){printf("Can not open the file\n");exit(0);}do{fscanf(fp, "%c", &str[i]);fscanf(fp, "%lf", &w[i]);i++;}while(str[i]!='\n');n = i-2;Initialization(str, w, n);fclose(fp);}}void Decoding(int n)//从文件CodeFile中读入哈弗曼树编码,进行译码,将译码结果存入TextFile文件中{int i=0, j=0, k=0, l=0, num;char *text[Maxsize], str[Maxsize][Maxsize];FILE *fp, *fp1;if((fp=fopen("CodeFile","r"))==NULL){printf("Can not open the file “CodeFile”\n");exit(0);}if((fp1=fopen("TextFile","w"))==NULL){printf("Can not open the file “TextFile”\n");exit(0);}for(i=0; i<Maxsize; i++)text[i] = str[i];i=0;while(fscanf(fp, "%s", text[i])==1)i++;num = i;for(i=0; i<num; i++){l=0;j=0;k=hcd[l].start;while(1){if(hcd[l].cd[k]!=text[i][j]){l++;j=0;k=hcd[l].start;}else{j++;k++;}if(j==(signed)strlen(text[i]) && k==n+1)break;}fprintf(fp1, "%c", ht[l].data);}printf("译码结果如下:\n");for(i=0; i<num; i++){l=0;j=0;k=hcd[l].start;while(1){if(hcd[l].cd[k]!=text[i][j]){l++;j=0;k=hcd[l].start;}else{j++;k++;}if(j==(signed)strlen(text[i]) && k==n+1)break;}printf("%c", ht[l].data);}printf("\n文件TextFile写入成功!\n");fclose(fp);fclose(fp1);}void Print(void)//将文件CodeFile以紧凑个数显示在终端上,每行50个代码。

哈夫曼编码实验报告

哈夫曼编码实验报告

哈夫曼编码实验报告数据结构实验报告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)选出权值最小的两个结点,其权值和作为其根结点的权值,最小的结点作为左子树,次小的作为右子树,不断将两棵子树合并为一棵树。

数据结构实验哈夫曼树及哈夫曼编码c语言

数据结构实验哈夫曼树及哈夫曼编码c语言

数据结构实验报告:哈夫曼树及哈夫曼编码一、实验目的1. 理解哈夫曼树及哈夫曼编码的概念和原理;2. 掌握C语言中哈夫曼树及哈夫曼编码的实现方法;3. 分析和讨论哈夫曼编码在实际应用中的优势和不足。

二、实验内容和步骤1. 哈夫曼树的构建1.1 通过C语言实现哈夫曼树的构建算法;1.2 输入一组权值,按哈夫曼树构建规则生成哈夫曼树;1.3 输出生成的哈夫曼树结构,并进行可视化展示。

2. 哈夫曼编码的实现2.1 设计哈夫曼编码的实现算法;2.2 对指定字符集进行编码,生成哈夫曼编码表;2.3 对给定字符串进行哈夫曼编码,并输出编码结果。

三、实验过程及结果1. 哈夫曼树的构建在C语言中,通过定义结构体和递归算法实现了哈夫曼树的构建。

根据输入的权值,依次选择权值最小的两个节点构建新的父节点,直至构建完成整棵哈夫曼树。

通过调试和可视化展示,确认了程序正确实现了哈夫曼树的构建。

2. 哈夫曼编码的实现经过分析和设计,利用哈夫曼树的特点实现了哈夫曼编码的算法。

根据生成的哈夫曼树,递归地生成字符对应的哈夫曼编码,并输出编码结果。

对指定的字符串进行了编码测试,验证了哈夫曼编码的正确性和有效性。

四、实验结果分析1. 哈夫曼编码在数据传输和存储中具有较高的压缩效率和可靠性,能够有效减少数据传输量和存储空间;2. 哈夫曼树及哈夫曼编码在通信领域、数据压缩和加密等方面有着广泛的应用和重要意义;3. 在实际应用中,哈夫曼编码的构建和解码算法需要较大的时间和空间复杂度,对于大规模数据的处理存在一定的局限性。

五、实验总结通过本次实验,深入理解了哈夫曼树及哈夫曼编码的理论知识,并掌握了C语言中实现哈夫曼树及哈夫曼编码的方法。

对哈夫曼编码在实际应用中的优势和局限性有了更深入的认识,这对今后的学习和工作有着积极的意义。

六、参考文献1. 《数据结构(C语言版)》,严蔚敏赵现军著,清华大学出版社,2012年;2. 《算法导论》,Thomas H. Cormen 等著,机械工业出版社,2006年。

数据结构试验报告-哈弗曼编码

数据结构试验报告-哈弗曼编码

实验报告:哈弗曼编码班级:姓名:学号:一、需求分析:1.利用哈弗曼编码进行通信时可以大大提高信息利用率,缩短信息传输时间,降低传输成本;2.哈夫曼编码对终端“明文”文件中的正文进行编码,然后将结果存入“密文”中。

同时也可以将“密文”进行译码,提高了信息的安全性;3.输入输出的要求:要求在输入和输出端都有一个完整的编/译码系统,用户按照提示内容从键盘输入命令,系统根据用户输入的命令在保证界面友好的前提下输出用户所需要的信息,并按要求保存文件,以便保存备份信息;4.测试数据;1)令叶子节点的个数为4,权值集合为:w[]={5,7,11,6};2)令叶子节点的个数为8,权值集合为:w[]={7, 5, 2, 4, 14, 23, 3, 11};二、概要设计:1.定义哈弗曼编码数据结构类型:ADT Huffman{数据对象:D={ ai |ai 属于字符数集,i=1,2,3,4……n n>=0}数据关系:R1={<ai-1, ai >| ai-1, ai ∈D,ai-1< ai ,i=2……n}基本操作:void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n)初始条件:HT,HC,w,n等都存在操作结果:将w数组内的数都转化到HT内的哈夫曼树内,然后将哈夫曼树内的数据转化到HC这个代码中,全部转化成只有0和1这两个二进制数的一串译码。

void Select(HuffmanTree &HT, int s, int &s1, int &s2)初始条件:HT这个哈夫曼树存在操作结果:通过该个函数,将原来的哈夫曼树扩展成为有权值,双亲,左孩子,右孩子等四个值得哈夫曼树。

并用s1,s2两个字将双亲为0中权值最小的两个的下标返回到HuffmanCoding函数中,改变哈夫曼树。

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

一.构造过程
①统计可知,字符串全长共59个字符,其中字符‘A’-‘F’的出现频数及对应概率(保留两位小数)如图所示:
②将每个字符出现概率作为权重,则对于上述给定的6个权值{25,15,14,20,17,9},依次构造6棵只有根节点的二叉树,共同构成森林F;
③在森林F中,选取权重最小和次小的两颗树,分别作为新二叉树的左子树、右子树,且该树根节点权值赋左右子树权值之和;
④从森林F中删除已选中的两棵子树,把新得到的二叉树加入F 中;
⑤重复③④,直到森林F中仅留下一棵树时,得到最终的哈夫曼树HF如图所示:
⑥对上述哈夫曼树,将其树中的每个左分支赋0、右分支赋1,则从根结点开始到叶子结点,各分支路径分别得到对应的二进制串,即为给定的每个字符的哈夫曼编码。

二、代码实现
源代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 6 //指定的编码字符数
#define M (2 * N - 1) //HT结点数
#define MAXWEIGHT 100
typedef struct { //哈夫曼树的存储表示
int weight;
int parent, lchild, rchild;
}HTNode;
typedef HTNode HuffmanTree[M + 1];
typedef char* HuffmanCode[N + 1]; //哈夫曼编码表
void Select(HuffmanTree HT, int n, int& s1, int& s2);
void CreateHuffmanTree(HuffmanTree& HT, int* w, int n); void CreateHuffmanCode(HuffmanTree HT, HuffmanCode& HC); void PrintHC(HuffmanCode HC, char ch[]);
int main() {
HuffmanTree HT;
HuffmanCode HC;
int w[N + 1];
char ch[N + 1];
printf("Please input %d characters & its weight(e.g. A 25):\n", N);
for (int i = 1; i <= N; i++) {
scanf("%c %d", &ch[i], &w[i]);
getchar();
}
CreateHuffmanTree(HT, w, N);
CreateHuffmanCode(HT, HC);
PrintHC(HC, ch);
return 0;
}
void Select(HuffmanTree HT, int n, int& s1, int& s2) { int i, min = 0, temp = MAXWEIGHT;
for (i = 1; i <= n; i++) {
if (!HT[i].parent) {
if (temp > HT[i].weight) {
temp = HT[i].weight;
min = i; //最小值作为新树左子树
}
}
}
s1 = min;
for (i = 1, min = 0, temp = MAXWEIGHT; i <= n; i++) { if ((!HT[i].parent) && i != s1) {
if (temp > HT[i].weight) {
temp = HT[i].weight;
min = i; //次小值作为新树右子树
}
}
}
s2 = min;
}
void CreateHuffmanTree(HuffmanTree& HT, int* w, int n) { //创建哈夫曼树HT
int i, s1, s2;
if (n <= 1) return; //树为空或仅有根节点
for (i = 1; i <= M; ++i) { //初始化
HT[i].weight = w[i];
HT[i].parent = 0;
HT[i].lchild = 0;
HT[i].rchild = 0;
}
for (i = n + 1; i <= M; ++i) { //创建新二叉树
Select(HT, i - 1, s1, s2);
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;
}
}
void CreateHuffmanCode(HuffmanTree HT, HuffmanCode& HC) {
int i, start, c, f;
char cd[N];
cd[N - 1] = '\0'; //编码结束符
for (i = 1; i <= N; i++) { //对于第i个待编码字符即第i个带权值的叶子节点
start = N - 1; //开始start指向结束符位置
c = i;
f = HT[i].parent; //f指向当前结点的双亲
while (f) { //从叶上溯,到根节点跳出
if (HT[f].lchild == c)
cd[--start] = '0'; //左孩子
else
cd[--start] = '1'; //右孩子
c = f;
f = HT[f].parent;
}
HC[i] = new char[N - start];
strcpy(HC[i], &cd[start]); //复制结果到编码表,用于输出}
}
void PrintHC(HuffmanCode HC, char ch[]) { //打印哈夫曼编码表for (int i = 1; i <= N; i++)
printf("\n%c: %s\n", ch[i], HC[i]);
}
三,输出各个字母的哈夫曼编码:
四、算法分析
1、哈夫曼编码是最优前缀编码:对包括N个字符的数据文件,分别以它们的出现概率构造哈夫曼树,利用该树对应的哈夫曼编码对报文进行编码,得到压缩后的最短二进制编码;
2、算法自底而上地构造出对应最优编码的二叉树HT,它从n个叶子结点开始,识别出最低权重的两个对象,并将其合并;当合并时,新对象的权重设置为原两个对象权值之和,一共执行了|n| - 1次合并操作;
3、是贪心算法:每次选择均为当下的最优选择,通过合并来构造最优树得到对应的哈夫曼编码;
4、复杂度:
①时间复杂度:有n个终端节点,构成的哈夫曼树总共有2n-1个节点,Select函数的时间复杂度为O(n),嵌套for循环,因此建立哈夫曼树的时间复杂度为O(n^2),创建哈弗曼编码表的时间复杂度为O(n^2);
②空间复杂度:算法中临时占用存储空间大小为数组第0号空间,其耗费的空间复杂度为O(1)。

相关文档
最新文档