实验四哈夫曼编码
- 格式:doc
- 大小:38.00 KB
- 文档页数:6
哈夫曼编码译码实验报告哈夫曼编码译码实验报告一、引言哈夫曼编码是一种用来对数据进行压缩的算法,它能够根据数据的频率分布来分配不同长度的编码,从而实现对数据的高效压缩。
本次实验旨在通过实际操作,深入理解哈夫曼编码的原理和实现方式,并通过编码和解码过程来验证其有效性。
二、实验目的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("您的输入有误,请重新输入。
哈夫曼编码的实验报告哈夫曼编码的实验报告一、引言信息的传输和存储是现代社会中不可或缺的一部分。
然而,随着信息量的不断增加,如何高效地表示和压缩信息成为了一个重要的问题。
在这个实验报告中,我们将探讨哈夫曼编码这一种高效的信息压缩算法。
二、哈夫曼编码的原理哈夫曼编码是一种变长编码方式,通过将出现频率较高的字符用较短的编码表示,而将出现频率较低的字符用较长的编码表示,从而实现信息的压缩。
它的核心思想是利用统计特性,将出现频率较高的字符用较短的编码表示,从而减少整体编码长度。
三、实验过程1. 统计字符频率在实验中,我们首先需要统计待压缩的文本中各个字符的出现频率。
通过遍历文本,我们可以得到每个字符出现的次数。
2. 构建哈夫曼树根据字符频率,我们可以构建哈夫曼树。
哈夫曼树是一种特殊的二叉树,其中每个叶子节点代表一个字符,并且叶子节点的权值与字符的频率相关。
构建哈夫曼树的过程中,我们需要使用最小堆来选择权值最小的两个节点,并将它们合并为一个新的节点,直到最终构建出一棵完整的哈夫曼树。
3. 生成编码表通过遍历哈夫曼树,我们可以得到每个字符对应的编码。
在遍历过程中,我们记录下每个字符的路径,左边走为0,右边走为1,从而生成编码表。
4. 进行编码和解码在得到编码表后,我们可以将原始文本进行编码,将每个字符替换为对应的编码。
编码后的文本长度将会大大减少。
为了验证编码的正确性,我们还需要进行解码,将编码后的文本还原为原始文本。
四、实验结果我们选取了一段英文文本作为实验数据,并进行了哈夫曼编码。
经过编码后,原始文本长度从1000个字符减少到了500个字符。
解码后的文本与原始文本完全一致,验证了哈夫曼编码的正确性。
五、讨论与总结哈夫曼编码作为一种高效的信息压缩算法,具有广泛的应用前景。
通过将出现频率较高的字符用较短的编码表示,哈夫曼编码可以在一定程度上减小信息的存储和传输成本。
然而,哈夫曼编码也存在一些局限性,例如对于出现频率相近的字符,编码长度可能会相差较大。
实验四、哈夫曼编码实验目的掌握哈夫曼编码的原理,并编出最优编码实验环境C语言读写文件实验内容先根据位权构造一颗哈夫曼树,测试数据0.05 0.1 0.15 0.2 0.25 0.25,再从叶子结点到根结点编码。
源代码实验结果实验总结源代码#include <stdio.h>#include <string.h>#include<stdlib.h>#define N 50 /*叶子结点数*/#define M 2*N-1 /*树中结点总数*/typedef struct{char data[5]; /*结点值*/float weight; /*权重*/float parent; /*双亲结点*/float lchild; /*左孩子结点*/float rchild; /*右孩子结点*/} HTNode;typedef struct{char cd[N]; /*存放哈夫曼码*/int start;} HCode;void CreateHT(HTNode ht[],int n){int i,k,lnode,rnode;float min1,min2;for (i=0;i<2*n-1;i++) /*所有结点的相关域置初值-1*/ht[i].parent=ht[i].lchild=ht[i].rchild=-1;for (i=n;i<2*n-1;i++) /*构造哈夫曼树*/{min1=min2=32767; /*lnode和rnode为最小权重的两个结点位置*/ 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[lnode].parent=i;ht[rnode].parent=i;ht[i].weight=ht[lnode].weight+ht[rnode].weight; ht[i].lchild=lnode;ht[i].rchild=rnode;}}void CreateHCode(HTNode ht[],HCode hcd[],int n) {int i,f,c;HCode hc;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';else /*处理右孩子结点*/hc.cd[hc.start--]='1';c=f;f=ht[f].parent;}hc.start++; /*start指向哈夫曼编码最开始字符*/ hcd[i]=hc;}}void main(){int n=6,i,k;float sum=0,m=0,j;float fnum[6];HTNode ht[M];HCode hcd[N];char *str[]={"a0","a1","a2","a3","a4","a5"};//float fnum[]={0.05,0.1,0.15,0.2,0.25,0.25};FILE *fp;if((fp=fopen("H:\\study\\C++\\file\\hafuman.txt","r+"))==NULL) {printf("不能打开文件!\n");exit(1);}for(i=0;i<n;i++)fscanf(fp,"%f",&fnum[i]);//原始文件的输出fseek(fp,0,2);//for(i=0;i<n;i++)//{// printf("%5.2f ",fnum[i]);//}//printf("\n");printf("\n赋值给字符:");fprintf(fp,"\n赋值给字符:");for(i=0;i<n;i++){printf("\n%s=%.2f ",str[i],fnum[i]);fprintf(fp,"\n%s=%.2f ",str[i],fnum[i]);}for (i=0;i<n;i++){strcpy(ht[i].data,str[i]);ht[i].weight=fnum[i];}printf("\n");CreateHT(ht,n);CreateHCode(ht,hcd,n);// DispHCode(ht,hcd,n);printf("输出哈夫曼编码:\n"); /*输出哈夫曼编码*/fprintf(fp,"\n输出哈夫曼编码:\n");for (i=0;i<n;i++){j=0;printf(" %s:\t",ht[i].data);fprintf(fp," %s:\t",ht[i].data);for (k=hcd[i].start;k<=n;k++){printf("%c",hcd[i].cd[k]);fprintf(fp,"%c",hcd[i].cd[k]);j++;}m+=ht[i].weight;sum+=ht[i].weight*j;printf("\n");fprintf(fp,"\n");}printf("\n 平均长度=%.2f\n",sum/m);fprintf(fp,"\n 平均长度=%.2f\n",sum/m);printf("\n");fprintf(fp,"\n");fclose(fp);}测试结果:0.05 0.10 0.15 0.2 0.25 0.25(最开始写入的数据)赋值给字符:a0=0.05a1=0.10a2=0.15a3=0.20a4=0.25a5=0.25输出哈夫曼编码:a0: 1110a1: 1111a2: 110a3: 00a4: 01a5: 10平均长度=2.45。
哈夫曼树编码实验报告哈夫曼树编码实验报告引言:哈夫曼树编码是一种常用的数据压缩算法,通过对数据进行编码和解码,可以有效地减小数据的存储空间。
本次实验旨在探究哈夫曼树编码的原理和应用,并通过实际案例验证其有效性。
一、哈夫曼树编码原理哈夫曼树编码是一种变长编码方式,根据字符出现的频率来确定不同字符的编码长度。
频率较高的字符编码较短,频率较低的字符编码较长,以达到最佳的数据压缩效果。
1.1 字符频率统计首先,需要对待编码的数据进行字符频率统计。
通过扫描数据,记录每个字符出现的次数,得到字符频率。
1.2 构建哈夫曼树根据字符频率构建哈夫曼树,频率较低的字符作为叶子节点,频率较高的字符作为父节点。
构建哈夫曼树的过程中,需要使用最小堆来维护节点的顺序。
1.3 生成编码表通过遍历哈夫曼树,从根节点到每个叶子节点的路径上的左右分支分别赋予0和1,生成对应的编码表。
1.4 数据编码根据生成的编码表,将待编码的数据进行替换,将每个字符替换为对应的编码。
编码后的数据长度通常会减小,实现了数据的压缩。
1.5 数据解码利用生成的编码表,将编码后的数据进行解码,恢复原始数据。
二、实验过程与结果为了验证哈夫曼树编码的有效性,我们选择了一段文本作为实验数据,并进行了以下步骤:2.1 字符频率统计通过扫描文本,统计每个字符出现的频率。
我们得到了一个字符频率表,其中包含了文本中出现的字符及其对应的频率。
2.2 构建哈夫曼树根据字符频率表,我们使用最小堆构建了哈夫曼树。
频率较低的字符作为叶子节点,频率较高的字符作为父节点。
最终得到了一棵哈夫曼树。
2.3 生成编码表通过遍历哈夫曼树,我们生成了对应的编码表。
编码表中包含了每个字符的编码,用0和1表示。
2.4 数据编码将待编码的文本数据进行替换,将每个字符替换为对应的编码。
编码后的数据长度明显减小,实现了数据的压缩。
2.5 数据解码利用生成的编码表,将编码后的数据进行解码,恢复原始文本数据。
四元霍夫曼编码的例子一、四元霍夫曼编码简介四元霍夫曼编码(Quaternary Huffman Code)是一种基于霍夫曼编码的编码方式,由美国计算机科学家David A.Huffman于1952年提出。
它是霍夫曼编码的一种扩展,采用四个符号(0、1、2、3)来表示输入字符的频率,以提高编码效率。
在实际应用中,四元霍夫曼编码常用于数据压缩、信息传输和数据库管理等领域。
二、四元霍夫曼编码的计算方法1.码字长度计算四元霍夫曼编码的码字长度计算方法与二元霍夫曼编码相似,仍然是根据输入字符的频率来确定码字长度。
不同的是,四元霍夫曼编码采用四个符号表示频率,因此码字长度有4种可能:1、2、3、4。
2.码字分配原则在分配码字时,四元霍夫曼编码遵循以下原则:1) 频率低的字符分配较短的码字;2) 频率高的字符分配较长的码字;3) 相邻字符的码字不能相同。
3.编码过程演示以字符“A”为例,其频率为1/4(假设四个字符中有一个是“A”):1) 初始化四个码字:0000、0001、0010、0011;2) 将码字0000分配给字符“A”;3) 更新剩余字符的码字:0001、0010、0011;4) 重复步骤2和3,直到所有字符都分配到码字;5) 得到最终的码字表。
三、四元霍夫曼编码的应用1.数据压缩四元霍夫曼编码可用于压缩原始数据,将字符映射到对应的码字。
压缩后的数据可用于存储、传输和检索。
在解码过程中,根据码字还原原始数据。
2.信息传输在信息传输过程中,四元霍夫曼编码可确保数据的可靠性。
通过编码和解码,接收方可以正确还原发送方的原始信息。
3.数据库管理在数据库管理中,四元霍夫曼编码可用于索引、排序和查找等操作。
通过编码,可以提高数据检索的速度和准确性。
四、四元霍夫曼编码的优缺点1.优点- 编码效率高:相较于二元霍夫曼编码,四元霍夫曼编码采用更多符号表示频率,可进一步提高编码效率;- 易于实现:四元霍夫曼编码的计算方法和二元霍夫曼编码相似,只需扩展符号集即可;- 可靠性高:四元霍夫曼编码具有较高的编码可靠性,可确保数据正确传输和解析。
数据结构哈夫曼编码实验报告【正文】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.构建一个哈夫曼树,根据字符出现的频率排序。
频率高的字符在左子树,频率低的字符在右子树。
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.比较编码前后字符串的内容,结果正确。
五、实验总结:通过本次实验,我了解了哈夫曼编码的原理和应用,并且实现了一个简单的哈夫曼编码的编码和译码器。
在实验过程中,我充分运用了数据结构中的树的知识,构建了一个哈夫曼树,并生成了编码表。
通过编码和译码过程,我进一步巩固了对树的遍历和节点查找的理解。
实验结果表明,本次哈夫曼编码的编码和译码过程正确无误。
在实验的过程中,我发现哈夫曼编码对于频率较高的字符具有较短的编码,从而实现了对字符串的高效压缩。
同时,哈夫曼编码还可以应用于数据传输和存储中,提高数据的传输效率和存储空间的利用率。
通过本次实验,我不仅掌握了哈夫曼编码的编码和译码过程,还深入了解了其实现原理和应用场景,加深了对数据结构和算法的理解和应用能力。
实验四、哈夫曼编码问题描述与实验目的:给定n个字母(或字)在文档中出现的频率序列X=<x1,x2,…,xn>,求出这n个字母的Huffman编码。
为方便起见,以下将频率用字母出现的次数(或称权值)w 1,w2,…,wn代替。
输入输入文件中的开始行上有一个整数T,(0<T<=20),表示有T组测试数据。
接下来是T行测试数据的描述,每组测试数据有2行。
测试数据的第1行上是一个正整数n,(n<50),表示序列的长度。
第2行是n个字母出现的权值序列w 1,w2,…,wn,它们均为正整数,相邻的两个整数之间用空格隔开。
输入直到文件结束。
输出对输入中的每组有n个权值的数据,应输出n+1行:先在一行上输出“Case #”,其中“#”是测试数据的组号(从1开始);接下来输出n行,其第1行到第n行上依次输出第i个字母出现的次数和相应的Huffman编码,格式如下:wi Huffman编码。
每组测试数据对应的输出最后结束时加一个空行,以便区分。
为保证Huffman编码的唯一性,在构造Huffman树的过程中,我们约定:1.左儿子标记为0,右儿子标记为1;2.左儿子的权值>=右儿子的权值;3.相同权值w的两个字母x、y,先输入权值的字母x的Huffman编码长度不超过后输入权值的字母y的Huffman编码长度。
4.合并两个节点后新的权值应从右到左搜索、插入到相应的位置。
例如:输入权值序列8 9 3 4 1 2,其Huffman编码求解过程如下,参考图A-J:8 9 3 4 1 2图 A38 9 4 3 2 1图 C 63 9 84 3 2 1图 D 8 9 4 3 2 1图 B 6 3 9 8 3 2 1 4图 E106 3 9 8 3 2 1 4图 F 10633 2 14 9 8图 G106 3 17 3 2 1 4 9 8图 H10 6 17 3 9 8 3 2 1 4图 I2710 6 17 3 9 8 3 2 1 4图 J注意,如图C 中权值1、2对应的节点合并后得权值为3的新节点,它插入到权值为3的原有节点的右边。
江 西 理 工 大 学江 西 理 工 大 学 实 验 报 告 纸第 1 页/共 4页一、实验目的掌握哈夫曼编码算法的基本原理;要求对屏幕输入的信符概率向量进行哈夫曼编码。
二、实验内容对屏幕输入的信符概率向量例如‘[0.4 0.2 0.16 0.12 0.06 0.04 0.02]’进行哈夫曼编码,计算计算信源的熵,哈夫曼编码的平均码字长及其编码效率,显示哈夫曼编码与相应计算结果.三、实验步骤和设计思想通过哈夫曼编码来计算信源的熵,用Matlab 来模拟算法的过程。
霍夫曼编码的步骤:1)根据待编码的符号串,统计各个符号的概率;2)根据符号的概率统计特征,构建霍夫曼编码表,即计算每个符号的编码结果; 3)用得到的编码表对符号序列进行编码。
四、程序清单clcclear allp=input('请输入信符的概率向量:'); n=length(p); q=p;a=zeros(n-1,n); for i=1:n-1fprintf('第%d 次排序\n',i); [q,l]=sort(q) %qa(i,:)=[l(1:n-i+1),zeros(1,i-1)]fprintf('\n 第%d 次排序后合并生成的数据',i);q=[q(1)+q(2),q(3:n),1] endfor i=1:n-1c(i,1:n*n)=blanks(n*n); endc(n-1,n)='1'; c(n-1,2*n)='0'; for i=2:n-1c(n-i,1:n-1)=c(n-i+1,n*(find(a(n-i+1,:)==1))-(n-2):n*(find(a(n-i+1,:)==1))) c(n-i,n)='1';c(n-i,n+1:2*n-1)=c(n-i,1:n-1); c(n-i,2*n)='0';for j=1:i-1c(n-i,(j+1)*n+1:(j+2)*n)=c(n-i+1,n*(find(a(n-i+1,:)==j+1)-1)+1:n*(find(a(n-i+1,:)==j+1))) end end for i=1:nh(i,1:n)=c(1,n*(find(a(1,:)==i)-1)+1:find(a(1,:)==i)*n); ll(i)=length(find(abs(h(i,:)~=32))); endLavg=sum(p.*ll)fprintf('\n huffman code:\n'); hHA=(-1) * sum(p.*log2(p));fprintf('\n huffman effciency:\n'); t=HA/Lavg五、实验调试记录六、实验结果及其分析请输入信符的概率向量:[0.4 0.2 0.16 0.12 0.06 0.04 0.02] 第1次排序q = 0.0200 0.0400 0.0600 0.1200 0.1600 0.2000 0.4000 l = 7 6 5 4 3 2 1 a = 7 6 5 4 3 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0数字图像处理 实验报告姓名: 江 西 理 工 大 学 实 验 报 告 纸第 2 页/共 4页0 0 0 0 0 0 0 0 0 0 0 0 0 0第1次排序后合并生成的数据 q =0.0600 0.0600 0.1200 0.1600 0.2000 0.4000 1.0000 第2次排序 q =Columns 1 through 60.0600 0.0600 0.1200 0.1600 0.2000 0.4000 Column 7 1.0000 l =1 2 3 4 5 6 7 a =7 6 5 4 3 2 1 1 2 3 4 5 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 第2次排序后合并生成的数据 q =Columns 1 through 60.1200 0.1200 0.1600 0.2000 0.4000 1.0000 Column 7 1.0000 第3次排序 q =Columns 1 through 60.1200 0.1200 0.1600 0.2000 0.4000 1.0000 Column 7 1.0000 l =1 2 3 4 5 6 7 a =7 6 5 4 3 2 1 1 2 3 4 5 6 0 1 2 3 4 5 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0第3次排序后合并生成的数据 q =Columns 1 through 60.2400 0.1600 0.2000 0.4000 1.0000 1.0000 Column 7 1.0000第4次排序q =Columns 1 through 60.1600 0.2000 0.2400 0.4000 1.0000 1.0000 Column 7 1.0000l = 2 3 1 4 5 6 7 a = 7 6 5 4 3 2 1 1 2 3 4 5 6 0 1 2 3 4 5 0 0 2 3 1 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0第4次排序后合并生成的数据 q =Columns 1 through 60.3600 0.2400 0.4000 1.0000 1.0000 1.0000 Column 7 1.0000第5次排序q = Columns 1 through 60.2400 0.3600 0.4000 1.0000 1.0000 1.0000 Column 7 1.0000l = 2 1 3 4 5 6 7 a = 7 6 5 4 3 2 1 1 2 3 4 5 6 0 1 2 3 4 5 0 0 2 3 1 4 0 0 0 2 1 3 0 0 0 0 0 0 0 0 0 0 0 第5次排序后合并生成的数据 q =Columns 1 through 60.6000 0.4000 1.0000 1.0000 1.0000 1.0000姓名: 江 西 理 工 大 学 实 验 报 告 纸第 3 页/共 4页Column 7 1.0000第6次排序q =Columns 1 through 60.4000 0.6000 1.0000 1.0000 1.0000 1.0000 Column 7 1.0000l = 2 1 3 4 5 6 7 a = 7 6 5 4 3 2 1 1 2 3 4 5 6 0 1 2 3 4 5 0 0 2 3 1 4 0 0 0 2 1 3 0 0 0 0 2 1 0 0 0 0 0第6次排序后合并生成的数据q = 1 1 1 1 1 1 1c = 0 1 0 c = 01 00 1 1 0 c = 00 01 00 1 1 0 c = 001 000 01 01 00 1 1 0 c = 001 000 01 1 01 00 1 1 0 c = 01 001 000 01 1 01 00 1 1 0 c = 011 010 001 001 000 01 1 01 00 1 1 0 c = 011 010 001 000 001 000 01 1 01 00 1 1 0 c = 011 010 001 000 1 001 000 01 1 01 00 1 1 0 c = 011 011 010 001 000 1 001 000 01 1 01 00 1 1 0 c = 0111 0110 010 011 010 001 000 1 001 000 01 1 01 00 1 1 0 c = 0111 0110 010 001 011 010 001 000 1 001 000 01 1 01 00 1 1 0 c = 0111 0110 010 001 000 011 010 001 000 1 001 000 01 1 01 00 1 1 0 c = 0111 0110 010 001 000 1 011 010 001 000 1 001 000 01 1 01 00 1 1 0 c =0111 0111 0110 010 001 000 1 011 010 001 000 1 001 000 01 1 01 00 1 1 0 c =01111 01110 0110 0111 0110 010 001 000 1姓名: 江西理工大学实验报告纸011 010 001 000 1001 000 01 101 00 11 0c = 01111 01110 0110 0100111 0110 010 001 000 1011 010 001 000 1001 000 01 101 00 11 0c =01111 01110 0110 010 0010111 0110 010 001 000 1011 010 001 000 1001 000 01 101 00 11 0c = 01111 01110 0110 010 001 0000111 0110 010 001 000 1011 010 001 000 1001 000 01 101 00 11 0c = 01111 01110 0110 010 001 000 10111 0110 010 001 000 1011 010 001 000 1001 000 01 101 00 11 0七、实验心得通过做这次实验掌握了哈夫曼编码的基本理论和算法流程;掌握了编程实现图像的哈夫曼编码算法。
一、实验目的1. 理解哈夫曼编码的基本原理和重要性。
2. 掌握哈夫曼树的构建方法。
3. 熟悉哈夫曼编码和译码的实现过程。
4. 分析哈夫曼编码在数据压缩中的应用效果。
二、实验原理哈夫曼编码是一种基于字符频率的编码方法,它利用字符出现的频率来构造一棵最优二叉树(哈夫曼树),并根据该树生成字符的编码。
在哈夫曼树中,频率越高的字符对应的编码越短,频率越低的字符对应的编码越长。
这样,对于出现频率较高的字符,编码后的数据长度更短,从而实现数据压缩。
三、实验内容1. 构建哈夫曼树:- 统计待编码数据中每个字符出现的频率。
- 根据字符频率构建哈夫曼树,其中频率高的字符作为叶子节点,频率低的字符作为内部节点。
- 重复上述步骤,直到树中只剩下一个节点,即为哈夫曼树的根节点。
2. 生成哈夫曼编码:- 从哈夫曼树的根节点开始,对每个节点进行遍历,根据遍历方向(左子树为0,右子树为1)为字符分配编码。
- 将生成的编码存储在编码表中。
3. 编码和译码:- 使用生成的编码表对原始数据进行编码,将编码后的数据存储在文件中。
- 从文件中读取编码后的数据,根据编码表进行译码,恢复原始数据。
四、实验步骤1. 编写代码实现哈夫曼树的构建:- 定义节点结构体,包含字符、频率、左子树、右子树等属性。
- 实现构建哈夫曼树的核心算法,包括节点合并、插入等操作。
2. 实现编码和译码功能:- 根据哈夫曼树生成编码表。
- 编写编码函数,根据编码表对数据进行编码。
- 编写译码函数,根据编码表对数据进行译码。
3. 测试实验效果:- 选择一段文本数据,使用实验代码进行编码和译码。
- 比较编码前后数据的长度,分析哈夫曼编码的压缩效果。
五、实验结果与分析1. 哈夫曼树构建:- 成功构建了哈夫曼树,树中节点按照字符频率从高到低排列。
2. 哈夫曼编码:- 成功生成编码表,字符与编码的对应关系符合哈夫曼编码原理。
3. 编码与译码:- 成功实现编码和译码功能,编码后的数据长度明显缩短,译码结果与原始数据完全一致。
数据结构哈夫曼编码实验报告实验目的:本实验旨在了解和实现哈夫曼编码算法,通过将字符转换为对应的哈夫曼编码来实现数据的压缩和解压缩。
一、引言1.1 背景介绍哈夫曼编码是一种基于字符出现频率的编码方法,通过使用不等长编码来表示不同字符,从而实现数据的高效压缩。
该编码方法在通信、存储等领域有着广泛的应用。
1.2 目标本实验的目标是实现哈夫曼编码算法,通过对给定文本进行编码和解码,验证哈夫曼编码的有效性和可靠性。
二、实验过程2.1 数据结构设计在实现哈夫曼编码算法时,我们需要设计合适的数据结构来存储字符和对应的编码。
常用的数据结构包括树和哈希表。
我们将使用二叉树作为数据结构来表示字符的编码。
2.2 构建哈夫曼树哈夫曼树是由给定字符集合构建而成的最优二叉树。
构建哈夫曼树的过程分为两步:首先根据字符出现频率构建叶子节点,然后通过合并叶子节点和父节点构造哈夫曼树。
2.3 哈夫曼编码表根据构建好的哈夫曼树,我们可以对应的哈夫曼编码表。
哈夫曼编码表由字符和对应的编码组成,可以用于字符的编码和解码。
2.4 文本压缩利用的哈夫曼编码表,我们可以对给定的文本进行压缩。
将文本中的字符逐个替换为对应的哈夫曼编码,从而实现数据的压缩。
2.5 文本解压缩对压缩后的数据进行解压缩时,我们需要利用的哈夫曼编码表,将哈夫曼编码逐个替换为对应的字符,从而还原出原始的文本数据。
三、实验结果我们使用不同长度、不同频率的文本进行了实验。
实验结果表明,哈夫曼编码在数据压缩方面有着显著的效果,可以大大减小数据存储和传输的开销。
四、实验总结通过本实验,我们深入理解了哈夫曼编码算法的原理和实现过程,掌握了数据的压缩和解压缩技术。
哈夫曼编码作为一种经典的数据压缩算法,具有重要的理论意义和实际应用价值。
附件:本文档附带哈夫曼编码实验的源代码和实验数据。
法律名词及注释:在本文档中,涉及的法律名词和注释如下:1.哈夫曼编码:一种数据压缩算法,用于将字符转换为可变长度的编码。
哈夫曼编码实验报告哈夫曼编码实验报告一、引言哈夫曼编码是一种用于数据压缩的算法,由大卫·哈夫曼于1952年提出。
它通过将出现频率高的字符用较短的编码表示,从而实现对数据的高效压缩。
本实验旨在通过实际操作和数据分析,深入了解哈夫曼编码的原理和应用。
二、实验目的1. 掌握哈夫曼编码的基本原理和算法;2. 实现哈夫曼编码的压缩和解压缩功能;3. 分析不同数据集上的压缩效果,并对结果进行评估。
三、实验过程1. 数据集准备本实验选取了三个不同的数据集,分别是一篇英文文章、一段中文文本和一段二进制数据。
这三个数据集具有不同的特点,可以用来评估哈夫曼编码在不同类型数据上的压缩效果。
2. 哈夫曼编码实现在实验中,我们使用了Python编程语言来实现哈夫曼编码的压缩和解压缩功能。
首先,我们需要统计数据集中各个字符的出现频率,并构建哈夫曼树。
然后,根据哈夫曼树生成每个字符的编码表,将原始数据转换为对应的编码。
最后,将编码后的数据存储为二进制文件,并记录编码表和原始数据的长度。
3. 压缩效果评估对于每个数据集,我们比较了原始数据和压缩后数据的大小差异,并计算了压缩比和压缩率。
压缩比是指压缩后数据的大小与原始数据大小的比值,压缩率是指压缩比乘以100%。
通过对比不同数据集上的压缩效果,我们可以评估哈夫曼编码在不同类型数据上的性能。
四、实验结果与分析1. 英文文章数据集对于一篇英文文章,经过哈夫曼编码压缩后,我们发现压缩比为0.6,即压缩后的数据只有原始数据的60%大小。
这说明哈夫曼编码在英文文本上具有较好的压缩效果。
原因在于英文文章中存在大量的重复字符,而哈夫曼编码能够利用字符的出现频率进行编码,从而减少数据的存储空间。
2. 中文文本数据集对于一段中文文本,我们发现哈夫曼编码的压缩效果不如在英文文章上的效果明显。
压缩比为0.8,即压缩后的数据只有原始数据的80%大小。
这是因为中文文本中的字符种类较多,并且出现频率相对均匀,导致哈夫曼编码的优势减弱。
哈夫曼编码实验报告数据结构实验报告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)选出权值最小的两个结点,其权值和作为其根结点的权值,最小的结点作为左子树,次小的作为右子树,不断将两棵子树合并为一棵树。
四元霍夫曼编码的例子一、四元霍夫曼编码的基本概念四元霍夫曼编码(Quaternary Huffman Code)是一种基于霍夫曼编码的编码方法,由美国计算机科学家David A.Huffman于1952年提出。
与二元霍夫曼编码相比,四元霍夫曼编码使用四个符号(0、1、2、3)来表示输入字符的频率,从而提高了编码的效率。
二、四元霍夫曼编码的编码规则1.符号的选择在四元霍夫曼编码中,符号的选择至关重要。
为了使编码效率最大化,应选择出现频率最高的字符作为0,其次为1、2、3。
这样,出现频率较高的字符将拥有较短的编码,从而降低整体编码长度。
2.码字的构造码字的构造遵循霍夫曼编码的原理,即从左到右,将出现频率最高的字符依次分配给0、1、2、3,形成一个码字。
在四元霍夫曼编码中,每个码字由两个符号组成,第一个符号表示最高位,第二个符号表示次高位。
3.码字的长度四元霍夫曼编码的码字长度与字符出现频率成反比。
出现频率最高的字符拥有最短的码字,而出现频率较低的字符则拥有较长的码字。
通过这种方式,四元霍夫曼编码实现了对字符的高效编码。
三、四元霍夫曼编码的应用场景四元霍夫曼编码在需要对字符进行压缩编码的场景中具有广泛应用,如数据通信、图像处理、语音识别等领域。
通过使用四元霍夫曼编码,可以有效地减少数据传输量,提高传输效率。
四、四元霍夫曼编码的优点与局限性1.优点(1)高效性:相较于其他编码方法,四元霍夫曼编码能够实现较高的编码效率,降低数据传输量。
(2)通用性:四元霍夫曼编码适用于多种场景,如文本、图像、语音等。
2.局限性(1)复杂性:相较于二元霍夫曼编码,四元霍夫曼编码的实现过程更为复杂,需要更多的计算资源和时间。
(2)编码长度:虽然四元霍夫曼编码能够实现较高的编码效率,但相较于一些其他编码方法(如K-ary Huffman编码),其编码长度仍有一定局限。
五、实际案例分析以文本压缩为例,假设有一篇英文文章,其中字母出现的频率如下:```A: 0.1B: 0.2C: 0.3D: 0.4```根据四元霍夫曼编码的规则,首先对字母进行排序,根据出现频率从高到低分别为:D、C、B、A。
一、实训目的本次实训旨在通过实际操作,使学生掌握哈夫曼编码的基本原理和方法,熟悉哈夫曼树的构建过程,并能够熟练地进行哈夫曼编码和译码操作。
通过实训,提升学生对数据压缩技术的理解和应用能力。
二、实训内容1. 哈夫曼树构建- 收集给定字符串中每个字符的出现频率。
- 根据字符频率构建哈夫曼树,其中频率高的字符对应较大的权重。
- 使用优先队列(最小堆)实现哈夫曼树的构建。
2. 哈夫曼编码- 遍历哈夫曼树,为每个叶子节点分配唯一的编码,左分支为0,右分支为1。
- 根据分配的编码生成字符编码表。
3. 哈夫曼译码- 使用生成的编码表,将编码字符串转换回原始字符串。
三、实训步骤1. 数据准备- 选择一段英文或中文文本作为输入数据。
2. 构建哈夫曼树- 统计输入数据中每个字符的出现频率。
- 使用优先队列构建哈夫曼树。
3. 生成哈夫曼编码- 遍历哈夫曼树,为每个叶子节点分配编码。
- 生成字符编码表。
4. 编码数据- 使用哈夫曼编码表对输入数据进行编码。
5. 译码数据- 使用哈夫曼编码表对编码后的数据进行译码。
6. 结果分析- 比较编码前后数据的大小,分析哈夫曼编码的压缩效果。
四、实训结果1. 哈夫曼树构建- 成功构建了给定字符串的哈夫曼树。
2. 哈夫曼编码- 成功生成了每个字符的哈夫曼编码。
3. 哈夫曼译码- 成功将编码后的数据译码回原始字符串。
4. 压缩效果分析- 通过对比编码前后数据的大小,验证了哈夫曼编码的压缩效果。
五、实训总结1. 哈夫曼编码原理- 哈夫曼编码是一种基于字符频率的变长编码方法,能够有效降低数据传输的冗余度。
2. 哈夫曼树构建- 哈夫曼树的构建是哈夫曼编码的关键步骤,通过优先队列(最小堆)实现。
3. 哈夫曼编码与译码- 哈夫曼编码和译码过程相对简单,但需要正确处理编码表和字符编码。
4. 实训收获- 通过本次实训,掌握了哈夫曼编码的基本原理和方法,熟悉了哈夫曼树的构建过程,并能够熟练地进行哈夫曼编码和译码操作。
实验四 贪心算法
实验目的和要求
(1)了解前缀编码的概念,理解数据压缩的基本方法;
(2)掌握最优子结构性质的证明方法;
(3)掌握贪心法的设计思想并能熟练运用
(4)证明哈夫曼树满足最优子结构性质;
(5)设计贪心算法求解哈夫曼编码方案;
(6)设计测试数据,写出程序文档。
实验内容
设需要编码的字符集为{d 1, d 2, …, dn },它们出现的频率为 {w 1, w 2, …, wn },应用哈夫曼树构造最短的不等长编码方案。
实验环境
Dev c++
实验学时
2学时,必做实验
数据结构与算法
/*示例
****哈夫曼编码****
请输入结点个数:8
输入这8个元素的权值(均为整形):
1:27
2:4
3:87
4:21
5:2
6:21
7:1
8:25
*/
#include <stdio.h>
#include <stdlib.h>
∑=j
i k k a
#include <string.h>
typedef struct
{
unsigned int weight; //用来存储各个结点的权值
unsigned int parent,LChild,RChild; //指向双亲、孩子结点的指针} HTNode, *HuffmanTree; //动态分配数组,存储哈夫曼树
typedef char *HuffmanCode; //动态分配数组,存储哈夫曼树
///选择两个parent为0,且weight最小的结点s1和s2
void Select(HuffmanTree *ht,int n,int *s1,int *s2)
{
int i,min;
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0)
{
min=i;
break;
}
}
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0)
{
if((*ht)[i].weight<(*ht)[min].weight)
min=i;
}
}
*s1=min;
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0 && i!=(*s1))
{
min=i;
break;
}
}
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0 && i!=(*s1))
{
if((*ht)[i].weight<(*ht)[min].weight)
min=i;
}
}
*s2=min;
}
///构造哈夫曼树ht,w存放已知n个权值
void CrtHuffmanTree(HuffmanTree *ht,int *w,int n) {
int m,i,s1,s2;
m=2*n-1; //总共的结点数
*ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); for(i=1; i<=n; i++) //1-n号存放叶子结点,初始化 {
(*ht)[i].weight=w[i];
(*ht)[i].LChild=0;
(*ht)[i].parent=0;
(*ht)[i].RChild=0;
}
for(i=n+1; i<=m; i++) //非叶子结点的初始化
{
(*ht)[i].weight=0;
(*ht)[i].LChild=0;
(*ht)[i].parent=0;
(*ht)[i].RChild=0;
}
printf("\n?哈夫曼树为: \n");
for(i=n+1; i<=m; i++) //创建非叶子结点,建哈夫曼树
{ /*在(*ht)[1]~(*ht)[i-1]的范围内选择两个parent为0且weight最小的结点,其序号分别赋值给s1、s2*/
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;
printf("%d (%d, %d)\n",(*ht)[i].weight,(*ht)[s1].weight,(*ht)[s2].weight);
}
printf("\n");
}
//从叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码
void CrtHuffmanCode(HuffmanTree *ht, HuffmanCode *hc, int n)
{
char *cd; //定义的存放编码的空间
int a[100];
int i,start,p,w=0;
unsigned int c;
hc=(HuffmanCode *)malloc((n+1)*sizeof(char *)); //分配n个编码的头指针
cd=(char *)malloc(n*sizeof(char)); //分配求当前编码的工作空间
cd[n-1]='\0'; //从右向左逐位存放编码,首先存放编码结束符
for(i=1; i<=n; i++) //求n个叶子结点对应的哈夫曼编码
{
a[i]=0;
start=n-1; //起始指针位置在最右边
for(c=i,p=(*ht)[i].parent; p!=0; c=p,p=(*ht)[p].parent) //从叶子到根结点求编码 {
if( (*ht)[p].LChild==c)
{
cd[--start]='1'; //左分支标1
a[i]++;
}
else
{
cd[--start]='0'; //右分支标0
a[i]++;
}
}
hc[i]=(char *)malloc((n-start)*sizeof(char)); //为第i个编码分配空间
strcpy(hc[i],&cd[start]); //将cd复制编码到hc
}
free(cd);
for(i=1; i<=n; i++)
printf(" 权值为%d的哈夫曼编码为:%s\n",(*ht)[i].weight,hc[i]);
for(i=1; i<=n; i++)
w+=(*ht)[i].weight*a[i];
printf(" 带权路径为:%d\n",w);
}
int main()
{
HuffmanTree HT;
HuffmanCode HC;
int *w,i,n,wei;
printf("**哈夫曼编码**\n" );
printf("请输入结点个数:" );
scanf("%d",&n);
w=(int *)malloc((n+1)*sizeof(int));
printf("\n输入这%d个元素的权值:\n",n);
for(i=1; i<=n; i++)
{
printf("%d: ",i);
fflush(stdin);
scanf("%d",&wei);
w[i]=wei;
}
CrtHuffmanTree(&HT,w,n);
CrtHuffmanCode(&HT,&HC,n);
system("pause");
return 0;
}
实验结果
实验体会。