(完整word版)实验七 哈夫曼编码实验

合集下载

《哈夫曼编码》实验报告

《哈夫曼编码》实验报告

《哈夫曼编码》实验报告《哈夫曼编码》实验报告一、实验目的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. 实验目的本实验旨在通过实践理解哈夫曼编码的原理和实现方法,加深对数据结构中树的理解,并掌握使用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.输入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。

哈夫曼树编码实验报告

哈夫曼树编码实验报告

哈夫曼树编码实验报告哈夫曼树编码实验报告引言:哈夫曼树编码是一种常用的数据压缩算法,通过对数据进行编码和解码,可以有效地减小数据的存储空间。

本次实验旨在探究哈夫曼树编码的原理和应用,并通过实际案例验证其有效性。

一、哈夫曼树编码原理哈夫曼树编码是一种变长编码方式,根据字符出现的频率来确定不同字符的编码长度。

频率较高的字符编码较短,频率较低的字符编码较长,以达到最佳的数据压缩效果。

1.1 字符频率统计首先,需要对待编码的数据进行字符频率统计。

通过扫描数据,记录每个字符出现的次数,得到字符频率。

1.2 构建哈夫曼树根据字符频率构建哈夫曼树,频率较低的字符作为叶子节点,频率较高的字符作为父节点。

构建哈夫曼树的过程中,需要使用最小堆来维护节点的顺序。

1.3 生成编码表通过遍历哈夫曼树,从根节点到每个叶子节点的路径上的左右分支分别赋予0和1,生成对应的编码表。

1.4 数据编码根据生成的编码表,将待编码的数据进行替换,将每个字符替换为对应的编码。

编码后的数据长度通常会减小,实现了数据的压缩。

1.5 数据解码利用生成的编码表,将编码后的数据进行解码,恢复原始数据。

二、实验过程与结果为了验证哈夫曼树编码的有效性,我们选择了一段文本作为实验数据,并进行了以下步骤:2.1 字符频率统计通过扫描文本,统计每个字符出现的频率。

我们得到了一个字符频率表,其中包含了文本中出现的字符及其对应的频率。

2.2 构建哈夫曼树根据字符频率表,我们使用最小堆构建了哈夫曼树。

频率较低的字符作为叶子节点,频率较高的字符作为父节点。

最终得到了一棵哈夫曼树。

2.3 生成编码表通过遍历哈夫曼树,我们生成了对应的编码表。

编码表中包含了每个字符的编码,用0和1表示。

2.4 数据编码将待编码的文本数据进行替换,将每个字符替换为对应的编码。

编码后的数据长度明显减小,实现了数据的压缩。

2.5 数据解码利用生成的编码表,将编码后的数据进行解码,恢复原始文本数据。

(完整word版)数据结构课程设计(哈夫曼编码)

(完整word版)数据结构课程设计(哈夫曼编码)

目录目录 (1)1 课程设计的目的和意义 (3)2 需求分析 (5)3 系统设计 (6)(1)设计思路及方案 (6)(2)模块的设计及介绍 (6)(3)主要模块程序流程图 (9)4 系统实现 (14)(1)主调函数 (14)(2)建立HuffmanTree (14)(3)生成Huffman编码并写入文件 (18)(4)电文译码 (19)5 系统调试 (22)小结 (25)参考文献 (26)附录源程序 (27)1 课程设计的目的和意义在当今信息爆炸时代,如何采用有效的数据压缩技术来节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视。

哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。

哈夫曼编码的应用很广泛,利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。

树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0"码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1"的序列作为和各个对应的字符的编码,这就是哈夫曼编码。

通常我们把数据压缩的过程称为编码,解压缩的过程称为解码。

电报通信是传递文字的二进制码形式的字符串。

但在信息传递时,总希望总长度尽可能最短,即采用最短码。

作为软件工程专业的学生,我们应该很好的掌握这门技术。

在课堂上,我们能过学到许多的理论知识,但我们很少有过自己动手实践的机会!课程设计就是为解决这个问题提供了一个平台。

在课程设计过程中,我们每个人选择一个课题,认真研究,根据课堂讲授内容,借助书本,自己动手实践。

这样不但有助于我们消化课堂所讲解的内容,还可以增强我们的独立思考能力和动手能力;通过编写实验代码和调试运行,我们可以逐步积累调试C程序的经验并逐渐培养我们的编程能力、用计算机解决实际问题的能力。

在课程设计过程中,我们不但有自己的独立思考,还借助各种参考文献来帮助我们完成系统。

