实验五 哈夫曼编码与译码的设计与实现
哈夫曼编码译码实验报告
![哈夫曼编码译码实验报告](https://img.taocdn.com/s3/m/a7da3c612e60ddccda38376baf1ffc4ffe47e29c.png)
哈夫曼编码译码实验报告哈夫曼编码译码实验报告一、引言哈夫曼编码是一种用来对数据进行压缩的算法,它能够根据数据的频率分布来分配不同长度的编码,从而实现对数据的高效压缩。
本次实验旨在通过实际操作,深入理解哈夫曼编码的原理和实现方式,并通过编码和解码过程来验证其有效性。
二、实验目的1. 掌握哈夫曼编码的原理和算法;2. 学会使用编程语言实现哈夫曼编码和解码;3. 验证哈夫曼编码在数据压缩中的实际效果。
三、实验过程1. 数据准备在实验开始前,首先需要准备一段文本数据作为实验材料。
为了更好地展示哈夫曼编码的效果,我们选择了一篇新闻报道作为实验文本。
这篇报道涵盖了多个领域的信息,包括科技、经济、体育等,具有一定的复杂性。
2. 哈夫曼编码实现根据哈夫曼编码的原理,我们首先需要统计文本中每个字符的频率。
为了方便处理,我们将每个字符与其频率构建成一个字符-频率的映射表。
然后,我们根据频率构建哈夫曼树,将频率较低的字符作为叶子节点,频率较高的字符作为内部节点。
最后,根据哈夫曼树构建编码表,将每个字符映射到对应的二进制编码。
3. 哈夫曼解码实现在哈夫曼解码过程中,我们需要根据编码表将二进制编码转换回字符。
为了实现高效解码,我们可以将编码表转换为一个二叉树,其中每个叶子节点对应一个字符。
通过遍历二叉树,我们可以根据输入的二进制编码逐步还原出原始文本。
4. 编码和解码效果验证为了验证哈夫曼编码的有效性,我们需要对编码和解码的结果进行比较。
通过计算编码后的二进制数据长度和原始文本长度的比值,我们可以得到压缩率,进一步评估哈夫曼编码的效果。
四、实验结果经过实验,我们得到了以下结果:1. 哈夫曼编码表根据实验文本统计得到的字符-频率映射表,我们构建了哈夫曼树,并生成了相应的编码表。
编码表中每个字符对应的编码长度不同,频率较高的字符编码长度较短,频率较低的字符编码长度较长。
2. 编码结果将实验文本使用哈夫曼编码进行压缩后,得到了一串二进制数据。
《哈夫曼编码》实验报告
![《哈夫曼编码》实验报告](https://img.taocdn.com/s3/m/75ffaff209a1284ac850ad02de80d4d8d15a010c.png)
《哈夫曼编码》实验报告《哈夫曼编码》实验报告一、实验目的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("您的输入有误,请重新输入。
哈夫曼编译码系统
![哈夫曼编译码系统](https://img.taocdn.com/s3/m/11b5606c561252d380eb6e66.png)
{
k=bt[i].weight;
temp=i;
break;
}
for(i=i+1;i<m;i++)//逐个与其他权值进行比较,并返回在parent为0下权值最小的序号
if(bt[i].weight < k && bt[i].parent == 0)
{
k=bt[i].weight;
{
fscanf(fp,"%c",&c[i]);
if(c[i]=='\n') continue;//读到换行符,跳过,读下一行
fscanf(fp,"%5d",&w[i]);
count++;
i++;
}
fclose(fp);
}
//将内容写入文件
void WriteDataFile(char *fileName)
printf("\t* *\t\n");
printf("\t* **哈夫曼编译码系统** *\t\n");
printf("\t* *\t\n");
printf("\t* *\t\n");
printf("\t* 1.更新哈夫曼编码信息*\t\n");
printf("\t* *\t\n");
printf("\t* 2.显示哈夫曼树及哈夫曼编码*\t\n");
(*s2)=Min(ht,m);
}
//构造哈夫曼树
void CreateHuffmanTree(HuffmanTree *HT,int n)
哈夫曼编码译码的设计与实现.pptx
![哈夫曼编码译码的设计与实现.pptx](https://img.taocdn.com/s3/m/8f6a02ab7c1cfad6195fa7e5.png)
abort();
} for(i=0;i<2*n-1;i++) //将内存中从 HaffNode[i]地址开始的 sizeof(HaffNode[i])的内容写入文 件中
cout<<HaffNode[i].weight<<" ";
cout<<HaffNode[i].lchild<<" ";
cout<<HaffNode[i].rchild<<" ";
cout<<HaffNode[i].parent<<endl;
} //写入文件 fstream outfile1;
3
数据结构课程设计报告
第 4 页 共 23 页
outfile1.open("E:\\nodedata.dat",ios::out|ios::trunc|ios::binary);//建立进行写入的文件
if(!outfile1) //没有创建成功则显示相应信息
{ cout<<"nodedata.dat 文件不能打开"<<endl;
二、系统设计
构造哈夫曼树时,使用静态链表作为哈夫曼树的存储。 在构造哈夫曼树时,设计一个结构体数组 HuffNode 保存哈夫曼树中各结点的信息,根据二叉 树的性质可知,具有 n 个叶子结点的哈夫曼树共有 2n-1 个结点,所以数组 HuffNode 的大小设 置为 2n-1, 求哈夫曼编码时使用一维结构数组HuffCode 作为哈夫曼编码信息的存储。 求哈夫曼编码实际上就是在已建立的哈夫曼树中,从叶子结点开始,沿结点的双亲链域回退到 根结点,每回退一步,就走过了哈夫曼的一个分支,从而得到一位哈夫曼编码值。由于一个字 符的哈夫曼编码就是从根结点到相应叶子结点所经过的路径上各分支所组成的 0、1 序列,因 此先得到的分支代码为所求编码的低位码,后得到的分支代码为所求的高位码 1、初始化功能模块 此功能模块的功能为从键盘接受字符集大小n,以及n 个字符和 n 个权值。 2、建立哈夫曼编码的功能模块 此模块功能为使用 1 中得到的数据按照教材中的构造哈弗曼的算法构造哈弗曼树,即将 HuffNode 数组中 的各个位置的各个域都填上相关 的值, 并将这个结构体数组存于文件 nodedata.dat 中。 函数原型为: void Creat_Haffmantree(int &n) {
数据结构哈夫曼树编码及译码的实现实验报告
![数据结构哈夫曼树编码及译码的实现实验报告](https://img.taocdn.com/s3/m/0263d58fe53a580216fcfe88.png)
实验:哈夫曼树编码及译码的实现一.实验题目给定字符集的HUFFMANN编码与解码,这里的字符集及其字符频数自己定义,要求输出个字符集的哈夫曼编码及给定的字符串的哈夫曼码及译码结果。
二.实验原理首先规定构建哈夫曼树,然后进行哈夫曼树的编码,接着设计函数进行字符串的编码过程,最后进行哈夫曼编码的译码。
首先定义一个结构体,这个结构体定义时尽可能的大,用来存放左右的变量,再定义一个地址空间,用于存放数组,数组中每个元素为之前定义的结构体。
输入n个字符及其权值。
构建哈夫曼树:在上述存储结构上实现的哈夫曼算法可大致描述为:1.首先将地址空间初始化,将ht[0…n-1]中所有的结点里的指针都设置为空,并且将权值设置为0.2.输入:读入n个叶子的权值存于向量的前n个分量中。
它们是初始森林中n个孤立的根结点上的权值。
3.合并:对森林中的树共进行n-1次合并,所产生的新结点依次放入向量ht的第i个分量中。
每次合并分两步:①在当前森林ht[0…i-1]的所有结点中,选取权最小和次小的两个根结点[s1]和 [s2]作为合并对象,这里0≤s1,s2≤i-1。
②将根为ht[s1]和ht[s2]的两棵树作为左右子树合并为一棵新的树,新树的根是新结点ht[i]。
具体操作:将ht[s1]和ht[s2]的parent置为i,将ht[i]的lchild和rchild分别置为s1和s2 .新结点ht[i]的权值置为ht[s1]和ht[s2]的权值之和。
4.哈夫曼的编码:约定左子为0,右子为1,则可以从根结点到叶子结点的路径上的字符组成的字符串作为该叶子结点的编码。
当用户输入字母时。
就在已经找好编码的编码结构体中去查找该字母。
查到该字母就打印所存的哈夫曼编码。
接着就是完成用户输入0、1代码时把代码转成字母的功能。
这是从树的头结点向下查找,如果当前用户输入的0、1串中是0则就走向该结点的左子。
如果是1这就走向该结点的右结点,重复上面步骤。
实验五哈夫曼树的建立、编码、解码
![实验五哈夫曼树的建立、编码、解码](https://img.taocdn.com/s3/m/dd77ece4fc0a79563c1ec5da50e2524de418d042.png)
实验题目: 哈夫曼树的应用一、实验目的•加深理解哈夫曼树的定义和特性;•掌握哈夫曼树的存储结构与实现;•掌握哈夫曼树的应用二、实验内容•根据输入的权值信息建立哈夫曼树•输出各个叶子结点所表示字符的哈夫曼编码•对给定的密码串进行解码三、设计与编码1.基本思想2、编码#include<iostream.h>#include<string.h>const int MAX=20;struct huffnode{int weight;int lchild,rchild,parent;};struct huffinit //输入的权值信息的结构{char data;int weight;};struct huffcode //哈夫曼树编码的结构{char data;char code[MAX+1];};class HuffTree //哈夫曼树类的声明{ public:HuffTree(huffinit w[],int n);~HuffTree() { }void Select(int &min1,int &min2,int m);void Output(); //输出哈夫曼树最终状态(tree数组)void Encode(); //编码void Decode(char code[]); //解码private:huffnode tree[2*MAX-1]; //存储哈夫曼树huffcode cd[MAX]; //存储各个哈夫曼编码int size; //哈夫曼树的叶子结点数};HuffTree::HuffTree(huffinit w[],int n){size=n;for(int i=0;i<2*n-1;i++){tree[i].parent=-1;tree[i].lchild=-1;tree[i].rchild=-1;}for(i=0;i<n;i++){tree[i].weight=w[i].weight;cd[i].data=w[i].data;}int min1=-1;int min2=-1;int m=size;for(int k=n;k<2*n-1;k++){Select(min1,min2, m);tree[min1].parent=k;tree[min2].parent=k;tree[k].weight=tree[min1].weight+tree[min2].weight;tree[k].lchild=min1;tree[k].rchild=min2;m++;}}void HuffTree::Select(int &min1,int &min2,int m)//选择两个权值最小的结点{int a=100;int b=100;for(int i=0;i<m;i++){if(tree[i].weight<a&&tree[i].parent==-1){a=tree[i].weight;min1=i;}}for(i=0;i<m;i++){if(tree[i].weight<b&&tree[i].parent==-1&&i!=min1){b=tree[i].weight;min2=i;}}}void HuffTree::Output(){for(int i=0;i<2*size-1;i++){cout<<tree[i].weight<<" "<<tree[i].parent<<" "<<tree[i].lchild<<" "<<tree[i].rchild<<endl;}}void HuffTree::Encode() //编码{int m;int a;int j; char b[100]; int k;for(int i=0;i<size;i++){m=i;j=0;while(tree[m].parent!=-1){a=m;m=tree[m].parent;if(tree[m].lchild==a)b[j++]='0';elseb[j++]='1';}for(k=0,j=j-1;j>=0;j--)cd[i].code[k++]=b[j];cd[i].code[k]='\0';cout<<cd[i].data<<"--->"<<cd[i].code<<endl;;}}void HuffTree::Decode(char code[]) //解码{int a=2*size-2;//根节点的下标for(int i=0;i<n;i++){if(code[i]=='0'){a=tree[a].lchild;}if(code[i]=='1')a=tree[a].rchild;if(tree[a].lchild==-1&&tree[a].rchild==-1){cout<<cd[a].data;a=2*size-2;}elseif(code[i+1]=='\0')cout<<"error";}cout<<endl;}void main(){huffinit w[20];int n;char s[100];cout<<"请输入字符个数: ";cin>>n;for(int i=0;i<n;i++){cout<<"请输入第"<<i+1<<"个字符及权值: " ;cin>>w[i].data;cin>>w[i].weight;}HuffTree H(w,n);cout<<"已经建好的节点信息为"<<endl;H.Output();cout<<"已经建好的节点编码信息为"<<endl;H.Encode();char q;do{cout<<"请输入密码: ";cin>>s;cout<<endl;cout<<"还要继续解码吗?(Y/N)";cin>>q;}while(q=='Y');}四、调试与运行1.调试时遇到的主要问题及解决2.运行结果(输入及输出, 可以截取运行窗体的界面)五、实验心得。
哈夫曼树编码译码实验报告
![哈夫曼树编码译码实验报告](https://img.taocdn.com/s3/m/6bab0119905f804d2b160b4e767f5acfa1c783ca.png)
数据结构课程设计设计题目:哈夫曼树编码译码课题名称院系学号姓名哈夫曼树编码译码年级专业成绩1、课题设计目的:在当今信息爆炸时代,如何采用有效的数据压缩技术节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视,哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。
哈夫曼编码是一种编码方式,以哈夫曼树—即最优二叉树,带权路径长度最小的二叉树,时常应用于数据压缩。
哈弗曼编码使用一张特殊的编码表将源字符(例如某文件中的一个符号)进行编码。
这张编码表的特殊之处在于,它是根据每一个源字符浮现的估算概率而建立起来的。
课题设计目的与设计意义2、课题设计意义:哈夫曼编码的应用很广泛,利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。
树中从根到每一个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或者“1”的序列作为和各个叶子对应的字符的编码,这就是哈夫曼编码。
哈弗曼译码输入字符串可以把它编译成二进制代码,输入二进制代码时可以编译成字符串。
指导教师:年月日第一章需求分析 (1)第二章设计要求 (1)第三章概要设计 (2)(1)其主要流程图如图 1-1 所示。
(3)(2)设计包含的几个方面 (4)第四章详细设计 (4)(1)①哈夫曼树的存储结构描述为: (4)(2)哈弗曼编码 (5)(3)哈弗曼译码 (7)(4)主函数 (8)(5)显示部份源程序: (8)第五章调试结果 (10)第六章心得体味 (12)第七章参考文献 (12)附录: (12)在当今信息爆炸时代,如何采用有效的数据压缩技术节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视,哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。
哈夫曼编码是一种编码方式,以哈夫曼树—即最优二叉树,带权路径长度最小的二叉树,时常应用于数据压缩。
哈弗曼编码使用一张特殊的编码表将源字符 (例如某文件中的一个符号) 进行编码。
数据结构课程设计哈夫曼编码实验
![数据结构课程设计哈夫曼编码实验](https://img.taocdn.com/s3/m/91e3345c0a4e767f5acfa1c7aa00b52acfc79ca9.png)
数据结构设计性实验Huffman编码与译码学号姓名班级设计性实验—Huffman 编码与译码一.实验目的:在掌握相关基础知识的基础上,学会自己设计实验算法,熟练掌握Huffman 树的建立方法,Huffman 编码的方法,进而设计出Huffman 译码算法,并编程实现。
二.实验要求:在6学时以内,制作出能够实现基于26个英文字母的任意字符串的编译码。
写出技术工作报告并附源程序。
三.实验内容及任务:1.设字符集为26个英文字母,其出现频度如下表所示。
2.建Huffman 树; 3.利用所建Huffman 树对任一字符串文件进行编码——即设计一个Huffman 编码器;4.对任一字符串文件的编码进行译码——即设计一个Huffman 译码器。
实现步骤:1.数据存储结构设计; 2.操作模块设计; 3.建树算法设计; 4.编码器设计;5. 译码器设计;51 48 1 15 63 57 20 32 5 1频度z y x w v u t 字符11611882380频度p 21 f q15 g r 47 h s o n m l k j 字符 57 103 32 22 13 64 186 频度 i e d c b a 空格 字符四.分析以及算法描述1.分析问题1)首先学习二叉树的知识,了解二叉树的路径、权数以及带权路径长度计算。
2)认识霍夫曼树,了解霍夫曼树的定义,构造霍夫曼树构造算法①又给定的n个权值{w1,w2,w3,……,w n}构造根节点的二叉树,从而得到一个二叉树森林F={T1,T2,T3,……T n}。
②在二叉树森里选取根节点全职最小和此最小的两棵二叉树作为左右节点构造新的二叉树,此时新的二叉树的根节点权值为左右子树权值之和。
③在二叉树森林中删除作为新二叉树的根节点左右子树的两棵二叉树,将新的二叉树加入到二叉树森林F中。
④重复②和③,当二叉树森林F只剩下一棵二叉树时,这棵二叉树是所构造的霍夫曼树。
3)练习通过普通树来构造霍夫曼树。
哈夫曼编码和译码的设计与实现
![哈夫曼编码和译码的设计与实现](https://img.taocdn.com/s3/m/984cdc4589eb172ded63b7ed.png)
算法与数据结构课程设计哈夫曼编码和译码的设计与实现1.问题描述利用哈夫曼编码进行通信可以大大提高信道的利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。
试为这样的信息收发站设计一个哈夫曼码的编/译码系统。
2.基本要求a.编/译码系统应具有以下功能:(1)I:初始化(Initialization)。
从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree中。
(2)E:编码(Encoding)。
利用已建好的哈夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
(3)D:译码(Decoding)。
利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。
(4)P:印代码文件(Print)。
将文件CodeFile以紧凑格式显示在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件CodePrin中。
(5)T:印哈夫曼树(Tree printing)。
将已在内存中的哈夫曼树以直观的方式(树或凹入表形式或广义表)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。
b.测试数据(1)利用下面这道题中的数据调试程序。
某系统在通信联络中只可能出现八种字符,其概率分别为0.25,0.29,0.07,0.08,0.14,0.23,0.03,0.11,试设计哈夫曼编码。
(2)用下表给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:“THIS PROGRAM IS MY FAVORITE”。
字符空格 A B C D E F G H I J K L M频度 186 64 13 22 32 103 21 15 47 57 1 5 32 20字符 N O P Q R S T U V W X Y Z频度57 63 15 1 48 51 80 23 8 18 1 16 13.需求分析3.1程序的基本功能本程序可以对任何大小的字符型文件进行Huffman编码,生成一个编码文件。
实验五 哈夫曼树的建立与编码实现
![实验五 哈夫曼树的建立与编码实现](https://img.taocdn.com/s3/m/42447caefd0a79563c1e7298.png)
实验五哈夫曼树的建立与编码实现
一、目的:
掌握哈夫曼树的表示,实现及其在编码上的应用。
二、要求:
1)建立一正文文件(本程序中建立的文件名文test.txt),向其中输入字符。
2)通过哈夫曼算法求出文件中字符的相应编码。
3)建立一与正文文件(test.txt)对应的编码文件(bainma.txt)。
三、实验内容
1、哈夫曼树的建立。
2、编写相应的译码程序。
四、实验报告要求
要求所编的程序能正确运行,并提交实验报告。
实验报告的基本要求为:
1、陈述程序设计的任务,强调程序要做什么,明确规定:
(1)输入的形式和输出值的范围;
(2)输出的形式;
(3)程序所能达到的功能;
(4)测试数据:包括正确的输入输出结果和错误的输入及输出结果。
2、说明用到的数据结构定义、主程序的流程及各程序模块之间的调用关系。
3、提交带注释的源程序或者用伪代码写出每个操作所涉及的算法。
4、调试分析:
(1)调试过程中所遇到的问题及解决方法;
(2)算法的时空分析;
(3)经验与体会。
5、用户使用说明:说明如何使用你的程序,详细列出每一步操作步骤。
6、测试结果:列出对于给定的输入所产生的输出结果。
哈夫曼编译码的设计与实现
![哈夫曼编译码的设计与实现](https://img.taocdn.com/s3/m/2574771c59eef8c75fbfb31d.png)
哈夫曼编\译码的设计与实现一、简介1.设计目的:通过对简单哈夫曼编/译码系统的设计与实现来熟练掌握树型结构在实际问题中的应用。
2.问题的描述:利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码。
系统应该具有如下的几个功能:接收原始数据、编码、译码、打印编码规则。
二、数据结构的设计:1.哈夫曼结点结构体:typedef struct HtNode{int weight;int parent, lchild, rchild;}HtNode;2.哈夫曼树结构体:typedef struct HtTree{struct HtNode ht[MAXNODE+1];int root;}HtTree, *PHtTree;三、功能(函数)设计:总体上划分为四个模块,具体功能描述如下:1.初始化功能模块:接收输入信息,并正确输出2.建立哈夫曼树的功能模块:按照构造哈夫曼树的算法构造哈夫曼树,将HuffNode数组中的各个位置的各个域都添上相关的值3.哈夫曼编码的功能模块:根据输入的相关字符信息进行哈夫曼编码,然后将结果存入,同时将字符与0、1代码串的一一对应关系打印到屏幕上。
4.译码的功能模块:接收需要译码的0、1代码串,按照哈夫曼编码规则将其翻译成字符集中的字符所组成的字符串形式,将翻译的结果在屏幕上输出四、界面设计:该界面操做简单,内容详细,便于程序使用者根据提示轻松上手。
简洁明朗是该界面最大的特点。
哈夫曼编/译码请逐个输入结点和结点的权值>>>按Enter键开始根据此提示界面进入程序使用阶段。
请输入结点个数:根据用户输入结点个数,动态输入并存储字符及权值然后输出字符与0、1代码串的对应关系。
进入以下界面,进行后续操作1----------------------------编码2----------------------------译码3----------------------------重新输入权值;0----------------------------退出用户键入“0”,即可出编码译码操作五、程序设计:1.函数功能说明及其程序流程图的描述:1>:main函数:控制整个程序的整个流程。
哈夫曼码编、译码器的实现
![哈夫曼码编、译码器的实现](https://img.taocdn.com/s3/m/b0205ee74028915f804dc245.png)
根据下面给出的存储结构定义 typedef struct // 定义哈夫曼树中每个结点结构体类型 { char ch; //结点字符信息 int weight; // 定义一个整型权值变量 int lchild; // 定义左、右孩子及双亲指针 int rchild; int parent; } HTNode; typedef HTNode HFMT[MAXLEN]; //用户自定义HFMT数组类型 typedef char** HfCode;//动态分配字符数组存储哈夫曼编码表 (7)基本操作的函数设计 void InitHFMT(HFMT T);//初始化哈夫曼树 void InputWeight(HFMT T,char* weightFile);// 输入权值 void SelectMin(HFMT T,int i,int *p1,int *p2); //选择所有结点中较小的结点 void CreatHFMT(HFMT T);// 构造哈夫曼树,T[2*n-1]为其根结点 void PrintHFMT (HFMT T);// 输出向量状态表 void printHfCode(HfCode hc);//输出字符的哈夫曼编码序列 HfCode hfEnCoding(HFMT T);//利用构成的哈夫曼树生成字符的编码 void print_HuffmanTree(HFMT HT,int t,int i)//按树形形态输出哈 夫曼树的形态 void Encoder(char* original,char* codeFile,HfCode hc,HFMT HT); //利用已建好的哈夫曼树,对original文件中要传输的原始数据进行编 码, //将编码结果存入文件codeFile中 void Decoder(char* codeFile ,char* textFile,HFMT HT); //利用已建好的哈夫曼树,对传输到达的codeFile中的数据代码进行译
哈夫曼编码译码
![哈夫曼编码译码](https://img.taocdn.com/s3/m/aa151de3bceb19e8b9f6ba2d.png)
哈夫曼编码译码一、【实验内容】【问题描述】利用哈夫曼编码进行住处通讯可以大大提高信道利用率,缩短住处传输时间,降低成本,但是,这要求在发送端通过一个编码系统将传输的数据预先编码,在接收端通过一个译码系统对传来的数据进行译码(复原),对于双向传输信息的信道,每端都一个完整的编码译码系统,试为这样的住处收发站写一个哈夫曼友的编码译码系统.【基本要求】:一个完整的系统应以下功能:(1) I. 初始化(Initialization)。
从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存放在文件hfmTree中.(2) E. 编码(Encoding)。
利用已建立好的哈夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果代码存(传输)到文件CodeFile中.(3) D. 译码(Decoding)。
利用已建好的哈夫曼树,对传输到达的CodeFile中的数据代码进行译码,将译码结果存入文件TextFile中.(4) P. 印文件代码(Print)。
将文件CodeFile以紧凑格式显示在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件CodePrin中。
(5) T. 印哈夫曼树(TreePrinting)。
将已在内存中的哈夫曼树以直观的方式(树或凹入表的形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。
测试数据:(1) 利用教科书例6-2中的数据调试程序。
(2) 用下表给出的字符集和频度的计数据建立哈曼树,并实现以下报文的编码和译码:“THIS PROGRAM IS MY FAVORITE”.。
字符 A B C D E F G H I J K L M频数 186 64 13 22 32 103 21 15 47 57 1 5 32 20字符 N O P Q R S T U V W X Y Z频数 57 63 15 1 48 51 80 23 8 18 1 16 1二、实验目的树型结构是一种应用极为广泛的非线性数据结构,也是本课程的重点内容,哈夫曼树(最优二叉树)是树型结构的典型应用,本次实验突出了数据结构加操作的程序设计观点,希望能根据树型结构的非线性特点,熟悉各种存储结构的特性,达到如何应用树型结构的非线性特点,熟悉各种存储结构的特性,达到如何应用树型结构解决具体问题的目的.三、实验文档:哈夫曼编码/译码一、需求分析1、利用哈夫曼编码进行信息通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
哈夫曼编码和译码的算法设计与实现
![哈夫曼编码和译码的算法设计与实现](https://img.taocdn.com/s3/m/3dba013f15791711cc7931b765ce050876327580.png)
哈夫曼编码和译码的算法设计与实现实验名称哈夫曼编码和译码的算法设计与实现实验方案实验成绩实验日期实验室信息系统设计与仿真室I 实验操作实验台号班级姓名实验结果一、实验目的1、掌握哈夫曼编码的二叉树结构表示方法;2、编程实现哈夫曼编码译码器;3、掌握贪心算法的设计策略。
二、实验任务①从文件中读取数据,构建哈夫曼树;②利用哈夫曼树,对输入明文进行哈夫曼编码;③利用哈夫曼树,对输入编码译码为明文。
三、实验设计方案1、结构体设计Huffman树:包括字符,权,父亲下标,左孩子下标,右孩子下标#define N 29 //26个小写字母,逗号,句号和空格字符.struct treenode{ //静态链表char c; //charint w; //weightint f; //fatherint l; //left child indexint r; //right child index};struct treenode htree[2*N-1];2、自定义函数设计①函数原型声明void input(); //读取文件字符、权值数据void huffman(); //建立huffman树void getcode(int i, char *str); //得到单个字符的huffman编码void encode(char ch); //将明文进行huffman编码void decode(char *str); //将huffman编码译为明文②读取文件字符、权值数据void input(){int i;char c;int f;freopen("in.txt","r",stdin);for(i=0;i<n;i++)< p="">{c=getchar(); //接收字符scanf("%d",&f); //接收权值getchar(); //接收回车ht[i].c=c;ht[i].w=f;ht[i].l=ht[i].f=ht[i].r=-1; //初始化父亲、左右孩子下标} freopen( "CON", "r", stdin);}③建立huffman树//使用贪心法建立huffman树,每次选择权值最小的根结点void huffman(){void huffman(){int j,k,n;input();j=0;k=N;for(n=N;n<2*N-1;n++){ //建立huffman树,共合并N-1次int r=0,s=0;ht[n].l=ht[n].f=ht[n].r=-1;while(r<2){ //选择两个最小的权值结点if((ht[k].w==0 || ht[k].w>ht[j].w) && j<n){< p="">s+=ht[j].w;if(r==0) ht[n].l = j; //修改父亲、孩子下标else ht[n].r=j;ht[j].f=n;j++;}else{s+=ht[k].w;if(r==0) ht[n].l = k; //修改父亲、孩子下标else ht[n].r=k;ht[k].f=n;k++;}r++;}ht[n].w=s; //修改权值}}④根据字符下标找到字符的huffman编码//根据字符所在的下标,从叶子结点往上搜索到根节点,然后逆置得到该字符的huffman编码void getcode(int i, char *str){ int n,j,l=0;for(n=i;ht[n].f!=-1;n=ht[n].f){ //沿着父亲往上搜索int m=ht[n].f;if(n==ht[m].l)str[l++]='0'; //左孩子记为0elsestr[l++]='1'; //右孩子记为1}for(j=0;j<=(l-1)/2;j++){ //将编码逆置char t;t=str[j];str[j]=str[l-1-j];str[l-1-j]=t;}str[l]=0; // str存放huffman编码,字符串结束标记}⑤读入明文生成huffman编码void encode(char ch){int i;char str[N];for(i=0;ht[i].c!=0;i++)if(ht[i].c==ch) //找字符下标break;if (ht[i].c!=0){getcode(i,str); //得到字符的huffman编码printf("%s",str);}}⑥将huffman编码串译码为明文void decode(char *str){while(*str!='\0'){int i;for(i=2*N-2;ht[i].l!=-1;){if(*str=='0')i=ht[i].l;elsei=ht[i].r;str++;}printf("%c",ht[i].c);}}3、主函数设计思路:主函数实现实验任务的基本流程。
哈夫曼编码译码器实验报告
![哈夫曼编码译码器实验报告](https://img.taocdn.com/s3/m/c9e33566443610661ed9ad51f01dc281e43a5658.png)
哈夫曼编码译码器实验报告实验名称:哈夫曼编码译码器实验一、实验目的: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.比较编码前后字符串的内容,结果正确。
五、实验总结:通过本次实验,我了解了哈夫曼编码的原理和应用,并且实现了一个简单的哈夫曼编码的编码和译码器。
在实验过程中,我充分运用了数据结构中的树的知识,构建了一个哈夫曼树,并生成了编码表。
通过编码和译码过程,我进一步巩固了对树的遍历和节点查找的理解。
实验结果表明,本次哈夫曼编码的编码和译码过程正确无误。
在实验的过程中,我发现哈夫曼编码对于频率较高的字符具有较短的编码,从而实现了对字符串的高效压缩。
同时,哈夫曼编码还可以应用于数据传输和存储中,提高数据的传输效率和存储空间的利用率。
通过本次实验,我不仅掌握了哈夫曼编码的编码和译码过程,还深入了解了其实现原理和应用场景,加深了对数据结构和算法的理解和应用能力。
实验五哈夫曼编码与译码的设计与实现
![实验五哈夫曼编码与译码的设计与实现](https://img.taocdn.com/s3/m/0f17ce90b90d6c85ec3ac6ad.png)
实验五哈夫曼编码与译码的设计与实现一、问题描述利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。
试为这样的信息收发编写一个哈夫曼码的编/译码系统。
基本要求:(1)接收原始数据:从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件nodedata.dat中。
(2)编码:利用已建好的哈夫曼树(如不在内存,则从文件nodedata.dat 中读入),对文件中的正文进行编码,然后将结果存入文件code.dat中。
(3)译码:利用已建好的哈夫曼树将文件code.dat中的代码进行译码,结果存入文件text中。
(4)打印编码规则:即字符与编码的一一对应关系。
(5)打印哈夫曼树:将已在内存中的哈夫曼树以直观的方式显示在终端上。
二、数据结构设计1、构造哈夫曼树时,使用静态链表作为哈夫曼树的存储。
在构造哈夫曼树时,设计一个结构体数组HuffNode保存哈夫曼树中各结点的信息,根据二叉树的性质可知,具有n个叶子结点的哈夫曼树共有2n-1个结点,所以数组HuffNode的大小设置为2n-1,描述结点的数据类型为:typedef struct{int weight;int parent;int lchild;int rchild;char inf;}HNodeType;2.求哈夫曼编码时使用一维结构数组HuffCode作为哈夫曼编码信息的存储。
求哈夫曼编码实际上就是在已建立的哈夫曼树中,从叶子结点开始,沿结点的双亲链域回退到根结点,每回退一步,就走过了哈夫曼的一个分支,从而得到一位哈夫曼编码值。
由于一个字符的哈夫曼编码就是从根结点到相应叶子结点所经过的路径上各分支所组成的0、1序列,因此先得到的分支代码为所求编码的低位码,后得到的分支代码为所求的高位码。
哈夫曼码编、译码器的实现
![哈夫曼码编、译码器的实现](https://img.taocdn.com/s3/m/cb7e613887c24028915fc3fb.png)
综合实验四哈夫曼码编、译码器的实现一、实验名称哈夫曼码编、译码器的实现二、实验目的1、熟练哈夫曼树的定义,掌握构造哈夫曼树的方法。
2、掌握哈夫曼编码和译码方法。
3、掌握文本文件的读写方法。
三、实验内容1、实验内容:利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编码、译码系统。
试为这样的信息收发站写一个哈夫曼码的编码、译码系统。
一个完整的系统应以下功能:(1) 从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存放在文件hfmTree中。
(2) 利用已建立好的哈夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果代码存(传输)到文件CodeFile中.(3) 译码(Decoding)。
利用已建好的哈夫曼树,对传输到达的CodeFile中的数据代码进行译码,将译码结果存入文件TextFile。
(4) 将文件CodeFile以紧凑格式显示在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件CodePrin中。
(5) 打印印哈夫曼树(TreePrinting)。
将已在内存中的哈夫曼树以直观的方式(树或凹入表的形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。
(6)数据结构设计根据下面给出的存储结构定义typedef struct // 定义哈夫曼树中每个结点结构体类型{char ch; //结点字符信息int weight; // 定义一个整型权值变量int lchild; // 定义左、右孩子及双亲指针int rchild;int parent;} HTNode;typedef HTNode HFMT[MAXLEN]; //用户自定义HFMT数组类型typedef char** HfCode;//动态分配字符数组存储哈夫曼编码表(7)基本操作的函数设计void InitHFMT(HFMT T);//初始化哈夫曼树void InputWeight(HFMT T,char* weightFile);// 输入权值void SelectMin(HFMT T,int i,int *p1,int *p2);//选择所有结点中较小的结点void CreatHFMT(HFMT T);// 构造哈夫曼树,T[2*n-1]为其根结点void PrintHFMT (HFMT T);// 输出向量状态表void printHfCode(HfCode hc);//输出字符的哈夫曼编码序列HfCode hfEnCoding(HFMT T);//利用构成的哈夫曼树生成字符的编码void print_HuffmanTree(HFMT HT,int t,int i)//按树形形态输出哈夫曼树的形态void Encoder(char* original,char* codeFile,HfCode hc,HFMT HT);//利用已建好的哈夫曼树,对original文件中要传输的原始数据进行编码,//将编码结果存入文件codeFile中void Decoder(char* codeFile ,char* textFile,HFMT HT);//利用已建好的哈夫曼树,对传输到达的codeFile中的数据代码进行译码,//将译码结果存入文件textFile中2、实验要求(1)、用C语言编程实现上述实验内容中的结构定义和算法。
哈夫曼编译码系统的设计与实现
![哈夫曼编译码系统的设计与实现](https://img.taocdn.com/s3/m/3bf7750416fc700abb68fcd1.png)
哈夫曼编/译码系统的设计与实现一、实验项目简介:1.问题描述:利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(解码)。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。
试为这样的信息收发站设计一个哈夫曼编/译码系统。
2.一个完整的系统应具有以下功能:1)初始化(Initialzation)。
从数据文件 DataFile.data 中读入字符及每个字符的权值,建立哈夫曼树HuffTree;2)编码(EnCoding)。
用已建好的哈夫曼树,对文件ToBeTran.data 中的文本进行编码形成报文,将报文写在文件 Code.txt 中;3)译码(Decoding)。
利用已建好的哈夫曼树,对文件CodeFile.data 中的代码进行解码形成原文,结果存入文件 Textfile.txt 中;4)输出(Output)。
输出 DataFile.data 中出现的字符以及各字符出现的频度(或概率);输出 ToBeTran.data 及其报文 Code.txt;输出 CodeFile.data 及其原文 Textfile.txt;要求:所设计的系统应能在程序执行的过程中,根据实际情况(不同的输入)建立DataFile.data、ToBeTran.data 和 CodeFile.data 三个文件,以保证系统的通用性。
二、实验目的:理解哈夫曼树的特征及其应用;在对哈夫曼树进行理解的基础上,构造哈夫曼树,并用构造的哈夫曼树进行编码和译码;通过该实验,使学生对二叉树的构建、遍历等以及哈夫曼编码的应用有更深层次的理解。
实验步骤:实验分 2 次完成第 1 次:完成程序的主框架设计,进行调试,验证其正确性;(2学时)第 2 次:详细设计,进行调试,对运行结果进行分析,完成实验报告。
哈夫曼编码译码实训报告
![哈夫曼编码译码实训报告](https://img.taocdn.com/s3/m/63ed9f75b5daa58da0116c175f0e7cd185251878.png)
一、实训目的本次实训旨在通过实际操作,使学生掌握哈夫曼编码的基本原理和方法,熟悉哈夫曼树的构建过程,并能够熟练地进行哈夫曼编码和译码操作。
通过实训,提升学生对数据压缩技术的理解和应用能力。
二、实训内容1. 哈夫曼树构建- 收集给定字符串中每个字符的出现频率。
- 根据字符频率构建哈夫曼树,其中频率高的字符对应较大的权重。
- 使用优先队列(最小堆)实现哈夫曼树的构建。
2. 哈夫曼编码- 遍历哈夫曼树,为每个叶子节点分配唯一的编码,左分支为0,右分支为1。
- 根据分配的编码生成字符编码表。
3. 哈夫曼译码- 使用生成的编码表,将编码字符串转换回原始字符串。
三、实训步骤1. 数据准备- 选择一段英文或中文文本作为输入数据。
2. 构建哈夫曼树- 统计输入数据中每个字符的出现频率。
- 使用优先队列构建哈夫曼树。
3. 生成哈夫曼编码- 遍历哈夫曼树,为每个叶子节点分配编码。
- 生成字符编码表。
4. 编码数据- 使用哈夫曼编码表对输入数据进行编码。
5. 译码数据- 使用哈夫曼编码表对编码后的数据进行译码。
6. 结果分析- 比较编码前后数据的大小,分析哈夫曼编码的压缩效果。
四、实训结果1. 哈夫曼树构建- 成功构建了给定字符串的哈夫曼树。
2. 哈夫曼编码- 成功生成了每个字符的哈夫曼编码。
3. 哈夫曼译码- 成功将编码后的数据译码回原始字符串。
4. 压缩效果分析- 通过对比编码前后数据的大小,验证了哈夫曼编码的压缩效果。
五、实训总结1. 哈夫曼编码原理- 哈夫曼编码是一种基于字符频率的变长编码方法,能够有效降低数据传输的冗余度。
2. 哈夫曼树构建- 哈夫曼树的构建是哈夫曼编码的关键步骤,通过优先队列(最小堆)实现。
3. 哈夫曼编码与译码- 哈夫曼编码和译码过程相对简单,但需要正确处理编码表和字符编码。
4. 实训收获- 通过本次实训,掌握了哈夫曼编码的基本原理和方法,熟悉了哈夫曼树的构建过程,并能够熟练地进行哈夫曼编码和译码操作。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验五哈夫曼编码与译码的设计与实现一、问题描述利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。
试为这样的信息收发编写一个哈夫曼码的编/译码系统。
基本要求:(1)接收原始数据:从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件nodedata.dat中。
(2)编码:利用已建好的哈夫曼树(如不在内存,则从文件nodedata.dat 中读入),对文件中的正文进行编码,然后将结果存入文件code.dat中。
(3)译码:利用已建好的哈夫曼树将文件code.dat中的代码进行译码,结果存入文件textfile.txt中。
(4)打印编码规则:即字符与编码的一一对应关系。
(5)打印哈夫曼树:将已在内存中的哈夫曼树以直观的方式显示在终端上。
二、数据结构设计1、构造哈夫曼树时,使用静态链表作为哈夫曼树的存储。
在构造哈夫曼树时,设计一个结构体数组HuffNode保存哈夫曼树中各结点的信息,根据二叉树的性质可知,具有n个叶子结点的哈夫曼树共有2n-1个结点,所以数组HuffNode的大小设置为2n-1,描述结点的数据类型为:typedef struct{int weight;int parent;int lchild;int rchild;char inf;}HNodeType;2.求哈夫曼编码时使用一维结构数组HuffCode作为哈夫曼编码信息的存储。
求哈夫曼编码实际上就是在已建立的哈夫曼树中,从叶子结点开始,沿结点的双亲链域回退到根结点,每回退一步,就走过了哈夫曼的一个分支,从而得到一位哈夫曼编码值。
由于一个字符的哈夫曼编码就是从根结点到相应叶子结点所经过的路径上各分支所组成的0、1序列,因此先得到的分支代码为所求编码的低位码,后得到的分支代码为所求的高位码。
所以设计如下数据类型:#define MaxBit 10struct HcodeType{int bit[MaxBit];int start;};3、文件nodedata.dat、code.dat、textfile.txt三、功能函数设计1、初始化功能模块此功能模块的功能为从键盘接受字符集大小n,以及n个字符和n个权值。
2、建立哈夫曼编码的功能模块此模块功能为使用1中得到的数据按照教材中的构造哈弗曼的算法构造哈弗曼树,即将HuffNode数组中的各个位置的各个域都填上相关的值,并将这个结构体数组存于文件nodedata.dat中。
函数原型为:void Creat_Haffmantree(int &n){HNodeType *HaffNode=new HNodeType[2*n-1];int i,j;int m1,m2,x1,x2;for(i=0;i<2*n-1;i++){HaffNode[i].weight=0;HaffNode[i].parent=-1;HaffNode[i].lchild=-1;HaffNode[i].rchild=-1;HaffNode[i].inf='0';}for(i=0;i<n;i++){cout<<"请输入字符"<<endl;cin>>HaffNode[i].inf;cout<<"请输入该字符的权值"<<endl;cin>>HaffNode[i].weight;}for(i=0;i<n-1;i++)//构造哈夫曼树{m1=m2=Maxvalue;x1=x2=0;for(j=0;j<n+i;j++)//选取最小和次小{if(HaffNode[j].parent==-1&&HaffNode[j].weight<m1){m2=m1;x2=x1;m1=HaffNode[j].weight;x1=j;}else{if(HaffNode[j].parent==-1&&HaffNode[j].weight<m2){m2=HaffNode[j].weight;x2=j;}}}//将找出的最小和次小合并,创造其父母结点HaffNode[x1].parent=n+i;HaffNode[x2].parent=n+i;HaffNode[n+i].weight=HaffNode[x1].weight+HaffNode[x2].weight;HaffNode[n+i].lchild=x2;HaffNode[n+i].rchild=x1;HaffNode[n+i].inf=NULL;}cout<<"显示存储的哈弗曼树信息:"<<endl;cout<<"权值左孩子右孩子双亲"<<endl;for(i=0;i<2*n-1;i++){cout<<HaffNode[i].inf<<" ";cout<<HaffNode[i].weight<<" ";cout<<HaffNode[i].lchild<<" ";cout<<HaffNode[i].rchild<<" ";cout<<HaffNode[i].parent<<endl;}//写入文件fstream outfile1;outfile1.open("E:\\nodedata.dat",ios::out|ios::trunc|ios::bina ry);//建立进行写入的文件if(!outfile1) //没有创建成功则显示相应信息{cout<<"nodedata.dat文件不能打开"<<endl;abort();}for(i=0;i<2*n-1;i++) //将内存中从HaffNode[i]地址开始的sizeof(HaffNode[i])的内容写入文件中outfile1.write((char*)&HaffNode[i],sizeof(HaffNode[i]));outfile1.close ();//关闭文件delete []HaffNode;}3、建立哈弗曼编码功的功能模块此模块功能是从文件nodedata.dat中读入相关的字符信息进行哈弗曼编码,然后将结果存入code.dat中,同时将字符与0和1代码串的一一对应关系显示到屏幕上。
函数原型为:void HaffCode(int &n)//哈夫曼编码{HNodeType *HaffNode=new HNodeType[Maxnode];HcodeType *HaffCode=new HcodeType[Maxleaf];HcodeType cd;int i,j,c,p;fstream in("E:\\nodedata.dat",ios::in|ios::binary);in.read((char*)HaffNode,(2*n-1)*sizeof(HNodeType));in.close();fstream outfile;outfile.open("E:\\codedata.dat",ios::out|ios::binary);//建立进行写入的文件for(i=0;i<n;i++){cd.start=n-1;c=i;p=HaffNode[c].parent;while(p!=-1){if(HaffNode[p].lchild==c)cd.bit[cd.start]=0;elsecd.bit[cd.start]=1;cd.start--;c=p;p=HaffNode[c].parent;}for(j=cd.start+1;j<n;j++)HaffCode[i].bit[j]=cd.bit[j];HaffCode[i].start=cd.start;}for(i=0;i<n;i++){outfile<<HaffNode[i].inf;for(j=HaffCode[i].start+1;j<n;j++)outfile<<HaffCode[i].bit[j];}cout<<"字符信息--编码信息"<<endl;for(i=0;i<n;i++){cout<<HaffNode[i].inf<<"---";for(j=HaffCode[i].start+1;j<n;j++)cout<<HaffCode[i].bit[j];cout<<endl;}outfile.close ();cout<<"请输入要编码的字符串,基本元素为(";for(i=0;i<n;i++)cout<<HaffNode[i].inf<<",";cout<<")"<<endl;char inf[100];cin>>inf;int f=strlen(inf);fstream outfile1;outfile1.open("E:\\code.dat",ios::out|ios::binary);//建立进行写入的文件if(!outfile1){cout<<"code.dat文件不能打开!"<<endl;abort();}else{ cout<<endl;cout<<"字符串编码后为:";for(int x=0;x<f;x++){for(i=0;i<n;i++){if(inf[x]==HaffNode[i].inf){for(j=HaffCode[i].start+1;j<n;j++){outfile1.write((char*)&HaffCode[i].bit[j],sizeof(HaffCode[i].bit[j])) ;cout<<HaffCode[i].bit[j];}}}}}cout<<endl;cout<<"编译后的代码串已经存入code.dat文件中!"<<endl;cout<<endl;outfile1.close();delete []HaffNode;delete []HaffCode;}4. 此模块功能为接收需要译码的0、1代码串,按照3中建立的编码规则将其翻译成字符集中字符所组成的字符串形式,存入文件textfile.dat,同时将翻译的结果在屏幕上打印输出。