算法分析与设计 实验二 哈夫曼编码
《哈夫曼编码》实验报告
《哈夫曼编码》实验报告《哈夫曼编码》实验报告一、实验目的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个信源符号及其对应的权值2.利用select()函数找出权值最小的两个信源,并各自分配一个码元“0”“1”,并将这两个信源合并为一个新的信源,其权值为这两个最小信源的权值之和,得到一个包n-1个信源符号的新信源,这一过程叫做信源的第一次缩减3.重复步骤二,直到只剩下两个符号为止,此时从最后一级缩减信源开始,依编码路经向前返回,得到各信源符号所对应的码字4.输出信息熵,平均码长以及编码效率三、源代码#include<iostream>#include <math.h>using namespace std;#define MAX 100typedef struct{int weight;int parent,Lc,Rc;char data;}HTNode,*HTree; //动态分配数组存储赫夫曼树typedef char * *HCode;void HuffmanCode(HTree &HT,HCode &HC,int *w,int n);void Select(HTree &HT,int n,int &s1,int &s2);void inputCode();void outputCode(HCode HC,char *data,int *w,int n);const int n=27;int flag=0;HTree Ht;HCode Hc;int num;void HuffmanCode(HTree &HT,HCode &HC,int *w,int n){//w存放n个字符权值(均>0),构造赫夫曼树HT,并求n个字符赫夫曼编码HC。
int m,i,s1,s2;//s1,s2为在HT[1..i-1]中parent为0且weight最小的两个结点if(n<=1) return;//如果结点小于或等于1个,则调用函数出错,退出函数m=2*n-1;//m为赫夫曼树的总结点数HT=(HTree)malloc((m+1)*sizeof(HTNode));// 对赫夫曼树进行初始化for(i=1;i<=n;i++) {HT[i].data=0;HT[i].weight=w[i-1];HT[i].parent=0;HT[i].Lc=0;HT[i].Rc=0;}for(;i<=m;i++) {HT[i].data=0;HT[i].weight=0;HT[i].parent=0;HT[i].Lc=0;HT[i].Rc=0;}//***************创建HuffmanTree******************char *cd;int start,c,f;for(i=n+1;i<=m;++i){Select(HT,i-1,s1,s2);HT[s1].parent=HT[s2].parent=i;HT[i].Rc=s2;HT[i].weight=HT[s1].weight+HT[s2].weight;}//从叶子到根逆向求每个字符的赫夫曼编码HC=(HCode)malloc((n+1)*sizeof(char*)); //分配n个字符编码的头指针向量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].Lc==c)cd[--start]='0';elsecd[--start]='1';HC[i]=(char*)malloc((n-start)*sizeof(char));// 为第i个字符编码分配空间strcpy(HC[i],&cd[start]); //从cd复制编码(串)到HC }free(cd);}//HuffmanCode//s1为权值最小的根结点void Select(HTree &HT,int n,int &s1,int &s2){//在HT[1..n]选择parent为0且weight最小的两个结点,其序号分别为s1,s2。
计算机算法设计与分析 哈夫曼编码 实验报告
×××学院实验报告纸计算机科学与工程学院(院、系)网络工程专业071班组计算机算法设计与分析课学号2007102××姓名121 实验日期2010.教师评定哈夫曼编码问题1、实验目的:根据最优二叉树构造哈夫曼编码利用哈夫曼树很容易求出给定字符集及其概率分布的最优前缀码。
哈夫曼编码正是一种应用广泛且非常,本次试验通过设计一个算法,体会和掌握哈夫曼编码要点。
2、算法分析:给定字符集的哈夫曼树生成后,求哈夫曼编码的具体实现过程是:依次以叶子T[i]为出发点,向上回溯至根为止。
上溯时走左分支则生成代码0,走右分支则生成代码1。
3、程序代码:问题描述:已知每一个字符出现的频率,构造哈夫曼树,并设计哈夫曼编码。
功能描述:键入权值和相应字符按照“树状结构”打印构造好的哈夫曼树,并打印出每一个字符对应的哈夫曼编码。
选作内容:已知一个字符串,将其进行编码;已知一串编码,可以将其译码成字符串。
cprintf("请输入哈夫曼编码测试数据,在此建议为'thisprogramme is my favorite'");printf("\n");cprintf("注意小写,空格由大写字母T代替,并且字符数小于27.\n");scanf("%s",sstring);if(strlen(sstring)>=MAXNODE){printf("you input the data number >=MAXNODE.");exit(1);}for(i=0;i<strlen(sstring);i++){for(j=0;j<MAXBIT;j++)if(sstring[i]==haffcode[j].data){k=j;break;}if(k<0||k>MAXNODE-1){printf("在系统中找不到与第个%d字符相匹配的编码\n",i+1);continue;}newhaffcode[i].start=haffcode[k].start;newhaffcode[i].weight=haffcode[k].weight;newhaffcode[i].data=haffcode[k].data;for(s=haffcode[k].start+1;s<MAXBIT;s++)newhaffcode[i].bit[s]=haffcode[k].bit[s];}pprintf(newhaffcode,strlen(sstring));}void end()4、时间复杂度分析:算法的时间复杂度分析:程序部分用双循环嵌套结构,时间复杂度为O(n2). 算法的空间复杂度分析:算法的空间复杂度为O(n)5、总结:通过一个简单的例子,掌握了哈夫曼编码的算法思想和要点。
哈夫曼树编码实验报告
哈夫曼树编码实验报告哈夫曼树编码实验报告引言:哈夫曼树编码是一种常用的数据压缩算法,通过对数据进行编码和解码,可以有效地减小数据的存储空间。
本次实验旨在探究哈夫曼树编码的原理和应用,并通过实际案例验证其有效性。
一、哈夫曼树编码原理哈夫曼树编码是一种变长编码方式,根据字符出现的频率来确定不同字符的编码长度。
频率较高的字符编码较短,频率较低的字符编码较长,以达到最佳的数据压缩效果。
1.1 字符频率统计首先,需要对待编码的数据进行字符频率统计。
通过扫描数据,记录每个字符出现的次数,得到字符频率。
1.2 构建哈夫曼树根据字符频率构建哈夫曼树,频率较低的字符作为叶子节点,频率较高的字符作为父节点。
构建哈夫曼树的过程中,需要使用最小堆来维护节点的顺序。
1.3 生成编码表通过遍历哈夫曼树,从根节点到每个叶子节点的路径上的左右分支分别赋予0和1,生成对应的编码表。
1.4 数据编码根据生成的编码表,将待编码的数据进行替换,将每个字符替换为对应的编码。
编码后的数据长度通常会减小,实现了数据的压缩。
1.5 数据解码利用生成的编码表,将编码后的数据进行解码,恢复原始数据。
二、实验过程与结果为了验证哈夫曼树编码的有效性,我们选择了一段文本作为实验数据,并进行了以下步骤:2.1 字符频率统计通过扫描文本,统计每个字符出现的频率。
我们得到了一个字符频率表,其中包含了文本中出现的字符及其对应的频率。
2.2 构建哈夫曼树根据字符频率表,我们使用最小堆构建了哈夫曼树。
频率较低的字符作为叶子节点,频率较高的字符作为父节点。
最终得到了一棵哈夫曼树。
2.3 生成编码表通过遍历哈夫曼树,我们生成了对应的编码表。
编码表中包含了每个字符的编码,用0和1表示。
2.4 数据编码将待编码的文本数据进行替换,将每个字符替换为对应的编码。
编码后的数据长度明显减小,实现了数据的压缩。
2.5 数据解码利用生成的编码表,将编码后的数据进行解码,恢复原始文本数据。
Huffman编码实验报告
Huffman编码实验报告1 二进制哈夫曼编码的原理及步骤(1)信源编码的计算设有N 个码元组成的离散、无记忆符号集,其中每个符号由一个二进制码字表示,信源符号个数n 、信源的概率分布P={p(s i )},i=1,…..,n 。
且各符号xi 的以li 个码元编码,在变长字编码时每个符号的平均码长为∑==ni li xi p L 1)( ;信源熵为:)(log )()(1xi p xi p X H ni ∑=-= ;唯一可译码的充要条件:11≤∑=-ni Ki m ;其中m 为码符号个数,n 为信源符号个数,Ki 为各码字长度。
构造哈夫曼数示例如下图所示。
(2)二元霍夫曼编码规则(1)将信源符号依出现概率递减顺序排序。
(2)给两个概率最小的信源符号各分配一个码位“0”和“1”,将两个信源符号合并成一个新符号,并用这两个最小的概率之和作为新符号的概率,结果得到一个只包含(n-1)个信源符号的新信源。
称为信源的第一次缩减信源,用s1 表示。
(3)将缩减信源 s1 的符号仍按概率从大到小顺序排列,重复步骤(2),得到只含(n-2)个符号的缩减信源s2。
0.0.0.0.1.000.0.0.00.0.0.0.(4)重复上述步骤,直至缩减信源只剩两个符号为止,此时所剩两个符号 的概率之和必为 1,然后从最后一级缩减信源开始,依编码路径向前返回,就得到各信源符号所对应的码字。
2 功能介绍输入一段字符序列,通过本程序可得出该字符序列中各个字符出现的次数,以及每个字符出现的概率,并能计算出信源符号熵,每个字符的哈弗曼编码,和相应的平均码长,编码效率,码方差。
3 算法基本步骤描述4 C 语言源代码#include<stdio.h>#include<string.h>#include<math.h>#define MAX 100//定义全局变量h 存放信息熵double h=0; 得到信得出信源得出信源计算信输输输输输信源符号的码编码平均输//定义结构体用于存放信源符号,数目及概率typedef struct{//不同的字符char SOURCECODE;//不同字符出现的次数int NUM;//不同字符出现的概率double PROBABILITY;//哈夫曼编码符号int Code[MAX];int start;//哈夫曼树的父结点int parent;//哈夫曼树的左右子结点int lchild;int rchild;//哈夫曼编码的长度int lengthofhuffmancode;}Hcode;Hcode INFORMATION[MAX];//该函数用来求信源所包含的符号,以及不同符号出现的次数和概率int Pofeachsource(char informationsource[MAX],int a){int i,j=1,m,flag=0;char temp;//预先存入第一个字符,便于与后面的字符进行比较//统计不同的字符存入结构体数组中//利用flag标签来标记每个字符是否出现过,若出现过标记为1,否则置为零INFORMATION[0].SOURCECODE=informationsource[0];for(i=1;i<a;i++){ for(m=0;m<i;m++){flag=0;if(informationsource[m]==informationsource[i]){flag=1;break;}}if(flag==1)continue;elseINFORMATION[j++].SOURCECODE=informationsource[i];}INFORMATION[j].SOURCECODE='\0';printf("信源符号数为:%d\n",j);//统计相同的字符出现的次数//每做一个字符出现次数的统计都将结构体数组里的NUM置为零for(i=0;i<j;i++){ INFORMATION[i].NUM=0;for(m=0;m<a;m++)if(informationsource[m]==INFORMATION[i].SOURCECODE)INFORMATION[i].NUM++;}//统计每个字符出现的概率for(i=0;i<j;i++) INFORMATION[i].PROBABILITY=(float)INFORMATION[i].NUM/a;//将每个不同字符出现的次数概率都显示出来for(i=0;i<j;i++)printf("The NUM and PROBABILITY of Code'%c'is %dand %.3f\n",INFORMATION[i].SOURCECODE,INFORMATION[i].NUM,INFORMATION [i].PROBABILITY);return j;}//求信源符号的熵void H(int a){int i;for(i=0;i<a;i++){h+=((-1)*(INFORMATION[i].PROBABILITY)*(log(INFORMATION[i].PROBABI LITY)/log(2)));}}//哈夫曼编码函数void Huffman(int a){Hcode cd;int i,j,m=0,lm=0,p,c;double min,lmin;//顺序初始化每个信源父子结点为-1for(i=0;i<a;i++){INFORMATION[i].parent=-1;INFORMATION[i].lchild=-1;INFORMATION[i].lchild=-1;}cd.start--; /* 求编码的低一位 */c=p;p=INFORMATION[c].parent; /* 设置下一循环条件 */}//保存求出的每个叶结点的哈夫曼编码和编码的起始位for(j=cd.start+1;j<m;j++){ INFORMATION[i].Code[j]=cd.Code[j];}INFORMATION[i].start=cd.start;}}void main(){//定义存放信源符号的数组char informationsource[MAX];int i,j,m;double averageofhuffmancode=0.0,Eita,cV=0.0;printf("please input the source of information:");for(i=0;;i++){scanf("%c",&informationsource[i]);if(informationsource[i]=='\n')break;}informationsource[i]='\0';printf("信源序列为:");//显示已输入的一串信源符号puts(informationsource);//返回不同信源符号的数目m=Pofeachsource(informationsource,i);//求信源的符号熵H(m);printf("信源的符号熵:H(X)=%.3f(比特/符号)\n",h);Huffman(m);//输出已保存好的所有存在编码的哈夫曼编码for(i=0;i<m;i++){printf("%c's Huffman code is: ",INFORMATION[i].SOURCECODE); for(j=INFORMATION[i].start+1;j<m;j++)printf("%d",INFORMATION[i].Code[j]);INFORMATION[i].lengthofhuffmancode=m-INFORMATION[i].start-1; printf("\n");}//求哈夫曼编码的平均码长和编码效率for(i=0;i<m;i++)averageofhuffmancode+=INFORMATION[i].PROBABILITY*INFORMATION[i].l engthofhuffmancode;printf("哈夫曼编码的平均码长为:%lf(码元/信源符号)\n",averageofhuffmancode);Eita=h/averageofhuffmancode;printf("哈夫曼编码的编码效率为:%lf\n",Eita);//求哈弗曼编码的码方差for(i=0;i<m;i++)cV+=INFORMATION[i].PROBABILITY*INFORMATION[i].lengthofhuffmancode *INFORMATION[i].lengthofhuffmancode;cV-=averageofhuffmancode*averageofhuffmancode;printf("哈弗曼编码的码方差为:%lf\n",cV);}5 运行结果截图:6 实验分析(1)在哈弗曼编码的过程中,对缩减信源符号按概率有大到小的顺序重新排列,应使合并后的新符号尽可能排在靠前的位置,这样可使合并后的新符号重复编码次数减少,使短码得到充分利用。
哈夫曼实验报告总结
哈夫曼实验报告总结
哈夫曼编码是一种常用的数据压缩算法,通过对频率较高的字符使用较短的编码,而对频率较低的字符使用较长的编码,从而实现对数据的高效压缩。
在哈夫曼编码的实验报告总结中,我们可以从以下几个方面进行全面回答:
1. 算法原理,首先可以简要介绍哈夫曼编码的原理,包括如何根据字符的频率构建哈夫曼树,以及如何根据哈夫曼树生成对应的编码表。
2. 实验过程,接着可以详细描述实验的具体过程,包括输入数据的准备、哈夫曼树的构建、编码表的生成以及对数据进行编码和解码的步骤。
3. 实验结果,然后可以总结实验的结果,包括使用哈夫曼编码前后数据的压缩比、编码效率以及解码的准确性等方面的数据和观察。
4. 应用场景,此外,还可以讨论哈夫曼编码在实际应用中的场景,例如在通信领域、数据存储领域以及多媒体压缩领域等方面的
应用。
5. 改进和展望,最后可以对哈夫曼编码进行改进的方向和未来的发展进行展望,例如基于哈夫曼编码的优化算法、并行计算等方面的研究。
通过以上多角度、详细的回答,可以全面总结哈夫曼编码实验报告的内容,并且保持严谨正确的用法和标点符号。
霍夫曼编码的实验报告(3篇)
第1篇一、实验目的1. 理解霍夫曼编码的基本原理和实现方法。
2. 掌握霍夫曼编码在数据压缩中的应用。
3. 通过实验,加深对数据压缩技术的理解。
二、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发环境:Visual Studio 20194. 数据源:文本文件三、实验原理霍夫曼编码是一种常用的数据压缩算法,适用于无损数据压缩。
它通过使用变长编码表对数据进行编码,频率高的数据项使用短编码,频率低的数据项使用长编码。
霍夫曼编码的核心是构建一棵霍夫曼树,该树是一种最优二叉树,用于表示编码规则。
霍夫曼编码的步骤如下:1. 统计数据源中每个字符的出现频率。
2. 根据字符频率构建一棵最优二叉树,频率高的字符位于树的上层,频率低的字符位于树下层。
3. 根据最优二叉树生成编码规则,频率高的字符分配较短的编码,频率低的字符分配较长的编码。
4. 使用编码规则对数据进行编码,生成压缩后的数据。
5. 在解码过程中,根据编码规则恢复原始数据。
四、实验步骤1. 读取文本文件,统计每个字符的出现频率。
2. 根据字符频率构建最优二叉树。
3. 根据最优二叉树生成编码规则。
4. 使用编码规则对数据进行编码,生成压缩后的数据。
5. 将压缩后的数据写入文件。
6. 读取压缩后的数据,根据编码规则进行解码,恢复原始数据。
7. 比较原始数据和恢复后的数据,验证压缩和解码的正确性。
五、实验结果与分析1. 实验数据实验中,我们使用了一个包含10000个字符的文本文件作为数据源。
在统计字符频率时,我们发现字符“e”的出现频率最高,为2621次,而字符“z”的出现频率最低,为4次。
2. 实验结果根据实验数据,我们构建了最优二叉树,并生成了编码规则。
使用编码规则对数据源进行编码,压缩后的数据长度为7800个字符。
将压缩后的数据写入文件,文件大小为78KB。
接下来,我们读取压缩后的数据,根据编码规则进行解码,恢复原始数据。
比较原始数据和恢复后的数据,发现两者完全一致,验证了压缩和解码的正确性。
实验二哈夫曼树及哈夫曼编码译码的实现
实验二哈夫曼树及哈夫曼编码译码的实现实验二:哈夫曼树及哈夫曼编码译码的实现(验证性、4学时) 一、实验目的和要求构建哈夫曼树及哈夫曼编码,输出哈夫曼树及哈夫曼编码,完成编码与译码的算法。
(1)掌握树的有关操作算法2)熟悉树的基本存储方法 ((3)学习利用树求解实际问题二、实验内容和原理定义哈夫曼树的存储结构;输入要编码的字符权重,根据权重建立哈夫曼树,并进行编码,最后输出哈夫曼编码。
三、实验环境硬件:(1)学生用微机(2)多媒体教室或远程教学(3)局域网环境软件:(1)Windows XP中文操作系统 (2)Turbo C 3.0 四、算法描述及实验步骤1( 算法描述(1) 建立叶子结点——由于每个叶子结点都有一个权重值,构造哈夫曼树的过程中每个分枝节点的权重值等于两个孩子结点权重值的和,所以应该有一个权重域和指向左右孩子的两个指针域;(2) 另外在建成哈夫曼树之后,为了求得每个叶子结点的哈夫曼编码,需要走一条从叶子结点到根结点的路径,而译码的过程是从根结点出发到叶子的不断匹配的过程,所以既需要知道孩子结点的信息,也需要知道双亲结点的信息,应该再有一个指向双亲结点的指针域。
(3) 构建哈夫曼编码——在已建好的哈夫曼树中从每个叶子结点开始沿双亲链域回退到根结点,每回退一步走过哈夫曼树的一个分枝得到一个哈夫曼编码值;由于每个叶子结点的哈夫曼编码是从根就诶点到相应叶子结点的路径上各分枝代码所组成的0、1序列,所以先得到的分枝代码为说求编码的低位码而后得到的为高位码。
2( 算法流程图构建哈夫曼树算法流程哈夫曼编码算法流程3( 代码#include<stdio.h>#define maxvalue 10000//定义最大权值常量#define maxnodenumber 100//定义结点最大数目常量 typedef struct{int weight;int parent,lchild,rchild; }htnode;typedef htnode *huffmantree;//定义哈夫曼树类型 htnodeht[maxnodenumber]; //定义静态三叉链表存储区数组#define maxbit 10//定义哈夫曼编码的最大长度 typedef struct//定义保存一个叶子结点哈夫曼编码的结构 {int bit[maxbit];//哈夫曼编码域为一维数组int start;//开始位置域为整型}hcodetype;//定义哈夫曼编码类型hcodetype cd[maxnodenumber];//定义存放哈夫曼编码的数组cd void crthuffmantree(int n);//建立哈夫曼树void gethuffmancode(int n);//哈夫曼编码void main (){int nodenum;printf("inputnodenum:"); scanf("%d",&nodenum);crthuffmantree(nodenum); gethuffmancode(nodenum); }void crthuffmantree(int n)//该算法对n个叶子结点建立哈夫曼树,权重值由键盘逐个输入{int i,j,m1,m2,k1,k2;//定义局部变量for(i=0;i<2*n-1;i++)//数组ht初始化{ht[i].weight=0;//权重初始化为0ht[i].parent=-1;//3个指针域初始化为-1,即NULL ht[i].lchild=-1;ht[i].rchild=-1;}for (i=0;i<n;i++)//读入n个叶子结点的权重值scanf("%d",&ht[i].weight); for(i=0;i<n-1;i++)//控制n-1趟生成新结点构造哈夫曼树 {m1=maxvalue;//预置最小权值变量为最大权值 m2=maxvalue;//预置次小权值变量为最大权值 k1=0;k2=0;//预置最小和次小权值结点位置为下标0处for (j=0;j<n+i;j++)//控制一趟中找处最小权值的结点if(ht[j].parent==-1&&ht[j].weight<m1){m2=m1;k2=k1;//若第j个结点权小于当前最小的m1改为次小的m1=ht[j].weight;k1=j;//并记下新的当前最小权值及位置}elseif(ht[j].parent==-1&&ht[j].weight<m2){m2=ht[j].weight;k2=j;}//否则若小于当前次小的m2则更新m2及其位置ht[k1].parent=n+i;//修改最小权值结点的双亲为刚生成的新结点ht[k2].parent=n+i;//修改次小权值结点的双亲刚好生成的新结点ht[n+i].weight=ht[k1].weight+ht[k2].weight;//填新生成结点的权重值ht[n+i].lchild=k1;//新生成结点的左孩子指针指向k1ht[n+i].rchild=k2;//新生成结点的右孩子指针指向k2}}void gethuffmancode(int n) /*对具有n个叶子结点的哈夫曼树ht,求所有叶子结点的哈夫曼编码并输出*/{int i,j,c,p; /*定义局部变量*/for(i=0;i<n;i++) /*定义存放哈夫曼编码的数组cd*/ {c=i;j=maxbit; /*为求一个结点的哈夫曼编码初始化c和j*/ do{j--; /*j指向bit中存放编码位的正确位置*/ p=ht[c].parent; /*p指向c 的双亲结点*/if(ht[p].lchild==c) /*如果c是p的左孩子*/cd[i].bit[j]=0; /*编码位上赋0*/elsecd[i].bit[j]=1; /*否则c是p的右孩子,编码位上赋1*/ c=p; /*更新c为p,为求下一个编码位做准备*/ }while(ht[p].parent!=-1); /*当未到达根结点继续做do循环*/ cd[i].start=j; /*求完一个叶子结点的哈夫曼编码时,记下编码开始位置*/}for(i=0;i<n;i++) /*输出n个叶子结点的哈夫曼编码*/{for(j=cd[i].start;j<maxbit;j++) /*逐位输出一个编码*/printf("%d",cd[i].bit[j]);printf("\n"); /*输出完一个哈夫曼编码后换行*/ }}五、调试过程一次编译二次编译三次编译六、实验结果七、总结(1) 深刻体会构建哈夫曼树的整个过程,对整体有个总的理解; (2) 复习以前所学C语言的一些语法,例如:for循环,if循环,while循环 (3) 理解哈夫曼的编码过程,编码思想(4) 此程序的不足之处在于在进行哈夫曼编码时未能对字符进行编制,有待改进。
哈夫曼编码实验报告
实验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的两个节点。
算法设计哈夫曼编码
if(h->element==NULL){
printf("out of space");
exit(-1);
}
h->element[0].f=-1;
for(i=1;i<=n;i++){
pushPrioQueue(h,tree[i]);//入队列
}
return h;
}
/*功能:用于生成哈夫曼树*/
huffman ctrHuffmanTree(int n){
while(encoding[j]!='\0'){
i=M;//从根开始遍历,至到叶子结点
while(tree[i].lchild!=-1 ||tree[i].rchild!=-1){
if(encoding[j]=='1'){
i=tree[i].rchild;//指向右孩子
}
else
{
i=tree[i].lchild;//左孩子
break;
}
}
ch=s[i];
}
printf("\n\n");
//输入编码,输出字符串
printf("input the binary string to deencoding:");
gets(encoding);
j=0;
//源码为:
printf("源码为");
puts(encoding);
printf("解码结果为:");
int m=2*n-1;//1~n存储叶子结点,n+1~m存储树的n-1个内部结点
huffman tree=(huffman)malloc(sizeof(huffmanNode)*(m+1));//用于存储哈夫曼树各结点
数据结构 哈夫曼编码实验报告(2023版)
数据结构哈夫曼编码实验报告实验目的:本实验旨在了解和实现哈夫曼编码算法,通过将字符转换为对应的哈夫曼编码来实现数据的压缩和解压缩。
一、引言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.构造哈夫曼树及哈夫曼编码:从终端读入字符集大小n、n 个字符以及n个对应的权值,建立哈夫曼树;利用已经建好的哈夫曼树求每个叶结点的哈夫曼编码,并保存。
2.编码:利用已构造的哈夫曼编码对“明文”文件中的正文进行编码,然后将结果存入“密文”文件中。
3.译码:将“密文”文件中的0、1代码序列进行译码。
(读文件) 4.打印“密文”文件:将文件以紧凑格式显示在终端上,每行30个代码;同时,将此字符形式的编码文件保存。
5.打印哈夫曼树及哈夫曼编码:将已在内存中的哈夫曼树以凹入表形式显示在终端上,同时将每个字符的哈夫曼编码显示出来;并保存到文件。
二、基本要求分析1、输入输出的要求按提示内容从键盘输入命令,系统根据用户输入的需求在保证界面友好的前提下输出用户所需信息,并按要求保存文件,以便保存备份信息。
2、测试数据(1).令叶子结点个数n为4,权值集合为{1,3,5,7},字符集合为{A,b,c,D},且字符集与权值集合一一对应。
(2).令叶子结点个数n为7,权值集合为{12,6,8,18,3,20,2},字符集合为{A,b,c,D,e,F,g},且字符集与权值集合一一对应。
(3).请自行选定一段英文文本,统计给出的字符集,实际统计字符的频度,建立哈夫曼树,构造哈夫曼编码,并实现其编码和译码。
三、概要设计1.主模块的流程及各子模块的主要功能主函数负责提供选项功能,循环调控整个系统。
创建模块实现接收字符、权值、构建哈夫曼树,并保存文件,此功能是后续功能的基础。
编码模块实现利用已编好的哈夫曼树对每个字符进行哈夫曼编码,即对每个字符译出其密文代码,并保存文件。
哈夫曼编码实验报告
实验报告与总结一、实验目的1、掌握哈夫曼编码原理;2、熟练掌握哈夫曼树的生成方法;3、理解数据编码压缩和译码输出编码的实现。
二、实验要求实现哈夫曼编码和译码的生成算法。
三、实验内容先统计要压缩编码的文件中的字符字母出现的次数,按字符字母和空格出现的概率对其进行哈夫曼编码,然后读入要编码的文件,编码后存入另一个文件;接着再调出编码后的文件,并对其进行译码输出,最后存入另一个文件中。
五、实验原理1、哈夫曼树的定义:假设有n个权值,试构造一颗有n个叶子节点的二叉树,每个叶子带权值为wi,其中树带权路径最小的二叉树成为哈夫曼树或者最优二叉树;2、哈夫曼树的构造:weight为输入的频率数组,把其中的值赋给依次建立的HT Node对象中的data属性,即每一个HT Node对应一个输入的频率。
然后根据data属性按从小到大顺序排序,每次从data取出两个最小和此次小的HT Node,将他们的data相加,构造出新的HTNode作为他们的父节点,指针parent,leftchild,rightchild赋相应值。
在把这个新的节点插入最小堆。
按此步骤可以构造构造出一棵哈夫曼树。
通过已经构造出的哈夫曼树,自底向上,由频率节点开始向上寻找parent,直到parent 为树的顶点为止。
这样,根据每次向上搜索后,原节点为父节点的左孩子还是右孩子,来记录1或0,这样,每个频率都会有一个01编码与之唯一对应,并且任何编码没有前部分是同其他完整编码一样的。
六、实验流程①初始化,统计文本文件中各字符的个数作为权值,生成哈夫曼树;②根据符号概率的大小按由大到小顺序对符号进行排序;③把概率最小的两个符号组成一个节点;④重复步骤(2)(3),直到概率和为1;⑤从根节点开始到相应于每个符号的“树叶”,概率大的标“0”,概率小的标“1”;⑥从根节点开始,对符号进行编码;⑦译码时流程逆向进行,从文件中读出哈夫曼树,并利用哈夫曼树将编码序列解码。
算法实验2-哈夫曼编码实验报告
算法实验2-哈夫曼编码实验报告
哈夫曼编码又称为霍夫曼编码,是1952年由克劳德·哈夫曼(Claude Elwood Shannon)提出的一种数据压缩和编码方法。
它可以从一个字符串中挑选出重复出现频率较高的字母等字符,将这些字母用比它们出现次数少的符号代替,从而达到减少数据存储空间的目的。
哈夫曼编码在文件压缩和网络传输中有着巨大的应用。
哈夫曼编码的原理基于信息论,利用熵的概念来实现数据压缩和编码。
熵是信息源发送信息的期望的信息量的度量,也就是说,发送的信息越多,熵越大。
所以,哈夫曼编码就是根据被发送信息的可能性来构造字符编码的,这样就能够优化发送的信息长度,从而实现数据压缩。
哈夫曼编码的基本步骤是:首先,根据待编码的字符统计其出现的频率,形成一棵二叉树;接着,给每个最底层的叶子节点分配编码,这里使用的是0和1来代替;最后,把最底层节点上的编码和字母相关联形成一个字符集。
哈夫曼编码得到的编码串中每个字符的编码长度都不一样,每个字符的编码长度取决于它出现的频率。
出现次数越多的字符编码得越短,这就使得哈夫曼编码能够获得比其他编码更短的编码长度,从而更好地完成数据压缩任务。
哈夫曼编码是实现数据压缩和编码的一种有效方法,它可以将数据压缩到最小可能的体积,同时使用起来非常简单。
它非常适用于实施网络传输的压缩处理,可以有效减少传输所需的时间,提高数据传输的效率。
实验报告-2Huffman编码
实验报告-2Huffman编码《信息与编码》课内实验报告学⽣姓名:及学号:学院:理学院班级:课程名称:信息与编码实验题⽬:Huffman编码指导教师副教授姓名及职称:讲师实验师2014年3⽉14⽇⽬录⼀、实验⽬的 (1)⼆、实验内容 (1)三、实验要点及说明 (1)四、实现⽅法 (1)五、实验结果 (2)六、源程序清单 (2)七、思考及总结 (5)⼀、实验⽬的1.掌握变长编码及即时码的特点; 2.理解Huffman 编码的特性及编码⽅法;⼆、实验内容对给定信源,统计信源分布,在信源概率分布确定情况下,进⾏Huffman 编码,并给出编码结果,并计算平均码长。
三、实验要点及说明通过matlab 编程,计算相应结果并绘制图形,理解相关性质。
四、实现⽅法以matlab 软件为基础,通过编程,对给出或计算出的概率分布计算相应Huffman 编码,并计算平均码长。
通过matlab 编程计算,步骤如下:1. ⽣成表⽰信源的概率分布p 和表⽰信号字母表的元包数组u ;2. 根据公式??=+-+-==.,,3,2,)1(,1,k j j k r j k j a t j 计算霍夫曼压缩表的列数k 和各列的⾏数j t ,为后⾯的计算做准备;3. 根据霍夫曼压缩表的构建⽅法,循环计算各概率列的数值,同时对各概率列排序并获取插⼊元素的位置(⿊框标记位置);4. 根据霍夫曼编码表的构建⽅法,从后往前计算出各列的霍夫曼编码;5. 将霍夫曼编码表中的第⼀列霍夫曼编码重新排序,得到最终霍夫曼编码。
五、实验结果霍夫曼编码表六、源程序清单运⾏命令:>> p=1./(8:16);>> p(10)=1-sum(p);>> for i=0:3u(i+1)={num2str(i)};end;>> [huff,summ,huffbiao] = huffman(p,u);源程序:function [huff,summ,huffbiao] = huffman(p,u) a=size(p,2); %获取第⼀列长度r=size(u,2); %获取信号字母个数huff=cell(1,a); %存储霍夫曼编码k=round((a-1)/(r-1)+0.5); %求列数huffbiao=cell(a,2*k); %存储霍夫曼压缩表t=zeros(1,k); %存储各列长度list=zeros(1,k-1); %存储标记位置pp=1:a; %标记排序后的位置t(1)=a;summ=0;for j=2:kt(j)=(k-j+1)*r-k+j; %求各列长度end;for j=a-1:-1:1 %⾸次排序for h=1:jp(h)=p(h+1);p(h+1)=temp;temp=pp(h);pp(h)=pp(h+1);pp(h+1)=temp;end;end;end;for i=1:ahuffbiao(i,1)={p(i)};end;for i=1:k-1temp=sum(p(t(i+1):t(i)));%求和num=0;for j=1:t(i+1) %插⼊,重排序if temp>=p(j)if temp>p(j) || j==t(i+1)num=num+1;end;temp1=p(j);p(j)=temp;temp=temp1;if num==1list(i)=j; %获取标记位置end;end;end;p(t(i+1)+1:t(i))=0; %将⽆⽤的部分置为0for h=1:t(i+1)huffbiao(h,2*i+1)={p(h)}; %⽣成霍夫曼压缩表end;end;for i=k:-1:1huff(j)=u(j); %给霍夫曼压缩表最后概率列赋值end;elsetemp=huff(list(i)); %缓存编码for h=list(i)+1:t(i+1)huff(h-1)=huff(h); %给该列的前段赋值,即将后⼀列的标记位后⾯的编码提前⼀位end;for j=t(i+1):t(i)huff(j)=strcat(temp,u(j-t(i+1)+1)); %给该列的后段赋值,即将后⼀列的标记位编码与信号字母表对应编码连接后赋值end;end;for h=1:t(i)huffbiao(h,2*i)=huff(h); %⽣成霍夫曼压缩表end;end;for j=a-1:-1:1 %霍夫曼编码排序for h=1:jif pp(h)>pp(h+1)temp=pp(h);pp(h)=pp(h+1);pp(h+1)=temp;temp=huff{h};huff{h}=huff{h+1};huff{h+1}=temp;end;end;end;for i=1:asumm=summ+huffbiao{i,1}*length(huffbiao{i,2}); %求平均码长end;huff=huff';end七、思考及总结本次课内实验我理解了信源的最优变长编码的基本思想,明⽩了霍夫曼编码是⼀种⽤于⽆损数据压缩的熵编码(权编码)算法,通过编程演算熟练地掌握了Huffman信源编码⽅法,同时了解了变长编码及即时码的特点。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
typedef struct
{
unsigned int weight; //用来存放各个结点的权值
unsigned int parent,LChild,RChild; //指向双亲、孩子结点的指针
} HTNode, *HuffmanTree; //动态分配数组,存储哈夫曼树
unsigned int c;
hc=(HuffmanCode *)malloc((n+1)*sizeof(char *));
cd=(char *)malloc(n*sizeof(char));
cd[n-1]='\0';
for(i=1; i<=n; i++) //求n个结点对应的哈夫曼编码
{
a[i]=0;
for(i=1; i<=n; i++)
w+=(*ht)[i].weight*a[i];
printf("\n带权路径长度WPL为:%d\n\n",w);
}
void main()
{
HuffmanTree HT;
HuffmanCode HC;
int *w,i,n,wei;
printf("\t\t\t\t哈夫曼编码\n" );
(*ht)[i].LChild=0;
(*ht)[i].parent=0;
(*ht)[i].RChild=0;
}
printf("\n所构造的哈夫曼树为: \n");
for(i=n+1; i<=m; i++) //创建非叶子结点,建哈夫曼树
{
Select(ht,i-1,&s1,&s2);
(*ht)[s1].parent=i;
实验报告是否规范:A.规范□B.基本规范□C.不规范□
实验过程是否详细记录:A.详细□B.一般 □C.没有 □
教师签名:
年 月 日
一、上机目的及内容
1.上机内容
设需要编码的字符集为{d1, d2, …, dn},它们出现的频率为{w1, w2, …, wn},应用哈夫曼树构造最短的不等长编码方案。
2.上机目的
a[i]++;
}
}
hc[i]=(char *)malloc((n-start)*sizeof(char)); //为第i个编码分配空间
strcpy(hc[i],&cd[start]);
}
free(cd);
for(i=1; i<=n; i++)
printf("权值为%d的哈夫曼编码为:%s\n",(*ht)[i].weight,hc[i]);
}
printf("\n");
}
//从叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码
void CrtHuffmanCode(HuffmanTree *ht, HuffmanCode *hc, int n)
{
char *cd; //定义的存放编码的空间
int a[100];
int i,start,p,w=0;
{
unsigned int weight;
unsigned int parent,LChild,RChild;
} HTNode, *HuffmanTree; //动态分配数组,存储哈夫曼树
typedef char *HuffmanCode; //动态分配数组,存储哈夫曼编码
void Select(HuffmanTree *ht,int n,int *s1,int *s2)
这次实验的内容是哈夫曼编码,哈夫曼树也就是最优二叉树,构造哈夫曼树的过程就是先在所有结点中找到权值最小的两个结点合并,依次这样找到较小的结点合并,最终生成哈夫曼树。树中所有叶子结点的带权路径长度之和最小,带权路径长度就是该结点到树根之间的路径长度与结点上权的乘积,且权值越大的叶子离跟越近。
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));
(1)了解前缀编码的概念,理解数据压缩的基本方法;
(2)掌握最优子结构性质的证明方法;
(3)掌握贪心法的设计思想并能熟练运用。
二、实验原理及基本技术路线图(方框原理图或程序流程图)
(1)证明哈夫曼树满足最优子结构性质;
(2)设计贪心算法求解哈夫曼编码方案;
(3)设计测试数据,写出程序文档。
数据结构与算法:
程序流程图:
三、所用仪器、材料(设备名称、型号、规格等或使用软件)
1台PC及VISUAL C++6.0软件
四、实验方法、步骤(或:程序代码或操作过程)
程序代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
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;
scanf("%d",&wei);
w[i]=wei;
}
CrtHuffmanTree(&HT,w,n);
CrtHuffmanCode(&HT,&HC,n);
}
五、实验过程原始记录( 测试数据、图表、计算等)
六、实验结果、分析和结论(误差分析与数据处理、成果总结等。其中,绘制曲线图时必须用计算纸或程序运行结果、改进、收获)
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';
a[i]++;
}
else
{
cd[--start]='0';
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);
}
}
*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)
昆明理工大学信息工程与自动化学院学生实验报告
(201—201学年第一学期)
课程名称:算法设计与分析 开课实验室:年 月 日
年级、专业、班
学号
姓名
成绩
实验项目名称
哈夫曼编码
指导教师
教师评语
该同学是否了解实验原理:A.了解□B.基本了解□C.不了解□
该同学的实验能力:A.强 □B.中等 □C.差 □
该同学的实验是否达到要求:A.达到□B.基本达到□C.未达到□
{
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;
(*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);