更为重要的是,我们同学之间加强了交流,在对问题的认识方面可以交换不同的意见.同时,师生之间的互动也随之改善,我们可以通过具体的实例来从老师那学到更多的实用的知识。

哈夫曼编码实验报告

哈夫曼编码实验报告
哈夫曼树的构造过程:
从一组权中取最小的两个权数作为叶子构成一个简单的树单元(根为两个权值的合)。

从这组权中去除这两个已经构成树单元的权,并把该树单元的根的权加入其中,重新选两个最小权数构成树单元,重复以上,直至所有权都被填入树中。

什么是最优带权二叉树:
所有叶子元素的权数*深度(可以理解为路径长)的和最小的树,哈夫曼树就是一种最优带权二叉树(待证明)。

为何要找最优二叉树:
哈夫曼编码是最优二叉树的应用之一。

简单来说哈夫曼编码是一种变长编码方式,通过压缩对象中各个元素的出现频度,生成一个特殊的编码表。

编码表中频度(出现次数)越高的元素,表示的编码长度越
短,所有元素的(出现次数*标识编码长度)求和就是压缩后文件的大小,这正是最优二叉树拥有的特性(总权和最小)。

交换操作对除这两个叶子之外的叶子的权重总值不会造成影响,重新计算这两个叶子的权重和即可,假设其余权重和为X。

交换前:T1=X+(n+q)*a+n*c
交换后:T2=X+(n+q)*c+n*a
由于要证T1<T2
X+(n+q)*a+n*c < X+(n+q)*c+n*a
处理后得到q*(a-c)<0
命题中深度差为正数,即要证a<c,即A叶子的权数小于C叶子的权数。

命题中A比C深,且该树是哈夫曼树。

哈夫曼树构造过程是由小到大的,若c<a,那么c会比a先组成单元或者C和A组成单元,先组成单元则C的深度大于A,C和A组成单元则这两个叶子深度相同,都不符合A比C深的命题,得证a<c。

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

数据结构哈夫曼编码实验报告【正文】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.结论通过本次实验,我们深入了解了哈夫曼编码的原理和实现方法,实践了哈夫曼编码的过程,并对其在数据压缩中的有效性进行了验证。

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

哈夫曼编码实验超详尽版


编码步骤
6



在F中选取两棵根结点权值最小的树作为新构造 的二叉树的左右子树,新二叉树的根结点的权 值为其左右子树的根结点的权值之和。 从F中删除这两棵树,并把这棵新的二叉树同样 以升序排列加入到集合F中。 重复二和三两步,直到集合F中只有一棵二叉树 为止。
示例
7

假如有A,B,C,D,E五个字符,出现的频率(即权值) 分别为5,4,3,2,1,那么我们第一步先取两个最小权值 作为左右子树构造一个新树,即取1,2构成新树, 其结点为1+2=3,如图:
原理
3

首先统计信源中各符号出现的概率,按符号出现的
概率从大到小排序; 把最小的两个概率相加合并成新的概率,与剩余的 概率组成新的概率集合; 对新的概率集合重新排序,再次把其中最小的两个 概率相加,组成新的概率集合。如此重复进行,直 到最后两个概率的和为l;原理4 Nhomakorabea
分配码字:码字分配从最后一步开始反向进行,
9


实现过程:首先通过 HuffmanTree() 函数构造哈夫 曼树,然后在主函数 main()中自底向上开始(也就 是从数组序号为零的结点开始)向上层层判断,若 在父结点左侧,则置码为 0,若在右侧,则置码为 1。 最后输出生成的编码。 typedef struct
{ int bit[MAXBIT]; int start; } HCodeType; /* 编码结构体 */
五、程序部分代码及其分析
13
/* 设置找到的两个子结点 x1、x2 的父结点信息 */ HuffNode[x1].parent = n+i; HuffNode[x2].parent = n+i; HuffNode[n+i].weight = HuffNode[x1].weight + HuffNode[x2].weight; HuffNode[n+i].lchild = x1; HuffNode[n+i].rchild = x2;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

实验七哈夫曼编码
哈夫曼编码
1. 问题描述
设某编码系统共有n个字符,使用频率分别为{w1, w2,…, w n},设计一个不等长的编码方案,使得该编码系统的空间效率最好。

2. 基本要求
⑴设计数据结构;
⑵设计编码算法;
⑶分析时间复杂度和空间复杂度。

