北邮信通院数据结构实验报告三哈夫曼编码器.pptx
实验三 哈夫曼编码

2013~2014 学年 班级: 第 二 学期 学号:
数据结构 实验报告
计算机科学与技术(专升本) 专业 姓名:
2013 级
实验三
一、 实验题目: 树的应用——哈夫曼编码进行通信可以大大提高信道的利用率,缩短信息传输的时间,降低传输成本。根据哈 夫曼编码的原理,编写一个程序,在用户输入结点权值的基础上求哈夫曼编码。 从键盘输入若干字符及每个字符出现的频率,将字符出现的频率作为结点的权值,建立哈夫曼树,求 出各字符的哈夫曼编码。要求: 1. 输出存放哈夫曼树的数组 HT 的初态和终态; 2. 输出每个字符的哈夫曼编码; 3. 输入由上述若干字符组成的字符串,对电文进行编码并输出; 4. (选作)输入电文的哈夫曼编码,进行译码并输出。
第 6 页
共 6 页
第 3 页 共 6 页
} void reverse(char a[],int &b) { char t,*p=a; for(int i=0,j=b-1;i<b/2;i++,j--) { t=*(p+i); *(p+i)=*(p+j); *(p+j)=t; } } void main() { char u[N],str[N]; int i,n,k,w[N]; HuffmanTree HT; HuffmanCode HC; printf("输入字符的个数:"); scanf("%d",&n); printf("分别输入这%d 个字符:\n",n); for(i=0;i<n;i++) { scanf("%c",&u[i]); getchar(); } printf("分别输入这%d 个字符对应的权值(以每个节点的频率的 10 倍输入):\n",n); for(i=0;i<n;i++) scanf("%d",&w[i]); printf("存放上述所输入\"字符\"的哈夫曼树的数组 HT 的状态如下:\n"); Huffmancoding(HT,HC,w,n); printf("以下是每个字符所对应的哈夫曼编码:\n"); for (i=1; i<=n; ++i) { printf("第%d 个字符所对应的哈夫曼编码是:",i); printf("%s\n",HC[i]); } printf("\n"); printf("(把上次输入的每个字符再依次输入,并存到 str 字符串中)\n"); printf("请输入:"); scanf("%s",str); k=strlen(str);
哈夫曼编码的实验报告

哈夫曼编码的实验报告哈夫曼编码的实验报告一、引言信息的传输和存储是现代社会中不可或缺的一部分。
然而,随着信息量的不断增加,如何高效地表示和压缩信息成为了一个重要的问题。
在这个实验报告中,我们将探讨哈夫曼编码这一种高效的信息压缩算法。
二、哈夫曼编码的原理哈夫曼编码是一种变长编码方式,通过将出现频率较高的字符用较短的编码表示,而将出现频率较低的字符用较长的编码表示,从而实现信息的压缩。
它的核心思想是利用统计特性,将出现频率较高的字符用较短的编码表示,从而减少整体编码长度。
三、实验过程1. 统计字符频率在实验中,我们首先需要统计待压缩的文本中各个字符的出现频率。
通过遍历文本,我们可以得到每个字符出现的次数。
2. 构建哈夫曼树根据字符频率,我们可以构建哈夫曼树。
哈夫曼树是一种特殊的二叉树,其中每个叶子节点代表一个字符,并且叶子节点的权值与字符的频率相关。
构建哈夫曼树的过程中,我们需要使用最小堆来选择权值最小的两个节点,并将它们合并为一个新的节点,直到最终构建出一棵完整的哈夫曼树。
3. 生成编码表通过遍历哈夫曼树,我们可以得到每个字符对应的编码。
在遍历过程中,我们记录下每个字符的路径,左边走为0,右边走为1,从而生成编码表。
4. 进行编码和解码在得到编码表后,我们可以将原始文本进行编码,将每个字符替换为对应的编码。
编码后的文本长度将会大大减少。
为了验证编码的正确性,我们还需要进行解码,将编码后的文本还原为原始文本。
四、实验结果我们选取了一段英文文本作为实验数据,并进行了哈夫曼编码。
经过编码后,原始文本长度从1000个字符减少到了500个字符。
解码后的文本与原始文本完全一致,验证了哈夫曼编码的正确性。
五、讨论与总结哈夫曼编码作为一种高效的信息压缩算法,具有广泛的应用前景。
通过将出现频率较高的字符用较短的编码表示,哈夫曼编码可以在一定程度上减小信息的存储和传输成本。
然而,哈夫曼编码也存在一些局限性,例如对于出现频率相近的字符,编码长度可能会相差较大。
哈夫曼编码实验报告

一、实验目的1.掌握MATLAB软件的使用,以及其设计流程;2.掌握哈夫曼编码的实现方法;3.用MATLAB语言设计哈夫曼编码的实现方法。
4.提高独立进行算法编程的能力。
二、实验仪器或设备装MATLAB软件的微机一台三、总体设计1、二进制Huffman编码的基本原理及算法1).将信源消息符号按其出现的概率大小依次排列为12...np p p≥≥≥2).取两个概率最小的字母分别配以0和1两个码元,并将这两个概率相加作为一个新字母的概率,与未分配的二进制符号的字母重新排队。
3).对重排后的两个概率最小符号重复步骤2的过程。
4).不断继续上述过程,直到最后两个符号配以0和1为止。
5).从最后一级开始,向前返回得到各个信源符号所对应的码元序列,即相应的码子。
2、程序设计的原理1)程序的输入:以一维数组的形式输入要进行huffman编码的信源符号的概率,在运行该程序前,显示文字提示信息,提示所要输入的概率矢量;然后对输入的概率矢量进行合法性判断,原则为:如果概率矢量中存在小于0的项,则输入不合法,提示重新输入;如果概率矢量的求和大于1,则输入也不合法,提示重新输入。
2)huffman编码具体实现原理:1>在输入的概率矩阵p正确的前提条件下,对p进行排序,并用矩阵L记录p排序之前各元素的顺序,然后将排序后的概率数组p的前两项,即概率最小的两个数加和,得到新的一组概率序列,重复以上过程,最后得到一个记录概率加和过程的矩阵p以及每次排序之前概率顺序的矩阵a。
2>新生成一个n-1行n列,并且每个元素含有n个字符的空白矩阵,然后进行huffman编码:将c矩阵的第n-1行的第一和第二个元素分别令为0和1(表示在编码时,根节点之下的概率较小的元素后补0,概率较大的元素后补1,后面的编码都遵守这个原则)然后对n-i-1的第一、二个元素进行编码,首先在矩阵a中第n-i行找到值为1所在的位置,然后在c矩阵中第n-i行中找到对应位置的编码(该编码即为第n-i-1行第一、二个元素的根节点),则矩阵c的第n-i行的第一、二个元素的n-1的字符为以上求得的编码值,根据之前的规则,第一个元素最后补0,第二个元素最后补1,则完成该行的第一二个元素的编码,最后将该行的其他元素按照“矩阵c中第n-i行第j+1列的值等于对应于a矩阵中第n-i+1行中值为j+1的前面一个元素的位置在c矩阵中的编码值”的原则进行赋值,重复以上过程即可完成huffman编码。
信息论课程实验报告—哈夫曼编码

