头歌赫夫曼树及其应用实践
数据结构实验实验报告Huffman赫夫曼编码及应用

实验报告课程名称:数据结构实验名称:赫夫曼编码及应用院(系):计算机与通信工程学院专业班级:计算机科学与技术姓名:学号:指导教师:2020 年 5 月12 日一、实验目的掌握赫夫曼树和赫夫曼编码的基本思想和算法的程序实现。
二、实验内容及要求1、任务描述a.提取原始文件中的数据(包括中文、英文或其他字符),根据数据出现的频率为权重,b.构建Huffman编码表;c.根据Huffman编码表对原始文件进行加密,得到加密文件并保存到硬盘上;d.将加密文件进行解密,得到解码文件并保存点硬盘上;e.比对原始文件和解码文件的一致性,得出是否一致的结论。
2、主要数据类型与变量a.对Huffman树采用双亲孩子表示法,便于在加密与解密时的操作。
typedef struct Huffman* HuffmanTree;struct Huffman{unsigned int weight; //权值unsigned int p, l, r;//双亲,左右孩子};b.对文本中出现的所有字符用链表进行存储。
typedef struct statistics* List;struct statistics {char str; //存储此字符int Frequency; //出现的频率(次数)string FinalNum; //Huffman编码struct statistics* Next;};3、算法或程序模块对读取到的文本进行逐字符遍历,统计每个字符出现的次数,并记录在创建的链表中。
借助Huffman树结构,生成结构数组,先存储在文本中出现的所有字符以及它们出现的频率(即权值),当作树的叶子节点。
再根据叶子节点生成它们的双亲节点,同样存入Huffman树中。
在完成对Huffman树的创建与存储之后,根据树节点的双亲节点域以及孩子节点域,生成每个字符的Huffman编码,并存入该字符所在链表节点的FinalNum域。
哈夫曼树的应用与实现

/*哈夫曼树的应用和实现(1)根据输入的字符和相应的权值建立哈夫曼树,并输出已建的相应内容作为检查;(2)用哈夫曼树实现前缀编码,并输出各字符的编码串;(3)输入一组二进制报文,进行译码,并输出译文。
*/#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#define N 1000 //定义结点数最大值#define M 2*N-1#define maxval 10000.0 //定义float的最大值typedef struct //定义哈夫曼树类型{char data;float weight;int lchild,rchild,parent;}hufmtree;hufmtree tree[M];typedef struct //定义哈夫曼树编码类型{char bits[N];int start;char data;}codetype;codetype code[N];void HUFFMAN(hufmtree t[]);void HUFFMANCODE(codetype code[],hufmtree t[]);void HUFFMANDECODE(codetype code[],hufmtree t[]);void OUTTREE(hufmtree t[]);static int n,m; //定义静态全局变量n储存需要的结点数//m为构建哈夫曼树后的总结点数//菜单的建立void main(){int x,flag1=0;printf("\t\t\t哈夫曼树的应用和实现\n");while(1){printf("——————————————————————————————————\n");printf("菜单:1 建立哈夫曼树 2 哈夫曼树编码 3 输入电文译码0 退出使用\n");printf("——————————————————————————————————\n");printf("请选择操作:\n");scanf("%d",&x);switch(x){case 1:HUFFMAN(tree);break;case 2:HUFFMANCODE(code,tree);break;case 3:HUFFMANDECODE(code,tree);break;case 0:flag1=1; //输入号为0时使flag1=1break;default:printf("输入的选择有误!请重新输入!\n");break;}if(flag1) break; //表明选择了退出操作故跳出循环}printf("Thank You!\n");}//哈夫曼树的构建void HUFFMAN(hufmtree t[]){int i,j,p1,p2;char ch;float small1,small2,f;printf("请输入叶子结点数:\n");scanf("%d",&n);m=2*n-1;for(i=0;i<m;i++) //初始化哈夫曼树{tree[i].parent=0;tree[i].lchild=0;tree[i].rchild=0;tree[i].data='0';tree[i].weight=0.0;}for(i=0;i<n;i++){getchar(); //getchar 吃掉回车printf("请输入第%d个结点的字符和权重(空格隔开):\n",i);scanf("%c %f",&ch,&f); //输入结点字符和权重tree[i].data=ch;tree[i].weight=f;}for(i=n;i<m;i++) //进行n-1次合并产生n-1个新结点{p1=0;p2=0; //预置最小次小权值的下标为0small1=maxval; //预置最小次小权值为float型最大值small2=maxval;for(j=i-1;j>=0;j--) //循环找出最小、次小权值和下标if(tree[j].parent==0)if((tree[j].weight-small1)<0.0001) //float精度,当两者之差小于0.0001认为相等{small2=small1; //小于当前最小权值,更新最小权值和次小权值以及位置small1=tree[j].weight;p2=p1;p1=j;}elseif((tree[j].weight-small2)<0.0001) //小于当前次小权值,更新次小权值和位置{small2=tree[j].weight;p2=j;}tree[p1].parent=i; //修改最小、次小结点的双亲为新生成的结点tree[p2].parent=i;tree[i].lchild=p1; //新结点的左右孩子指向最小次小值的结点tree[i].rchild=p2;tree[i].weight=tree[p1].weight+tree[p2].weight; //新生成结点权值为两小之和}OUTTREE(tree);}//哈夫曼编码void HUFFMANCODE(codetype code[],hufmtree t[]){int i,j,c,p;codetype cd; //定义缓冲变量for(i=0;i<n;i++){cd.start=n;c=i; //从叶子节点出发线上回溯p=tree[c].parent; //p指向c的双亲结点cd.data=tree[c].data;while(p!=0){cd.start--;if(tree[p].lchild==c) //判断是否是左孩子,是编码为‘0’cd.bits[cd.start]='0';else //否则编码为‘1’cd.bits[cd.start]='1';c=p; //更新p的双亲结点,进行下一次循环p=tree[c].parent;}code[i]=cd; //把一个字符的编码赋给相应code[i]}printf("输出每个字符的哈夫曼编码:\n"); //输出每个字符的哈弗曼编码for(i=0;i<n;i++){printf("%c: ",code[i].data);for(j=code[i].start;j<n;j++)printf("%c ",code[i].bits[j]);printf("\n");}}//哈夫曼译码void HUFFMANDECODE(codetype code[],hufmtree t[]){int i,c=0;char b[100]; //定义字符数组储存输入的字符串int endflag='#'; //电文结束标志位#i=m-1; //从根结点开始向下搜索printf("请输入电文:\n");printf("注意:电文结束标志为#\n");getchar();gets(b);while(b[c]!=endflag) //遍历输入的字符串{if(b[c]=='0') //编码为0 走向左孩子i=tree[i].lchild;elsei=tree[i].rchild; //编码为1 走向右孩子if(tree[i].lchild==0) //结点为叶子结点{putchar(code[i].data); //输出译码值i=m-1; //回到根结点}c++ ;}printf("\n");if((tree[i].lchild!=0)&&(b[c]!='#')) //电文读完尚未到叶子结点printf("输入的电文有错误!\n");}//打印哈夫曼树void OUTTREE(hufmtree t[]){int i;printf("\n\n");printf("结点数据权重双亲左孩子右孩子\n");for(i=0;i<m;i++){printf("%d",i);printf(" %c",tree[i].data);printf(" %f",tree[i].weight);printf(" %d",tree[i].parent);printf(" %d",tree[i].lchild);printf(" %d\n",tree[i].rchild);}}。
哈夫曼编码树实现及应用场景讲解

哈夫曼编码树实现及应用场景讲解哈夫曼编码树(Huffman coding tree)是一种被广泛应用于数据压缩的算法,它通过利用输出频率不同的字符分配不同长度的编码,从而实现数据的高效压缩。
本文将介绍哈夫曼编码树的实现方法,并探讨其在实际应用中的场景。
一、哈夫曼编码树的实现方法1.1 字符频率统计在构建哈夫曼编码树之前,我们首先需要对目标数据中的字符进行频率统计。
可以通过遍历数据集,并利用哈希表或数组记录每个字符出现的次数。
例如,对于字符串"Hello World!",我们可以统计出每个字符的频率为:H: 1, e: 1, l: 3, o: 2, W: 1, r: 1, d: 1, !: 1。
1.2 构建哈夫曼编码树构建哈夫曼编码树的过程分为两个步骤:创建叶节点集合和合并节点。
创建叶节点集合:根据字符频率统计结果,创建一个包含所有字符的叶节点集合。
每个叶节点包含字符、频率以及指向其左右子节点的指针(若存在子节点)。
合并节点:从叶节点集合中选取频率最低的两个节点,合并成一个新节点,该新节点的频率等于这两个节点的频率之和。
将合并后的节点插入叶节点集合中,并从集合中移除被合并的节点。
重复该操作,直到叶节点集合只剩下一个节点,即为哈夫曼编码树的根节点。
1.3 构建哈夫曼编码表遍历哈夫曼编码树,沿着根节点到叶节点的路径,给每个字符赋予对应的二进制编码。
例如,对于字符串"Hello World!",哈夫曼编码表如下:H: 00e: 01l: 10o: 11W: 010r: 011d: 100!: 101二、哈夫曼编码树的应用场景2.1 数据压缩哈夫曼编码树最常见的应用场景之一是数据压缩。
通过使用较短的二进制编码表示频率较高的字符,以及使用较长的二进制编码表示频率较低的字符,可以大幅减小数据的存储空间。
这种压缩方法被广泛应用于文本、图像和音频等多媒体数据的传输和存储。
举个例子,在一个文件中,字符'E'出现频率最高,通过哈夫曼编码树,我们可以将其编码为一个比特(如0),而字符'Z'出现频率最低,可以将其编码为多个比特(如11001),从而实现数据的高效压缩。
数据结构哈夫曼树的构造及其应用课程设计实验报告

目录第一章哈夫曼树的基本术语 (1)1.1路径和路径长度 (1)1.2树的带权路径长度 (1)1.3哈夫曼树的定义 (1)第二章哈夫曼树的构造 (2)2.1哈夫曼树的构造 (2)第三章哈夫曼树的存储结构及哈夫曼算法的实现 (3)3.1哈夫曼树的存储结构 (3)3.2 哈夫曼算法的简要描述 (3)第四章哈夫曼树的应用 (5)4.1哈夫曼编码 (5)4.2求哈夫曼编码的算法 (5)4.21思想方法 (5)4.22字符集编码的存储结构及其算法描述 (6)4.3哈夫曼树和编码程序实现: (6)4.4程序运行结果: (9)心得体会 (10)参考文献 (10)第一章哈夫曼树的基本术语1.1路径和路径长度在一棵树中,从一个结点往下可以达到的孩子或子孙结点之间的通路,称为路径。
通路中分支的数目称为路径长度。
若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。
1.2结点的权及带权路径长度若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。
结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。
1.2树的带权路径长度树的带权路径长度(Weighted Path Length of Tree):也称为树的代价,定义为树中所有叶结点的带权路径长度之和,通常记为:其中:n表示叶子结点的数目wi和li分别表示叶结点ki的权值和根到结点ki之间的路径长度。
1.3哈夫曼树的定义在权为wl ,w2,…,wn的n个叶子所构成的所有二叉树中,带权路径长度最小(即代价最小)的二叉树称为最优二叉树或哈夫曼树。
[例]给定4个叶子结点a,b,c和d,分别带权7,5,2和4。
构造如下图所示的三棵二叉树(还有许多棵),它们的带权路径长度分别为:(a)WPL=7*2+5*2+2*2+4*2=36(b)WPL=7*3+5*3+2*1+4*2=4(c)WPL=7*1+5*2+2*3+4*3=35其中(c)树的WPL最小,可以验证,它就是哈夫曼树。
哈夫曼树的实际应用

哈夫曼树的实际应用
哈夫曼树(Huffman Tree)是一种重要的数据结构,它在信息编码和压缩、数据传输和存储、图像处理等领域有广泛应用。
1. 数据压缩:哈夫曼树是一种无损压缩的方法,能够有效地减小数据的存储空间。
在进行数据压缩时,可以使用哈夫曼树构建字符编码表,将出现频率较高的字符用较短的编码表示,而出现频率较低的字符用较长的编码表示,从而减小数据的存储空间。
2. 文件压缩:在文件压缩领域,哈夫曼树被广泛应用于压缩算法中。
通过构建哈夫曼树,可以根据字符出现的频率来生成不同长度的编码,从而减小文件的大小。
常见的文件压缩格式如ZIP、GZIP等都使用了哈夫曼树。
3. 图像压缩:在图像处理中,哈夫曼树被用于图像压缩算法中。
通过将图像中的像素值映射为不同长度的编码,可以减小图像的存储空间,提高图像传输和存储的效率。
常见的图像压缩格式如JPEG、PNG等都使用了哈夫曼树。
4. 文件传输:在数据传输中,哈夫曼树被用于数据压缩和传输。
通过对数据进行压缩,可以减小数据的传输时间和带宽占用。
在传输过程中,接收方可以通过哈夫曼树解码接收到的数据。
5. 数据加密:在数据加密中,哈夫曼树可以用于生成密钥,从而实现数据的加密和解密。
通过将字符映射为不同长度的编码,可以实
现对数据的加密和解密操作。
哈夫曼树在信息编码和压缩、数据传输和存储、图像处理等领域有广泛应用,能够有效地减小数据的存储空间、提高数据传输效率、实现数据加密等功能。
6.6 赫夫曼树及其应用++

6.6 赫夫曼树及其应用赫夫曼(Huffman)树,又称最优树,是一类带权路径长度最短的树,有着广泛的应用。
本节先讨论最优二叉树。
6.6.1 最优二叉树(赫夫曼树)首先给出路径和路径长度的概念。
从树中一个结点到另一个结点之间的分支构成这两个结点之间的路径,路径上的分支数目称做路径长度。
树的路径长度是从树根到每一结点的路径长度之和。
6.2.1节中定义的完全二叉树就是这种路径长度最短的二叉树。
若将上述概念推广到一般情况,考虑带权的结点。
结点的带权路径长度为从该结点到树根之间的路径长度与结点上权的乘积。
树的带权路径长度为树中所有叶子结点的带权路径长度之和,通常记作WPL =∑=nk k k l w 1。
(注:W K 为第K 个叶子结点的权,L K 为第K 个叶子结点到根结点的路径长度。
所谓带权路径长度就是结点的权与该结点路径长度的乘积。
)假设有n 个权值{w 1,w 2,…,w n },试构造一棵有n 个叶子结点的二叉树,每个叶子结点带权为w i ,则其中带权路径长度WPL 最小的二叉树称做最优二叉树或赫夫曼树。
例如,图6.22中的3棵二叉树,都有4个叶子结点a 、b 、c 、d ,分别带权7、5、2、4,它们的带权路径长度分别为(a)WPL =7×2+5×2+2×2+4×2=36(b)WPL =7×3+5×3+2×1+4×2=46(c)WPL =7×1+5×2+2×3+4×3=35其中以(c)树的为最小。
可以验证,它恰为赫夫曼树,即其带权路径长度在所有带权为7、5、2、4的4个叶子结点的二叉树中居最小。
(将权比较大的叶子结点尽量靠近根结点!)在解某些判定问题时,利用赫夫曼树可以得到最佳判定算法。
例如,要编制一个将百分制转换成五级分制的程序。
显然,此程序很简单,只要利用条件语句便可完成。
赫夫曼树的作用及应用

赫夫曼树的作用及应用1.引言在计算机科学中,赫夫曼树是一种重要的数据结构,它被广泛应用于数据压缩、存储和解码等领域。
赫夫曼树以其高效的特点,成为了压缩算法中的重要组成部分。
本文将介绍赫夫曼树的作用以及它在不同应用领域中的具体应用。
2.赫夫曼树的基本概念赫夫曼树,也称为最优二叉树,是一种树形结构。
它的构建基于赫夫曼编码算法,该算法通过将频率较高的字符编码为较短的二进制码,从而实现数据的高效压缩。
3.赫夫曼树的构建赫夫曼树的构建过程包括以下几个步骤:1.统计字符频率:遍历待压缩的数据,统计各个字符出现的频率。
2.构建叶子节点:将每个字符及其频率作为叶子节点,构成初始的二叉树。
3.合并节点:选择两个频率最低的节点合并,并将合并后的节点作为新的节点插入二叉树中。
4.重复合并:重复执行合并节点的操作,直到只剩下一个节点,即赫夫曼树的根节点。
4.赫夫曼树的作用赫夫曼树在数据压缩和解压缩中发挥着重要作用,主要体现在以下几个方面:4.1数据压缩赫夫曼树通过赫夫曼编码将频率较高的字符编码为较短的二进制码,从而实现数据的高效压缩。
压缩后的数据体积大大减小,方便存储和传输。
4.2文件压缩赫夫曼树可用于对文件进行压缩,将文件中的字符编码为对应的二进制码,从而减小文件的大小。
在文件传输和存储中,减小文件的大小可以提高传输速度和节省存储空间。
4.3图像压缩赫夫曼树也可用于图像数据的压缩,通过对图像中的像素进行编码,减小图像的大小。
图像压缩在图像处理和存储中起到重要的作用,减小图像的大小可以提高图像的传输速度和存储效率。
4.4视频压缩赫夫曼树在视频编码中也有重要应用,通过对视频帧中的数据进行编码,实现对视频的压缩。
视频压缩可以降低视频的带宽占用率,提高视频传输的效率和稳定性。
5.赫夫曼树的应用举例除了数据压缩方面,赫夫曼树在其他领域也有广泛应用,以下列举几个常见的应用场景:5.1字符串匹配赫夫曼树可以用于字符串匹配算法中,通过构建赫夫曼树和相关数据结构,提高字符串匹配的效率和准确性。
哈夫曼树的应用-哈夫曼树代码实现

哈夫曼树的应用-哈夫曼树代码实现一、简介哈夫曼树又称为最优树。
1、路径和路径长度在一棵树中,从一个结点往下可以达到的孩子或子孙结点之间的通路,称为路径。
通路中分支的数目称为路径长度。
若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。
2、结点的权及带权路径长度若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。
结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。
3、树的带权路径长度树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL二、哈夫曼树的应用1、哈夫曼编码在数据通信中,需要将传送的文字转换成二进制的字符串,用0,1码的不同排列来表示字符。
例如,需传送的报文为“AFTER DATA EAR ARE ART AREA”,这里用到的字符集为“A,E,R,T,F,D”,各字母出现的次数为{8,4,5,3,1,1}。
现要求为这些字母设计编码。
要区别6个字母,最简单的二进制编码方式是等长编码,固定采用3位二进制,可分别用000、001、010、011、100、101对“A,E,R,T,F,D”进行编码发送,当对方接收报文时再按照三位一分进行译码。
显然编码的长度取决报文中不同字符的个数。
若报文中可能出现26个不同字符,则固定编码长度为5。
然而,传送报文时总是希望总长度尽可能短。
在实际应用中,各个字符的出现频度或使用次数是不相同的,如A、B、C的使用频率远远高于X、Y、Z,自然会想到设计编码时,让使用频率高的用短码,使用频率低的用长码,以优化整个报文编码。
为使不等长编码为前缀编码(即要求一个字符的编码不能是另一个字符编码的前缀),可用字符集中的每个字符作为叶子结点生成一棵编码二叉树,为了获得传送报文的最短长度,可将每个字符的出现频率作为字符结点的权值赋予该结点上,求出此树的最小带权路径长度就等于求出了传送报文的最短长度。
因此,求传送报文的最短长度问题转化为求由字符集中的所有字符作为叶子结点,由字符出现频率作为其权值所产生的哈夫曼树的问题。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
头歌赫夫曼树及其应用实践
头歌赫夫曼树是一种特殊的哈夫曼树算法,它在图像压缩、数据传输、数据存储等方面得到广泛应用。
本文将介绍头歌赫夫曼树的原理、构
建方法以及应用实践。
一、头歌赫夫曼树的原理
头歌赫夫曼树是由美国计算机科学家J. L. Bentley和A. J. Heineman
在1986年所提出的算法。
该算法的核心思想是根据数据源中的出现频率来构建一棵哈夫曼树,使得重复次数多的数据用较短的编码表示,
而出现较少的则用更长的编码表示。
头歌赫夫曼树相较于普通的哈夫
曼树,使用的是无损压缩技术,将数据源的压缩结果保持无误的情况
下完成数据压缩。
二、头歌赫夫曼树的构建方法
头歌赫夫曼树的构建方法主要分为两个步骤:哈夫曼树的构建和头歌
操作。
1. 哈夫曼树的构建
(1)将数据源中的所有元素按照出现频率的高低进行排序,出现频率越高的排名越靠前。
(2)依次将排名靠前的两个元素作为一组,其中出现频率较高的元素为根节点,出现频率较低的元素为叶子节点。
将该组元素从数据源中删除,并将新生成的节点加入数据源。
(3)重复执行(1)和(2),直到数据源中只剩下一棵哈夫曼树。
2. 头歌操作
头歌操作是在树的基础上,使用二进制位操作来达成哈夫曼编码。
(1)记录每个叶子节点所代表的字符和二进制编码。
(2)从根节点到叶子节点,如果在这条路径上向左走,则将下一位的二进制编码设为0,向右走则为1。
(3)将所有叶子节点的二进制编码连接起来,以形成数据源压缩后的结果。
三、头歌赫夫曼树的应用实践
头歌赫夫曼树已经广泛应用于图像压缩、数据传输、数据存储等方面,以下是头歌赫夫曼树在这些领域的具体应用实践。
1. 图像压缩
头歌赫夫曼树可以将图像中重复出现的像素点压缩为一个代表像素点
的数据,从而达到压缩图像的效果,提高图像传输和存储的效率。
2. 数据传输
头歌赫夫曼树可以将传输的数据进行压缩,缩短传输时间,减少传输量,有效地减轻传输负担。
3. 数据存储
头歌赫夫曼树可以将数据存储为压缩格式,占用的存储空间更小,提
高存储效率。
总之,头歌赫夫曼树是一种应用广泛的数据压缩算法,其优点在于编
码具有唯一性且无需解压,为数据传输、存储、处理等方面的优化带
来了有效的解决方案。