3. 编码
#include<iostream>
#include<string.h>
using namespace std;
const int Size=10,Size1=50;
struct element
{
int weight;
int lchild,rchild,parent;
};
char s[Size];int w[Size],w1[Size];
int getW(char T1[]) //统计字母频率,获得权值
{
char T[Size1];
strcpy(T,T1);
char c;int count,k=0;
for(int i=0;T[i]!='\0';i++)
{
count=0;
if(T[i]>='a'&&T[1]<='z')
{
c=T[i];
s[k]=c;s[k+1]='\0';
}
if(c!='\0')
{
for(int j=0;T[j]!='\0';j++)
{
if(T[j]==c)
{
count++;
T[j]='$';
}
}
}
if(c!='\0')
{
w1[k]=count;
w[k++]=count;
}
c='\0';
}
return k;
}
void Select(element h[],int &i3,int &i4)//获得哈夫曼数组中权值最小的两个下标{
int c;
i3=-1;i4=-1;
for(int i=0;i3==-1;i++)
if(h[i].parent==-1)
i3=i;
for(i;i4==-1;i++)
if(h[i].parent==-1)
i4=i;
if(h[i3].weight>h[i4].weight)
{
c=i3;
i3=i4;
i4=c;
}
for(i;h[i].weight>0;i++)
{
if(h[i].parent==-1)
if(h[i].weight<h[i3].weight)
i4=i3,i3=i;
else if(h[i].weight<h[i4].weight)
i4=i;
}
}
void HuffmanTree(element *huffTree,int n)//哈夫曼树
{
int i1,i2;
for(int i=0;i<2*n-1;i++)
{
huffTree[i].parent=-1;
huffTree[i].lchild=-1;
huffTree[i].rchild=-1;
}
for(i=0;i<n;i++)
huffTree[i].weight=w[i];
for(int k=n;k<2*n-1;k++)
{
Select(huffTree,i1,i2);
huffTree[i1].parent=k;
huffTree[i2].parent=k;
huffTree[k].weight=huffTree[i1].weight+huffTree[i2].weight;
huffTree[k].lchild=i1;
huffTree[k].rchild=i2;
}
}
struct codetype
{
char bits[Size];
char ch;
};
codetype code[Size];
void bm(element h[],int m)//记录路径编码
{
char b[Size];b[0]='\0';
int s1[Size],cd;
int top=-1,i=0,k;
while(m!=-1||top!=-1)
{
while(m!=-1)
{
if(h[m].lchild==-1 && h[m].rchild==-1)//记录路径编码'0','1'的算法,用到parent 回溯。

{
cd=0;
for(int j=h[m].parent;j!=-1;j=h[j].parent)
cd++;
b[cd]='\0';
k=m;
for(j=h[k].parent;j!=-1;j=h[j].parent)
{
if(h[j].lchild==k) b[--cd]='0';
else b[--cd]='1';
k=j;
}
for(j=0;s[j]>='a'&&s[j]<='z';j++)
{
if(h[m].weight==w[j])
{
strcpy(code[i].bits,b);
code[i++].ch=s[j];
w[j]=-1;break;
}
}
}
s1[++top]=m;
m=h[m].lchild;
}
if(top!=-1)
{
m=s1[top--];
m=h[m].rchild;
}
}
}
void jm(element huffT[],int n,char t1[])
{
char b1[Size];b1[0]='\0';
int k=2*n-2,g=0;
for(int i=0;t1[i]!='\0';i++)
{
if(t1[i]=='0')
{
k=huffT[k].lchild;
b1[g++]='0';
b1[g]='\0';
}
else
{
k=huffT[k].rchild;
b1[g++]='1';
b1[g]='\0';
}
if(huffT[k].lchild==-1 && huffT[k].rchild==-1)
{
for(int j=0;j<n;j++)
{
if(strcmp(b1,code[j].bits)==0)
{
cout<<code[j].ch;
break;
}
}
k=2*n-2;g=0;
}
}
cout<<endl;
}
void main()
{
char T[Size1],t[Size1];int n;
cout<<"输入字符串:";
gets(T);
n=getW(T);
element huffTree[Size1];
HuffmanTree(huffTree,n);
cout<<"编码:"<<endl;
bm(huffTree,2*n-2);
for(int i=0;i<n;i++) cout<<code[i].ch<<":"<<code[i].bits<<endl;
for(i=0;T[i]!='\0';i++)
for(int j=0;j<n;j++)
if(T[i]==code[j].ch)
cout<<code[j].bits;
cout<<endl;
cout<<"输入编码:";
gets(t);
cout<<"解码:"<<endl;
jm(huffTree,n,t);
}
4.实验结果
5.实验小结
本次实验主要是通过实验过程掌握哈夫曼编码的逻辑结构,掌握哈夫曼编码和解码的
基本算法,bm函数中通过对树的遍历寻找叶子结点,进行编码。

相关文档
最新文档