*p2 = j;
}
}
void CreateHuffmanTree(HuffmanTree T)
{
int i,p1,p2;
InitHuffmanTree(T);
InputWeight(T);
for(i = n;i < m;i++)
4)依次继续下去,直至信源最后只剩下两个信源符号为止,将这最后两个信源符号分别用二元码符号“0”和“1”表示;
5)然后从最后—级缩减信源开始,进行回溯,就得到各信源符号所对应的码符号序列,即相应的码字。
四、实验目的:
(1)进一步熟悉Huffman编码过程;(2)掌握C语言递归程序的设计和调试技术。以巩固课堂所学编码理论的知识。
#include "stdio.h"
#include "stdlib.h"
#include <float.h>
#include <math.h>
#define n 8
#define m 2*n-1
typedef struct
{
float weight;
int lchild,rchild,parent;
}
}
void InputWeight(HuffmanTree T)
{
float temp[n] = {0.20,0.18,0.17,0.15,0.15,0.05,0.05,0.05};
for(int i = 0;i < n;i++)
T[i].weight = temp[i];
}
北邮-数据结构-哈夫曼树报告

数据结构之阳早格格创做真验报告真验称呼:哈妇曼树教死姓名:袁普班级:2013211125班班内序号:14号教号:2013210681日期:2014年12月1.真验手段战真质利用二叉树结构真止哈妇曼编/解码器.基原央供:1、初初化(Init):不妨对于输进的任性少度的字符串 s举止统计,统计每个字符的频度,并修坐哈妇曼树2、修坐编码表(CreateTable):利用已经修佳的哈妇曼树举止编码,并将每个字符的编码输出.3、编码(Encoding):根据编码表对于输进的字符串举止编码,并将编码后的字符串输出.4、译码(Decoding):利用已经修佳的哈妇曼树对于编码后的字符串举止译码,并输出译码截止.5、挨印(Print):以曲瞅的办法挨印哈妇曼树(选做)6、估计输进的字符串编码前战编码后的少度,并举止分解,计划赫妇曼编码的压缩效验.7、可采与二进造编码办法(选做)尝试数据:I love data Structure, I love Computer.I will try my best to study data Structure.提示:1、用户界里不妨安排为“菜单”办法:不妨举止接互.2、根据输进的字符串中每个字符出现的次数统计频度,对于不出现的字符一律不必编码2. 步调分解2.1 保存结构用struct结构典型去真止保存树的结面典型struct HNode{int weight; //权值int parent; //女节面int lchild; //左孩子int rchild; //左孩子};struct HCode //真止编码的结构典型{char data; //被编码的字符char code[100]; //字符对于应的哈妇曼编码};2.2 步调过程2.3算法1:void Huffman::Count()[1] 算法功能:对于出现字符的战出现字符的统计,构修权值结面,初初化编码表[2] 算法基原思维:对于输进字符一个一个的统计,并统计出现次数,构修权值数组,[3] 算法空间、时间搀纯度分解:空间搀纯度O(1),要遍历一遍字符串,时间搀纯度O(n)[4] 代码逻辑:leaf=0; //初初化叶子节面个数int i,j=0;int s[128]={0}; 用于保存出现的字符for(i=0;str[i]!='\0';i++) 遍历输进的字符串s[(int)str[i]]++; 统计每个字符出现次数for(i=0;i<128;i++)if(s[i]!=0){data[j]=(char)i; 给编码表的字符赋值weight[j]=s[i]; 构修权值数组j++;}leaf=j; //叶子节面个数即字符个数for(i=0;i<leaf;i++)cout<<data[i]<<"的权值为:"<<weight[i]<<endl;算法2:void Init();[1] 算法功能:构修哈弗曼树[2] 算法基原思维:根据哈妇曼树构修央供,采用权值最小的二个结面分离,新结面加进数组,再继承采用最小的二个结面继承构修.[3] 算法空间、时间搀纯度分解:与决于叶子节面个数,时间搀纯度O(n),空间搀纯度O(1)[4] 代码逻辑HTree=new HNode[2*leaf-1]; n2=n0-1,一同需要2n-1个结面空间for(int i=0;i<leaf;i++){HTree[i].weight=weight[i]; 给每个结面附权值HTree[i].lchild=-1; 初初化安排孩子战女节面,皆为-1HTree[i].rchild=-1;HTree[i].parent=-1;}int x,y; //用于记录二个最小权值for(int i=leaf;i<2*leaf-1;i++){Selectmin(HTree,i,x,y); 选出二个最小权值的结面HTree[x].parent=i; 女节面树坐为新修坐的结面 HTree[y].parent=i;HTree[i].weight=HTree[x].weight+HTree[y].weight; 女节面权值为二个相加HTree[i].lchild=x; 使女节面指背那二个孩子结面HTree[i].rchild=y;HTree[i].parent=-1; 女节面的女节面设为-1 }算法3:void Selectmin(HNode*hTree,int n,int&i1,int &i2);[1] 算法功能:从现有的结面中采用出二个最小的结面,返回其位子[2] 算法基原思维:先选出二个不构修的结面,而后背后依次比较,筛选出最小的二个结面[3] 算法空间、时间搀纯度分解:空间搀纯度O(1),要遍历所有结面,时间复纯度O(N)[4] 代码逻辑int i;for(i=0;i<n;i++) //n为目前有的结面个数,是个变更值,会有相加后的新权值加进{if(hTree[i].parent==-1) //女节面不是-1表示着那个结面还不被采用过{i1=i; 记录结面位子break;}}i++; //真止一遍for循环便加1,意为下次查找从目前位子启初查找for(;i<n;i++){if(hTree[i].parent==-1){i2=i; 记录第二个出采用过的结面编号break;}}if(hTree[i1].weight>hTree[i2].weight) 举止比较,使I1为最小的,I2为第二小的{int j=0;j=i2;i2=i1;i1=j;}i++;for(;i<n;i++) 将I1 I2 与后里的结面举止比较{if(hTree[i].parent==-1&&hTree[i].weight<hTree[i1].weight) 如果结面小于I1{i2=i1; 使I2=I1 I1=新结面i1=i;}else if(hTree[i].parent==-1&&hTree[i].weight<hTree[i2].weight){ I1《新结面《I2,使I2为新节面i2=i;}}算法4:void CreateTable();[1] 算法功能:对于出现的字符举止编码[2] 算法基原思维:根据字符正在哈妇曼树中的位子,从下到上编码,是左孩子编0,左孩子编1[3] 算法空间、时间搀纯度分解:空间搀纯度O(1),要遍历data数组,时间搀纯度0(N)[4] 代码逻辑HCodeTable=new HCode[leaf]; 新修编码结面,个数为叶子节面个数for(int i=0;i<leaf;i++){HCodeTable[i].data=data[i];int child=i; 初初化要编码的结面的位子int parent=HTree[i].parent; 初初化女结面int k=0; //统计编码个数while(parent!=-1){if(child==HTree[parent].lchild)HCodeTable[i].code[k]='0'; //左孩子标‘0’elseHCodeTable[i].code[k]='1'; //左孩子标‘1’k++;child=parent; 孩子结面上移parent=HTree[child].parent; 女节面也上移}HCodeTable[i].code[k]='\0'; //将编码反背char code[100];for(int u=0;u<k;u++)code[u]=HCodeTable[i].code[k-u-1];for(int u=0;u<k;u++)HCodeTable[i].code[u]=code[u];cout<<data[i]<<"的哈妇曼编码为:";cout<<HCodeTable[i].code<<endl;length3[i]=k; //每一个字符编码的少度,为供编码总少度干准备}算法5:void Encoding();[1] 算法功能:对于输进的字符串举止编码[2] 算法基原思维:找到每个字符对于应的编码,将编码按程序输出[3] 算法空间、时间搀纯度分解:空间搀纯度O(1),时间搀纯度0(n)[4] 代码逻辑cout<<endl<<"输进的字符串转移为哈妇曼编码为:"<<endl;for (int i=0;str[i]!='\0';i++) 遍历输进的每一个字符{for(int j=0;j<leaf;j++)if(str[i]==HCodeTable[j].data) 找到字符对于应的编码{ s1=s1+HCodeTable[j].code; 将所有编码按程序加起去cout<<HCodeTable[j].code; 输出编码 }}cout<<endl;算法6:void Decoding();[1] 算法功能:对于编码串举止解码[2] 算法基原思维:找到每段编码对于应的字符,输出字符[3] 算法空间、时间搀纯度分解:时间搀纯度0(N),空间搀纯度0(1)[4] 代码逻辑(可用真代码形貌)cout<<"解码后的字符串为: "<<endl;char *s = const_cast<char*>(s1.c_str()); 将编码字符串转移为charwhile(*s!='\0'){int parent=2*leaf-2; 女节面为末尾一个节面while(HTree[parent].lchild!=-1) //另有左子树,不可能是叶子节面{if(*s=='0') 编码为0,为左孩子parent=HTree[parent].lchild;elseparent=HTree[parent].rchild; 编码为1,为左孩子s++;}cout<<HCodeTable[parent].data; 输出字符}cout<<endl;……注意分解步调的时间搀纯度、内存申请战释搁,以及算法思维的体现.2.4 其余正在此次考查中使用了类战STL中的string,使用string不妨便当的将单个字符的编码加起去成为总的编码后的数值,再利用STL中的转移函数不妨间接将string 转移为char,便当举止解码处事.总而止之,使用STL使得编码大大的简净了.3.步调运止截止分解调试历程中逢到的问题主假如真止时有内存过失,查看后创造是数组有越界局里,那指示尔正在编写时一定要小心,特地是正在for循环条件上一定要注意范畴归纳最先正在输进字符串时尔创造间接用cin无法输进空格,正在上钩查询后找到了getline函数办理了那个问题.而后另有便是怎么样保存编码后总的那个字符串,果为每一个字符编码的少度大概,无法用char数组去保存,于是用了string 的相加函数去将所有编码加起去.末尾由于正在解码时要用char数组,又上钩查询到了string转移成char的函数办理了那个问题,真验易面也正在于怎么样找到二个最小权值去构修哈妇曼树,觅找二个最小权值的思维主假如通过一个个的比较去找到最小值,而且注意形参要用引用.通过此次真验尔体验到了stl的劣良性.另有便是编码时要注意数组的大小.再者便是有问题时不妨试着去网上查询问案.。
哈弗曼编码数据结构实验报告

数据结构实验报告----约瑟夫环一、需求分析:约瑟夫环是程序的一道经典例题,可以使用数据结构的单链表进行编写。
二、概要设计:大体上可以使用单链表通过节点的创建和删除来达到人数出列的效果,可以大大缩短程序量。
三、详细设计:1、首先定义一个单链表,然后分别做创建链表、以及对应的输入数据,删除节点对应的删除数据,以及输出功能。
最后用主函数实现上述功能。
下为程序源代码:#include<stdio.h>#include<malloc.h>typedef struct Lnode //创建一个单链表{int num;int key;struct Lnode *next;}Joseph;struct Lnode *head,*p,*p1;int creatlinklist(int n) //为节点分配内存,创建节点{int i=0;head = (struct Lnode*)malloc(sizeof(struct Lnode));if(!head){return 0;}p=head;for(i = 0;i<n-1;i++){p1=(struct Lnode*)malloc(sizeof(struct Lnode));if(!p1){return 0;}p->next=p1;p=p1;}p->next=head;p1=head;return 0;}int input(int n) //在分配的节点上输入数据{int i=0;int j=0;printf("please input the keys:\n");for(i =1;i<n+1;i++){scanf("%d",&j);p1->num=i;p1->key=j;p1=p1->next;}p1=p;return j;}int output(int m,int n) \\在约瑟夫环的规定上输出数据删除节点{int i=0;int a=0;for(i =0;i <n;i++){for(a=0;a<m-1;a++){p1=p1->next;}p=p1->next;m=p->key;printf("%d\n",p->num);p1->next=p->next;free(p);}return 0;}void main(){int m=0;int n=0;printf("请输入上限值和人数值:\n");scanf("%d%d",&m,&n);creatlinklist(n);input(n);printf("出对的人:\n");output(m,n);}四、调试分析:程序仅能使用一次,并且输入格式没有提示,容易犯错。
哈夫曼编码报告

实验项目:哈夫曼编码5.实验步骤(含实验代码)第i次:完成程序的主框架设计,进行调试,验证其正确性;第2次:详细设计,进行调试,验证其正确性;第3次:进行整体调试,运行程序,对运行结果进行分析,完成实验报告#i nclude<stdio.h>#i nclude<stri ng.h>#i nclude<malloc.h>#defi ne MAXWORD 100typedef struct{ un sig ned int weight;char data;un sig ned int pare nt,llchild,rrchild;typedef char * *HuffmanCode;/ / 动态分配数组存储哈夫曼编码typedef struct tnode{ char ch;struct tnode *lchild,*rchild;}BTree,*BT;int a=0,b=0;int s[MAXWORD];char str[MAXWORD];void main(){ int n;int i=0;HuffmanTree HT;HuffmanCode HC;void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int n);void DispHCode(HuffmanTree HT,HuffmanCode HC,int n);void Creatree(BT &p,char c); //Creatree() 和InOrderTraverse()void InOrderTraverse(BT p); // 利用二叉树统计出现的字符及 个数 void TTranChar(HuffmanTree HT,HuffmanCode HC,int n);void Tran(HuffmanTree HT,int n); printf(" 请输入要用几种字符: "); }HTNode,*HuffmanTree;// 动态分配数组存储哈夫曼树// 字符 int count;// 出现次数scanf("%d",&n);BT root=NULL;printf("\n");printf(" 请输入字符串 :\n"); scanf("%s",str);while(str[i]!='\0'){Creatree(root,str[i]);i++;}printf(" 字符及出现次数 :\n");InOrderTraverse(root);printf("\n");HuffmanCoding(HT,HC,n);DispHCode(HT,HC,n);Tran(HT,n);TTranChar(HT,HC,n);void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int n) { // w 放 n 个权值 , 构造赫夫曼树 HT,n 个字符编码 HC void select(HuffmanTree t,int i,int &s1,int &s2);int m,i,s1,s2,start;char *cd;unsigned c,f;HuffmanTree p;if(n<=1) return;m=2*n-1;HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));for(p=HT+1,i=1;i<=n;++i,++p){ (*p).parent=0;(*p).llchild=0;(*p).rrchild=0;}for(p=HT+1,i=0;i<n;++i,++p){ (*p).data=str[i];(*p).weight=s[i];for(;i<=m;++i,++p)(*p).parent=0;for(i=n+1;i<=m;++i) // 建赫夫曼树{ // 在 HT[1~i-1] 中选择 parent 为 0 且 weight s2select(HT,i-1,s1,s2);HT[s1].parent=HT[s2].parent=i;HT[i].llchild=s1;HT[i].rrchild=s2;HT[i].weight=HT[s1].weight+HT[s2].weight;}HC=(HuffmanCode)malloc((n+1)*sizeof(char*));//([0] cd=(char*)malloc(n*sizeof(char));cd[n-1]='\0'; //for(i=1;i<=n;i++)// 编码结束符位置for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)if(HT[f].llchild==c) 最小的两个,分别s1 、不用)编码结束符{ start=n-1;cd[--start]='0';elsecd[--start]='1';HC[i]=(char*)malloc((n-start)*sizeof(char));strcpy(HC[i],&cd[start]); // 复制}free(cd);}void select(HuffmanTree t,int i,int &s1,int &s2) // s1 为较小{ int min(HuffmanTree t,int i);int j;s1=min(t,i);s2=min(t,i);if(s1>s2){j=s1;s1=s2;s2=j;}}int min(HuffmanTree t,int i) {int j,flag;unsigned int k=100;for(j=1;j<=i;j++)if(t[j].weight<k&&t[j].paren t==0)k=t[j].weight,flag=j;t[flag].parent=1;return flag;}void Creatree(BT &p,char c){if(p==NULL)// 函数 void select() 调用// 取 k 比任何权值都大// 采用递归方式构造一棵二叉排序树//p 为 NULL ,则建立一个新结点{p=(BTree* )malloc(sizeof(BTree));p->ch=c;p->count=1;p->lchild=p->rchild=NULL;}elseif(c==p->ch) p->count++;elseif(c<p->ch) Creatree(p->lchild,c);else Creatree(p->rchild,c);}void InOrderTraverse(BT p) // 中序遍历{if(p!=NULL){ InOrderTraverse(p->lchild);{printf("%c 的个数为 :%d\n",p->ch,p->count);s[b]=p->count;b++;str[a]=p->ch;a++;}InOrderTraverse(p->rchild);} }void DispHCode(HuffmanTree HT,HuffmanCode HC,int n)1 编码{int i;printf(" 输出哈夫曼编码 :\n");for(i=1;i<=n;i++){ printf("%c:\t",HT[i].data);puts(HC[i]);}}void Tran(HuffmanTree HT,int n) // 将含 0 、{int i,j=0;char cc[MAXWORD];i=2*n-1;printf(" 输入发送的(0 、1)编码(以'#'为结束标志 ):"); scanf("%s",cc);// 显示0 、1 的编码翻译成字符printf(" 译码后的字符为 ");while(cc[j]!='#'){if(cc[j]=='0')i=HT[i].llchild;elsei=HT[i].rrchild;if(HT[i].llchild==0){printf("%c",HT[i].data);i=2*n-1; }j++;}printf("\n");}void TTranChar(HuffmanTree HT,HuffmanCode HC,int n)printf(" 输入字符串 :"); scanf("%s",ss);i=0;while(ss[i]!='\0'){j=1;while((HT[j].data!=ss[i])&&(j<=n)){j++;}printf("%s",HC[j]);i++;}printf("\n");}6.实验结果与总结:char ss[50];int i,j;// 将字符串翻译成 0、1 代码总结:在实现哈夫曼树编码的过程中,首先构建哈夫曼树,并用动态分配数组存储,也用动态分配数组存储哈夫曼编码表。
哈夫曼编码译码器实验报告

哈夫曼编码译码器实验报告实验名称:哈夫曼编码译码器实验一、实验目的: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.比较编码前后字符串的内容,结果正确。
五、实验总结:通过本次实验,我了解了哈夫曼编码的原理和应用,并且实现了一个简单的哈夫曼编码的编码和译码器。
在实验过程中,我充分运用了数据结构中的树的知识,构建了一个哈夫曼树,并生成了编码表。
通过编码和译码过程,我进一步巩固了对树的遍历和节点查找的理解。
实验结果表明,本次哈夫曼编码的编码和译码过程正确无误。
在实验的过程中,我发现哈夫曼编码对于频率较高的字符具有较短的编码,从而实现了对字符串的高效压缩。
同时,哈夫曼编码还可以应用于数据传输和存储中,提高数据的传输效率和存储空间的利用率。
通过本次实验,我不仅掌握了哈夫曼编码的编码和译码过程,还深入了解了其实现原理和应用场景,加深了对数据结构和算法的理解和应用能力。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
-1
2.2 关键算法分析 (1)计算出现字符的权值
利用 ASCII 码统计出现字符的次数,再将未出现的字符进行筛选,将出现的字符及頻 数存储在数组 a[]中。
void Huffman::Init() {
int nNum[256]= {0}; //记录每一个字符出现的次数 int ch = cin.get();
第2页
北京邮电大学信息与通信工程学 院
2
-1
-1
-1
5
-1
-1
-1
6
-1
-1
-1
7
-1
-1
-1
9
-1
-1
-1
weight lchild rchild parent
2
-1
-1
5
5
-1
-1
5
6
-1
-1
6
7
-1
-1
6
9
-1
-1
7
7
0
1
7
第3页
北京邮电大学信息与通信工程学 院
13
2
3
8
16
5
4
8
29
6
7
2、建立编码表(CreateTable):利用已经建好的赫夫曼树进行编码,并将每 个字符的编码输出。
3、编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的 字符串输出。
4、译码(Decoding):利用已经建好的赫夫曼树对编码后的字符串进行译 码,并输出译码结果。
5、打印(Print):以直观的方式打印赫夫曼树(选作) 6、计算输入的字符串编码前和编码后的长度,并进行分析,讨论赫夫
int i=0; while((ch!='\r') && (ch!='\n')) {
nNum[ch]++; // 统 计 字 符 出 现 的 次 数 str[i++] = ch; // 记 录 原 始 字 符 串 ch = cin.get(); // 读 取 下 一 个 字 符 } str[i]='\0';
} int x,y; for (int i = n; i < 2*n-1; i++) //开始建 Huffman 树 {
SelectMin( HTree, i, x, y); //从 1~i 中选出两个权值最小的结点 HTree[x].parent = HTree[y].parent = i; HTree[i].weight = HTree[x].weight+ HTree[y].weight; HTree[i].LChild = x; HTree[i].RChild = y; HTree[i].parent = -1; } } 时间复杂度为 O(n2) void Huffman::SelectMin( HNode *hTree,int n, int &i1, int &i2 ) { int i; //找一个比较值的起始值 for(i=0; i<n; i++) //找 i1 { if(hTree[i].parent==-1 )
北京邮电大学信息与通信工程学 院
数据结构实验报告
实验名称: 实验三 树——哈夫曼编/解码器 学生姓名: 班 级: 班内序号: 学 号:
日 期: 2014 年 12 月 11 日
1. 实验要求
利用二叉树结构实现赫夫曼编/解码器。 基本要求:
1、初始化(Init):能够对输入的任意长度的字符串 s 进行统计,统计每个 字符的频度,并建立赫夫曼树
2. 程序分析
第1页
北京邮电大学信息与通信工程学院
2.1 存储结构 Huffman 树 给定一组具有确定权值的叶子结点,可以构造出不同的二叉树,其中带权路径 长 度 最 小 的 二 叉 树 称 为 Huffman 树 , 也 叫 做 最 优 二 叉 树 。
weight lchild rchild parent
Huffman 树采用顺序存储---数组; 数组的前 n 个结点存储叶子结点,然后是分支结点,最后是根结点; 首先初始化叶子结点元素—循环实现; 以循环结构,实现分支结点的合成,合成规则按照 huffman 树构成 Huffman::CreateHTree() {
HTree = new HNode [2*n-1]; //根据权重数组 a[0..n-1] 初始化 Huffman 树 for (int j = 0; j < n; j++)
第5页
北京邮电大学信息与通信工程学 院
{ HTree[j].weight = a[j]; HTree[j].LChild = HTree[j].RChild = HTree[j].parent = -1;
&& hTree[i].weight < hTree[i1].weight ) { i2=i1; i1 = i; } else if( hTree[i].parent==-1
&& hTree[i].weight < hTree[i2].weight) { i2=i; } } } 时间复杂度为 O(n) (3)创建编码表
第7页
曼 编码的压缩效果。 测试数据:
I love data Structure, I love Computer 。 I will try my best to study data Structure.
提示: 1、用户界面可以设计为“菜单”方式:能够进行交互。 2、根据输入的字符串中每个字符出现的次数统计频度,对没有出现的 字符一律不用编码。
n = 0;
第4页
北京邮电大学信息与通信工程学 院
for ( i=0;i<256;i++) {
if (nNum[i]>0) // 若 nNum[i]==0, 字 符 未 出 现 {
l[n] = (char)i; a[n] = nNum[i]; n++; } } } 时间复杂度为 O(1); (2)创建哈夫曼树: 算法过程:
第6页
北京邮电大学信息与通信工程学 院
{ i1=i; break; } } i++; for( ; i<n; i++) //找 i2 { if(hTree[i].parent==-1 )
{ i2=i; break; } } if(hTree[i1].weight>hTree[i2].weight) //i1 指向最小的 { int j=i2; i2=i1; i1 = j; } //开始找最小的两个 i++; for( ; i<n; i++) { if(hTree[i].parent==-1