哈夫曼实验报告(附代码)

合集下载

《哈夫曼编码》实验报告

《哈夫曼编码》实验报告

《哈夫曼编码》实验报告《哈夫曼编码》实验报告一、实验目的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("您的输入有误,请重新输入。

数据结构(C语言版)实验报告(哈夫曼树)

数据结构(C语言版)实验报告(哈夫曼树)

《数据结构与算法》实验报告一、需求分析1.问题描述:利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。

但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。

对于双工通道(及可以双向传输信息的通道),每端都需要一个完整的编/译码系统。

试为这样的信息收发站写一个哈夫曼的编/译码系统。

2.基本要求一个完整的系统应具有以下功能:(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中。

3.测试数据(1)利用教科书例6-2中的数据调试程序。

(2)用下表给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:“THIS PROGRAM IS MY FAVORITE”。

4,实现提示(1)编码结果以文本方式存储在文件CodeFile中。

(2)用户界面可以设计为“菜单”方式:显示上述功能符号,再加上“Q”表示退出运行Quit。

请用户键入一个选择功能符。

此功能执行完毕后再显示此菜单,直至某次用户选择了“Q”为止。

(3)在程序的一次执行过程中,第一次执行I、D或C命令之后,哈夫曼树已经在内存了,不必再读入。

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

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

数据结构哈夫曼编码实验报告数据结构哈夫曼编码实验报告1·实验目的1·1 理解哈夫曼编码的基本原理1·2 掌握哈夫曼编码的算法实现方式1·3 熟悉哈夫曼编码在数据压缩中的应用2·实验背景2·1 哈夫曼编码的概念和作用2·2 哈夫曼编码的原理和算法2·3 哈夫曼编码在数据压缩中的应用3·实验环境3·1 硬件环境:计算机、CPU、内存等3·2 软件环境:编程语言、编译器等4·实验过程4·1 构建哈夫曼树4·1·1 哈夫曼树的构建原理4·1·2 哈夫曼树的构建算法4·2 哈夫曼编码4·2·1 哈夫曼编码的原理4·2·2 哈夫曼编码的算法4·3 实现数据压缩4·3·1 数据压缩的概念和作用4·3·2 哈夫曼编码在数据压缩中的应用方法5·实验结果5·1 构建的哈夫曼树示例图5·2 哈夫曼编码表5·3 数据压缩前后的文件大小对比5·4 数据解压缩的正确性验证6·实验分析6·1 哈夫曼编码的优点和应用场景分析6·2 数据压缩效果的评估和对比分析6·3 实验中遇到的问题和解决方法7·实验总结7·1 实验所获得的成果和收获7·2 实验中存在的不足和改进方向7·3 实验对于数据结构学习的启示和意义附件列表:1·实验所用的源代码文件2·实验中用到的测试数据文件注释:1·哈夫曼编码:一种用于数据压缩的编码方法,根据字符出现频率构建树形结构,实现高频字符用较短编码表示,低频字符用较长编码表示。

2·哈夫曼树:由哈夫曼编码算法构建的一种特殊的二叉树,用于表示字符编码的结构。

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

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

数据结构哈夫曼编码实验报告数据结构哈夫曼编码实验报告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 构建哈夫曼树根据字符频率构建哈夫曼树是哈夫曼编码的核心步骤。

我们可以使用最小堆(优先队列)来高效地构建哈夫曼树。

首先,将每个字符频率作为节点存储到最小堆中。

然后,从最小堆中取出频率最小的两个节点,将它们作为子树构建成一个新的节点,新节点的频率等于两个子节点频率的和。

将新节点重新插入最小堆,并重复该过程,直到最小堆中只剩下一个节点,即哈夫曼树的根节点。

哈夫曼树实验报告(付原c语言程序)

哈夫曼树实验报告(付原c语言程序)

哈夫曼树实验报告(付原c语言程序)需求分析:从终端读入一串字符,利用建立好的哈夫曼树对其进行编码,储存到文件当中去,然后从文件读入哈夫曼编码,针对每个字母对其进行译码,翻译为原来的信息。

二、概要设计程序分为以下几个模块:1、从终端读入字符集大小,n个字符和n个权值,建立哈夫曼树,写入文件2、对hfmTree进行编码,建立hfm编码表。

hfmTree中去。

3、从文件ToTran读入信息,根据hfm编码表对其进行hfm编码,将编码后的信息写入文件Codefile中去4、对Codefile文件反向译码,结果储存在Textfile5、将建立的hfmTree打印在终端上,并储存于相应的中去。

Treeprint文件中去。

抽象的数据定义如下:哈夫曼树结构typedefstruct//定义哈夫曼树的结构{intweight;intparent;intlchild;intrchild;////////权值双亲左孩子右孩子}htnode,huffmantree[M+1];建立哈夫曼树voidcrthuffmantree(huffmantreeht,intw[],intn)//初始化哈夫曼树{inti,s1,s2,m;for(i=1;i<=n;i++) {ht[i].weight=w[i]; ht[i].parent=0;ht[i].lchild=0;ht[i].rchild=0;}m=2*n-1;for(i=n+1;i<=m;i++) {ht[i].weight=0;ht[i].parent=0;ht[i].lchild=0;ht[i].rchild=0;}for(i=n+1;i<=m;i++){select(ht,i-1,&s1,&s2);ht[i].weight=ht[s1].weight+ht[s2].weight;ht[s1].parent=i;ht[s2].parent=i;ht[i].lchild=s1;ht[i].rchild=s2;}}typedefchar*huffmancode[N+1];//建立哈夫曼树编码表voidcrthuffmancode(huffmantreeht,huffmancodehc,intn){ char*cd;//新建立一个指针intstart,i,c,p;cd=(char*)malloc(n*sizeof(char))cd[n-1]='\0';//;//分配求一个字符的哈夫曼编码的空间编码结束符for(i=1;i<=n;i++){start=n-1;c=i;p=ht[i].parent;while(p!=0){--start;if(ht[p].lchild==c)cd[start]='0';elsecd[start]='1';c=p;p=ht[p].parent;}hc[i]=(char*)malloc((n-start)*sizeof(char)); strcpy(hc[i],&cd[start]);}free(cd);}select(huffmantreeht,intpos,int*s1,int*s2)//取最小和次小权值{intj,m1,m2;m1=m2=maxint;for(j=1;j<=pos;j++){if(ht[j].weight<m1&&ht[j].parent==0)//定义为双亲为零时才开始求,这样就做到了防止筛选过的重新加入比较列表里{m2=m1;*s2=*s1;*s1=j;m1=ht[j].weight;}elseif(ht[j].weight<m2&&ht[j].parent==0){m2=ht[j].weight;*s2=j;}}}主程序模块intmain(){初始化参数printf("请输入:初始化I;编码E;译码D;印代码文件P;印哈弗曼树T\n");printf("结束请输入Q\n");while(1){//这就是用户输入scanf("%c",&q);if(q=='Q'){break;}if(q=='I'){fpw=fopen("hfmtree.txt","w");ftest=fopen("date.txt","r");printf("请输入密码表,第一位表示密码表大小,之后按空格键开始以紧凑的格式输入编码字母和权值。

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

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

数据结构实验报告----约瑟夫环一、需求分析:约瑟夫环是程序的一道经典例题,可以使用数据结构的单链表进行编写。

二、概要设计:大体上可以使用单链表通过节点的创建和删除来达到人数出列的效果,可以大大缩短程序量。

三、详细设计: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);}四、调试分析:程序仅能使用一次,并且输入格式没有提示,容易犯错。

数据结构哈夫曼树编码译码实验报告.doc

数据结构哈夫曼树编码译码实验报告.doc

数据结构哈夫曼树编码译码实验报告.【详细设计】具体代码实现如下://HaffmanTree.h#include#include#includestruct HuffmanNode //哈夫曼树的一个结点{ int weight; int parent; int lchild,rchild; };class HuffmanTree //哈夫曼树{private: HuffmanNode *Node; //Node[]存放哈夫曼树char *Info; //Info[]存放源文用到的字符——源码,如'a','b','c','d','e',此内容可以放入结点中,不单独设数组存放int LeafNum; //哈夫曼树的叶子个数,也是源码个数public: HuffmanTree(); ~HuffmanTree(); void CreateHuffmanTree(); /*在内存中建立哈夫曼树,存放在Node[]中。

让用户从两种建立哈夫曼树的方法中选择:1.从键盘读入源码字符集个数,每个字符,和每个字符的权重,建立哈夫曼树,并将哈夫曼树写入文件hfmTree中。

2.从文件hfmTree中读入哈夫曼树信息,建立哈夫曼树*/ void CreateHuffmanTreeFromKeyboard(); void CreateHuffmanTreeFromFile(); void Encoder(); /*使用建立好的哈夫曼树(如果不在内存,则从文件hfmTree中读入并建立内存里的哈夫曼树),对文件ToBeTran中的正文进行编码,并将码文写入文件CodeFile中。

ToBeTran的内容可以用记事本等程序编辑产生。

*/ void Decoder(); /*待译码的码文存放在文件CodeFile中,使用建立好的哈夫曼树(如果不在内存,则从文件hfmTree中读入并建立内存里的哈夫曼树)将码文译码,得到的源文写入文件TextFile中,并同时输出到屏幕上。

哈夫曼树实验报告

哈夫曼树实验报告

哈夫曼树实验报告一、需求分析(1)输入输出形式输入数组的组数n: 整形变量组数(回车)请依次输入n组权值与字符, 中间用空格隔开。

如“2 a”:按右提示格式输入(回车)请输入待编译文本: 随机输入字符(回车)输出: 编译出的代码请输入待编译代码: 随机输入一串代码(回车)(2)输出: 编译出的代码(3)程序功能1. 用C语言实现二叉树的说明2. 输入n个权值, 并生成n个二叉树3. 对n个二叉树逐步生成Huffman树4. 对Huffman树的每个叶子结点生成编码5.用哈夫曼树编码。

6.解码哈夫曼编码。

(4)测试用例设计Example1: 输入325 a15 b60 cabbacc010*******输出010*******abbaccExample2: 输入510 a20 b30 c20 d10 eababcde10000100001101101输出10000100001101101ababcde二、概要设计1.根据给定的n个权值(w1, w2, …, wn)构成n棵二叉树的集合F={T1, T2, …, Tn}, 其中每棵二叉树Ti中只有一个带树为Ti的根结点在F中选取两棵根结点的权值最小的树作为左右子树构造一棵新的二叉树, 且置其根结点的权值为其左右子树权值之和3.在F中删除这两棵树, 同时将新得到的二叉树加入F中4.重复2, 3, 直到F只含一棵树为止三、 5.将给定的字符串通过程序编码成哈夫曼编码, 并打印结果在屏幕上。

四、 6.翻译给定的哈夫曼编码变成可读字符串, 并将结果打印在屏幕上。

五、详细设计四、调试分析(1)编译代码、运行代码所遇到的问题及其解决办法问题1: 编译代码过程中有遇到循环体的循环次数不对, 导致二叉树生成得不对解决办法:通过小数字的演算, 检验循环, 再进行更改(2)算法的时空分析(3)心得体会五、用户使用说明如上图所示, 依次输入组数、权值及全值所对应字符。

再根据用户自身需求输入需编译的文本及代码。

哈夫曼编码解码实验报告

哈夫曼编码解码实验报告

哈夫曼编码解码实验1.实验要求掌握二叉树的相关概念掌握构造哈夫曼树,进行哈夫曼编码。

对编码内容通过哈夫曼树进行解码。

2.实验内容通过二叉树构造哈夫曼树,并用哈夫曼树对读取的txt文件进行哈夫曼编码。

编码完成后通过哈夫曼树进行解码。

#include<stdio.h>#include<string.h>#define MAX 100//定义哈夫曼树的存储结构typedef struct{char data;int weight;int parent;int lch;int rch;}HuffNode;//定义哈夫曼编码的存储结构typedef struct{char bit[MAX];int start;}HuffCode;HuffNode ht[2*MAX];HuffCode hcd[MAX];int Coun[127]={0};int n;char s1[200000];char text[5000];//构造哈夫曼树void HuffmanTree(){int i,j,k,left,right,min1,min2;//printf("输入叶子的节点数:");//scanf("%d",&n);printf("字符数量=%d\n",n);for(i=1;i<=2*n-1;i++){ht[i].parent=ht[i].lch=ht[i].rch=0;}j=0;for(i=1;i<=n;i++){/*getchar();printf("输入第%d个叶子节点的值:",i);scanf("%c",&ht[i].data);printf("输入该节点的权值:");scanf("%d",&ht[i].weight);*/for(;j<127;j++){if(Coun[j]!=0){ht[i].data=j;//printf("%c",ht[i].data);ht[i].weight=Coun[j];//printf("%d",ht[i].weight);break;}}j++;}printf("\n");for(i=1;i<=n;i++){printf("%c",ht[i].data);}printf("\n");for(i=n+1;i<=2*n-1;i++){//在前n个结点中选取权值最小的两个结点构成一颗二叉树min1=min2=10000;//为min1和min2设置一个比所有权值都大的值left=right=0;for(k=1;k<=i-1;k++){if(ht[k].parent==0)//若是根结点//令min1和min2为最小的两个权值,left和right 为权值最小的两个结点位置if(ht[k].weight<min1){min2=min1;right=left;min1=ht[k].weight;left=k;}else if (ht[k].weight<min2){min2=ht[k].weight;right=k;}}ht[left].parent=i;ht[right].parent=i;ht[i].weight=ht[left].weight+ht[right].weight;ht[i].lch=left;ht[i].rch =right;}}//构造哈夫曼编码void HuffmanCode(){int i,c,k,f;HuffCode cd;for(i=1;i<=n;i++){cd.start=n;c=i;f=ht[i].parent;while(f!=0){if(ht[f].lch==c)cd.bit[cd.start]='0';elsecd.bit[cd.start]='1';cd.start--;c=f;f=ht[f].parent;}hcd[i]=cd;}printf("输出哈夫曼编码:\n");for(i=1;i<=n;i++){printf("%c:",ht[i].data);for(k=hcd[i].start+1;k<=n;k++)printf("%c",hcd[i].bit[k]);printf("\n");}}//对字母进行编码void Code()//将字符与相应的哈夫曼编码进行匹配,输出编码结果{int i=0,j,k,h=0;while(text[i]!='\0'){for(j=1;j<=n;j++){if(text[i]==ht[j].data){for(k=hcd[j].start+1;k<=n;k++){s1[h]=hcd[j].bit[k];h++;}break;}}i++;}//printf("编码\n");//puts(s1);//printf("\n");}//解码void HuffmanDecode(){printf("解码\n");int len,i,f;char C;//char S[MAXCODE];//scanf("%s",S);//使用gets()直接跳过len=strlen(s1);printf("s1:%d\n",len);f=2*n-1;for(i=0;i<len;i++){if(s1[i]=='0'){f=ht[f].lch;if(ht[f].lch==0&&ht[f].rch==0){C=ht[f].data;printf("%c",C);f=2*n-1;}}else if(s1[i]=='1'){f=ht[f].rch;if(ht[f].lch==0&&ht[f].rch==0){C=ht[f].data;printf("%c",C);f=2*n-1;}}}printf("\n");}//统计字母个数及其权值void Count(){int i,j,m;n=0;i=0;//printf("请仅输入小写字母\n");//例程本省存在一个BUG,只输入一个字母不能进行编码(并未解决)//scanf("%s",s);while(text[i]!='\0')//使用ASCII码表进行统计{m=text[i];//printf("%d\n",m);Coun[m]++;i++;}for(j=0;j<127;j++){if(Coun[j]!=0)n++;}}//mark Codevoid main(){int l=0;FILE *fp;fp=fopen("text.txt","r");if(fp==NULL){printf("文件打开失败\n");while(1);}while(!feof(fp)){text[l] = fgetc(fp);l++;}printf("输入文本\n");printf("%s\n",text);fclose(fp);Count();HuffmanTree();HuffmanCode();Code();HuffmanDecode();}文本文件文本输入进行哈夫曼编码对文本进行编码输出解码结果3.实验总结通过本次实验,对二叉树的应用有了相应的了解,掌握了如何构造哈夫曼编码,如何对编码结果进行解码。

哈夫曼树实验实验报告(3篇)

哈夫曼树实验实验报告(3篇)

第1篇一、实验目的1. 理解哈夫曼树的基本概念和构造方法。

2. 掌握哈夫曼编码和译码的原理及实现过程。

3. 熟练运用哈夫曼树解决实际问题,提高数据压缩效率。

二、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发环境:Visual Studio 2019三、实验内容1. 构造哈夫曼树2. 哈夫曼编码3. 哈夫曼译码四、实验步骤1. 数据准备(1)创建一个包含字符及其权值的数组,例如:`{'a', 5, 'b', 9, 'c', 12, 'd', 13, 'e', 16, 'f', 45}`。

(2)根据数组内容,使用C++编写程序,实现以下功能:- 将数组元素插入到最小堆中。

- 构建哈夫曼树。

2. 哈夫曼编码(1)遍历哈夫曼树,记录每个字符的编码。

(2)根据编码规则,将字符和编码存储在映射表中。

(3)将映射表输出到文件中。

3. 哈夫曼译码(1)从文件中读取编码序列。

(2)根据哈夫曼树,逐个解码字符。

(3)将解码后的字符输出到文件中。

五、实验结果1. 哈夫曼树```45/ \16 29/ \ / \13 3 12 4/ \ / / \d c b a f```2. 哈夫曼编码```a: 0b: 100c: 101d: 110e: 111f: 1```3. 编码前后的数据```原始数据:abcdef编码后数据:0100110110111011```六、实验分析1. 哈夫曼树通过构建哈夫曼树,可以将权值较小的字符分配较短的编码,权值较大的字符分配较长的编码,从而提高数据压缩效率。

2. 哈夫曼编码哈夫曼编码是一种前缀编码,可以保证解码过程不会产生歧义。

3. 哈夫曼译码通过哈夫曼树,可以快速地将编码序列解码为原始数据。

七、实验总结1. 通过本次实验,掌握了哈夫曼树的基本概念、构造方法、编码和译码原理。

哈夫曼实验报告

哈夫曼实验报告

一、实验目的1. 理解哈夫曼编码的基本原理和重要性。

2. 掌握哈夫曼树的构建方法。

3. 熟悉哈夫曼编码和译码的实现过程。

4. 分析哈夫曼编码在数据压缩中的应用效果。

二、实验原理哈夫曼编码是一种基于字符频率的编码方法,它利用字符出现的频率来构造一棵最优二叉树(哈夫曼树),并根据该树生成字符的编码。

在哈夫曼树中,频率越高的字符对应的编码越短,频率越低的字符对应的编码越长。

这样,对于出现频率较高的字符,编码后的数据长度更短,从而实现数据压缩。

三、实验内容1. 构建哈夫曼树:- 统计待编码数据中每个字符出现的频率。

- 根据字符频率构建哈夫曼树,其中频率高的字符作为叶子节点,频率低的字符作为内部节点。

- 重复上述步骤,直到树中只剩下一个节点,即为哈夫曼树的根节点。

2. 生成哈夫曼编码:- 从哈夫曼树的根节点开始,对每个节点进行遍历,根据遍历方向(左子树为0,右子树为1)为字符分配编码。

- 将生成的编码存储在编码表中。

3. 编码和译码:- 使用生成的编码表对原始数据进行编码,将编码后的数据存储在文件中。

- 从文件中读取编码后的数据,根据编码表进行译码,恢复原始数据。

四、实验步骤1. 编写代码实现哈夫曼树的构建:- 定义节点结构体,包含字符、频率、左子树、右子树等属性。

- 实现构建哈夫曼树的核心算法,包括节点合并、插入等操作。

2. 实现编码和译码功能:- 根据哈夫曼树生成编码表。

- 编写编码函数,根据编码表对数据进行编码。

- 编写译码函数,根据编码表对数据进行译码。

3. 测试实验效果:- 选择一段文本数据,使用实验代码进行编码和译码。

- 比较编码前后数据的长度,分析哈夫曼编码的压缩效果。

五、实验结果与分析1. 哈夫曼树构建:- 成功构建了哈夫曼树,树中节点按照字符频率从高到低排列。

2. 哈夫曼编码:- 成功生成编码表,字符与编码的对应关系符合哈夫曼编码原理。

3. 编码与译码:- 成功实现编码和译码功能,编码后的数据长度明显缩短,译码结果与原始数据完全一致。

哈弗曼树实验报告(3篇)

哈弗曼树实验报告(3篇)

一、实验目的1. 理解并掌握哈弗曼树的构建原理。

2. 学会使用哈弗曼树进行数据编码和解码。

3. 了解哈弗曼编码在数据压缩中的应用。

二、实验原理哈弗曼树(Huffman Tree)是一种带权路径长度最短的二叉树,用于数据压缩。

其基本原理是:将待编码的字符集合按照出现频率从高到低排序,构造一棵二叉树,使得叶子节点代表字符,内部节点代表编码,权值代表字符出现的频率。

通过这棵树,可以生成每个字符的编码,使得编码的平均长度最小。

三、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发工具:Visual Studio 2019四、实验步骤1. 构建哈弗曼树(1)创建一个结构体`HuffmanNode`,包含字符、权值、左子树和右子树指针。

```cppstruct HuffmanNode {char data;int weight;HuffmanNode left;HuffmanNode right;};(2)定义一个函数`HuffmanTree()`,用于创建哈弗曼树。

```cppHuffmanNode HuffmanTree(std::vector<char>& chars, std::vector<int>& weights) {// 创建初始二叉树std::vector<HuffmanNode> trees;for (int i = 0; i < chars.size(); ++i) {trees.push_back(new HuffmanNode{chars[i], weights[i], nullptr, nullptr});}// 构建哈弗曼树while (trees.size() > 1) {// 选择两个权值最小的节点auto it1 = std::min_element(trees.begin(), trees.end(),[](HuffmanNode a, HuffmanNode b) {return a->weight < b->weight;});auto it2 = std::next(it1);HuffmanNode parent = new HuffmanNode{0, it1->weight + it2->weight, it1, it2};// 删除两个子节点trees.erase(it1);trees.erase(it2);// 将父节点添加到二叉树集合中trees.push_back(parent);}// 返回哈弗曼树根节点return trees[0];}```2. 生成哈弗曼编码(1)定义一个函数`GenerateCodes()`,用于生成哈弗曼编码。

数据结构 哈夫曼编码实验报告(2023版)

数据结构 哈夫曼编码实验报告(2023版)

数据结构哈夫曼编码实验报告实验目的:本实验旨在了解和实现哈夫曼编码算法,通过将字符转换为对应的哈夫曼编码来实现数据的压缩和解压缩。

一、引言1.1 背景介绍哈夫曼编码是一种基于字符出现频率的编码方法,通过使用不等长编码来表示不同字符,从而实现数据的高效压缩。

该编码方法在通信、存储等领域有着广泛的应用。

1.2 目标本实验的目标是实现哈夫曼编码算法,通过对给定文本进行编码和解码,验证哈夫曼编码的有效性和可靠性。

二、实验过程2.1 数据结构设计在实现哈夫曼编码算法时,我们需要设计合适的数据结构来存储字符和对应的编码。

常用的数据结构包括树和哈希表。

我们将使用二叉树作为数据结构来表示字符的编码。

2.2 构建哈夫曼树哈夫曼树是由给定字符集合构建而成的最优二叉树。

构建哈夫曼树的过程分为两步:首先根据字符出现频率构建叶子节点,然后通过合并叶子节点和父节点构造哈夫曼树。

2.3 哈夫曼编码表根据构建好的哈夫曼树,我们可以对应的哈夫曼编码表。

哈夫曼编码表由字符和对应的编码组成,可以用于字符的编码和解码。

2.4 文本压缩利用的哈夫曼编码表,我们可以对给定的文本进行压缩。

将文本中的字符逐个替换为对应的哈夫曼编码,从而实现数据的压缩。

2.5 文本解压缩对压缩后的数据进行解压缩时,我们需要利用的哈夫曼编码表,将哈夫曼编码逐个替换为对应的字符,从而还原出原始的文本数据。

三、实验结果我们使用不同长度、不同频率的文本进行了实验。

实验结果表明,哈夫曼编码在数据压缩方面有着显著的效果,可以大大减小数据存储和传输的开销。

四、实验总结通过本实验,我们深入理解了哈夫曼编码算法的原理和实现过程,掌握了数据的压缩和解压缩技术。

哈夫曼编码作为一种经典的数据压缩算法,具有重要的理论意义和实际应用价值。

附件:本文档附带哈夫曼编码实验的源代码和实验数据。

法律名词及注释:在本文档中,涉及的法律名词和注释如下:1.哈夫曼编码:一种数据压缩算法,用于将字符转换为可变长度的编码。

哈夫曼编码实验报告

哈夫曼编码实验报告

哈夫曼编码实验报告①问题描述:给定n个字符的权值数组w,根据哈夫曼编码与译码规则,实现一个哈夫曼编/译码系统(利用实验指导书上的27个字符的数据进行实验)。

②利用顺序表存储Huffman树,编码结果的存储方式采用书上的结构。

③Huffman树的构造约定如下:根的权值较小的子树作为左子树,当权值相等时,则先生成的子树是左子树;按照结点的生成次序选择权值较小的两棵子树构造Huffman树;从叶子结点到根结点逆向求出每个字符的Huffman编码,不采用递归方法;从根结点开始实现译码,要求被译码的字符数大于20个字符。

④采用文件方式存储n个权值和待翻译的二进制代码,其余数据均不采用文件存储。

序号字符权值双亲结点左孩子右孩子1 □186 0 0 02 A 64 0 0 03 B 13 0 0 04 C 22 0 0 05 D 32 0 0 06 E 103 0 0 07 F 21 0 0 08 G 15 0 0 09 H 47 0 0 010 I 57 0 0 011 J 1 0 0 012 K 5 0 0 013 L 32 0 0 014 M 20 0 0 015 N 57 0 0 016 O 63 0 0 017 P 15 0 0 018 Q 1 0 0 019 R 48 0 0 020 S 51 0 0 021 T 80 0 0 022 U 23 0 0 023 V 8 0 0 024 W 18 0 0 025 X 1 0 0 026 Y 16 0 0 027 Z 1 0 0 0实验过程与结果完整代码:(实验环境codeblock)关闭程序,重新开始,此时选择读取文件方式构建哈夫曼树,文件hafuman.txt中存储着各叶子节点权值,对应字符和待编译的二进制编码,读取文件截图如下,其他操作6.7.8及结果同上。

哈夫曼实验报告(附代码)

哈夫曼实验报告(附代码)

哈弗曼编码/译码器一、程序的功能分析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.主模块的流程及各子模块的主要功能主函数负责提供选项功能,循环调控整个系统。

创建模块实现接收字符、权值、构建哈夫曼树,并保存文件,此功能是后续功能的基础。

编码模块实现利用已编好的哈夫曼树对每个字符进行哈夫曼编码,即对每个字符译出其密文代码,并保存文件。

译码模块实现对用户输入的密文翻译成明文,即用户所需的字符串信息。

输出模块实现对已编好的哈夫曼树以凹入表的的形式输出。

2、模块之间的层次关系四、详细设计1.采用c语言定义的相关数据类型(1)结点的类型定义描述如下:#define N 叶子结点的个数typedef strcut{int weight; /*结点权值*/int parent;int lchild;int rchild;}HNodeType;HNodeType HNode[2*N-1];(2)编码的类型定义描述如下:#define MAXBIT 10typedef struct{int bit[MAXBIT];int start;}HCodeType;HCodeType HCode[N];2.各模块伪算法(1)主函数int main(){do:{界面友好设计;cout<<各个选项功能内容;cin>>ch;容错处理;switch(ch){case 1:.....}}while();return 0;}(2)系统初始化模块void create() //系统初始化{for(i=0;i<2*N-1;i++) //数组HNode初始化{};从键盘接收字符;for(i=0;i<N;i++){ cout<<"输入字符"<<endl;cin>>HNode[i].data;}接收权值;构造哈夫曼树;for(i=0;i<N-1;i++){ 找最小和次小两个权值;将找出的两棵子树合并为一棵子数;}将已建好的哈夫曼树存入文件hfmtree.txt中;调用哈夫曼编码子函数;}void HaffmanCode() //对哈夫曼树进行编码{从hfmtree.txt文件中读出哈夫曼树的信息存入内存HNodeType a[2*N-1];求每个叶子结点的哈夫曼编码;for(i=0;i<N;i++){从叶节点回溯,回溯到根结点(parent==-1);记录回溯路径;}打印出每个字符对应的密文;将密文信息存入文件codefile.dat中;}(3)编码模块void HfmanCode() //对用户输入的字符串进行编码{提示输入信息;接收用户输入的要编译的字符串;cin>>s;//从文件中读取哈夫曼编码信息infile.open ("F:\\codefile.dat",ios::in|ios::binary); //读文件for(i=0;i<N;i++) //将文件中的数据读出放在temp[i]内//从文件中读字节到指定的存储器区域。

哈夫曼树和哈夫曼编码——实验报告

哈夫曼树和哈夫曼编码——实验报告

实验报告学生姓名 学号专业 年级、班级课程名称 实验项目 排队系统的模拟 实验类型✓ 综合实验时间 年 月 日实验指导老师 实验评分1、实验项目名称哈夫曼树和哈夫曼编码2、实验目的及要求掌握哈夫曼树和哈夫曼编码的实现3、实验内容及步骤(1)新建一个工程——Win32 Console Application,为工程取名——创建一个简单的程序【S】(2)进入类视图,添加类——鼠标右键,点击New Class——输入类的名称,点击确定。

(3)将对应代码放入对应文件——5-13代码放入 hfTree.h文件;5-14、5.15代码放入hfTree.cpp文件;5-16代码放入幂函数文件ex 007.cpp。

(//后绿色的字是在分析代码)(4)组建、编译,运行结果4、实验结果及分析5-13 哈夫曼树类的定义代码分析template <class Type>//模板类class hfTree{private:struct Node//数组中的元素类型:一个结点{ Type data;//结点值int weight;//结点的权值int parent,left,right;//父结点以及左右儿子的下标地址};Node *elem;//定义一个数组,elem是数组的起始位置,哈夫曼树被保存在一个数组中int length;//数组的规模长度public:struct hfCode{//保存赫夫曼编码的类型Type data;//待编码的字符string code;//对应的哈夫曼编码};hfTree(const Type*x,const int*w,int size);//构造函数,构造函数接收一组待编码的字符以及对应的权值,构造一棵哈夫曼树void getCode(hfCode result[]);//返回哈夫曼编码的函数~hfTree(){delete []elem;}//析构函数,释放存储空间};5-14 哈夫曼树的构造函数代码分析template <class Type>hfTree<Type>::hfTree(const Type*v,const int *w,int size)//哈夫曼树的构造函数,有3个参数,一组待编码的符号,符号对应的权值,前面两个数组的数组规模{ const int MAX_INT=32767;int min1,min2;//最小树、次小树的权值int x,y;//最小树、次小树的下标length=2*size;//保存哈夫曼树的数组规模是符号数组、权值数组的两倍elem=new Node[length];//申请一个保存哈夫曼树的数组for(int i=size;i<length;++i)//for循环为数组赋初值{ elem[i].weight=w[i-size];//将待编码的符号对应的权值放到数组的后半部分elem[i].data=v[i-size];//将待编码的符号放到数组的后半部分 elem[i].parent=elem[i].left=elem[i].right=0;//将符号的父结点以及左右儿子都设为0,表明它们都是只有根结点的树}for(i=size-1;i>0;--i)//for循环完成size-1次的归并{ min1=min2=MAX_INT;x=y=0;// min1,min2分别保存两棵权值最小的数的权值,x、y分别表示这两棵树的树根在数组中的下标for(int j=i+1;j<length;++j)//找出父结点为0,且权值最小和次小的两棵树,等待归并的两棵树if(elem[j].parent==0)if(elem[j].weight<min1){min2=min1;min1=elem[j].weight;x=y;y=j;}else if(elem[j].weight<min2){min2=elem[j].weight;x=j;}elem[i].weight=min1+min2;//归并这两棵树,形成新树i,i这棵树的权值=min1+min2(分别保存挑选出的两棵权值最小的树的权值) elem[i].left=x;elem[i].right=y;elem[i].parent=0;//将挑选出来的两个结点作为左、右子树,构建一棵新树,i为根结点elem[x].parent=i;elem[y].parent=i;//i是挑选出来的两个结点的父结点}}5-15 哈夫曼的getCode函数代码分析template <class Type>void hfTree<Type>::getCode(hfCode result[])//哈夫曼树的getCode函数,返回的是一个数组,数组元素类型是hfCode,每一个元素包含待编码的符号和它对应的编码,编码是一个比特串,用字符串类型表示{ int size=length/2;//符号数组规模=哈夫曼数组规模/2int p,s;//s是追溯过程中正在处理结点的下标,p是s的父结点下标for(int i=size;i<length;++i)//读取每一个符号{result[i-size].data=elem[i].data; // result数组中第一个元素符号是哈夫曼数组elem中间的元素符号,因为哈夫曼数组elem包含了元素符号数组和元素符号权值数组,而符号数组规模=权值数组规模,所以哈夫曼数组elem数组是它们的两倍。

哈夫曼编码实验报告

哈夫曼编码实验报告

哈夫曼编码实验报告数据结构实验报告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)选出权值最小的两个结点,其权值和作为其根结点的权值,最小的结点作为左子树,次小的作为右子树,不断将两棵子树合并为一棵树。

数据结构实验哈夫曼树及哈夫曼编码c语言

数据结构实验哈夫曼树及哈夫曼编码c语言

数据结构实验报告:哈夫曼树及哈夫曼编码一、实验目的1. 理解哈夫曼树及哈夫曼编码的概念和原理;2. 掌握C语言中哈夫曼树及哈夫曼编码的实现方法;3. 分析和讨论哈夫曼编码在实际应用中的优势和不足。

二、实验内容和步骤1. 哈夫曼树的构建1.1 通过C语言实现哈夫曼树的构建算法;1.2 输入一组权值,按哈夫曼树构建规则生成哈夫曼树;1.3 输出生成的哈夫曼树结构,并进行可视化展示。

2. 哈夫曼编码的实现2.1 设计哈夫曼编码的实现算法;2.2 对指定字符集进行编码,生成哈夫曼编码表;2.3 对给定字符串进行哈夫曼编码,并输出编码结果。

三、实验过程及结果1. 哈夫曼树的构建在C语言中,通过定义结构体和递归算法实现了哈夫曼树的构建。

根据输入的权值,依次选择权值最小的两个节点构建新的父节点,直至构建完成整棵哈夫曼树。

通过调试和可视化展示,确认了程序正确实现了哈夫曼树的构建。

2. 哈夫曼编码的实现经过分析和设计,利用哈夫曼树的特点实现了哈夫曼编码的算法。

根据生成的哈夫曼树,递归地生成字符对应的哈夫曼编码,并输出编码结果。

对指定的字符串进行了编码测试,验证了哈夫曼编码的正确性和有效性。

四、实验结果分析1. 哈夫曼编码在数据传输和存储中具有较高的压缩效率和可靠性,能够有效减少数据传输量和存储空间;2. 哈夫曼树及哈夫曼编码在通信领域、数据压缩和加密等方面有着广泛的应用和重要意义;3. 在实际应用中,哈夫曼编码的构建和解码算法需要较大的时间和空间复杂度,对于大规模数据的处理存在一定的局限性。

五、实验总结通过本次实验,深入理解了哈夫曼树及哈夫曼编码的理论知识,并掌握了C语言中实现哈夫曼树及哈夫曼编码的方法。

对哈夫曼编码在实际应用中的优势和局限性有了更深入的认识,这对今后的学习和工作有着积极的意义。

六、参考文献1. 《数据结构(C语言版)》,严蔚敏赵现军著,清华大学出版社,2012年;2. 《算法导论》,Thomas H. Cormen 等著,机械工业出版社,2006年。

赫夫曼编码实验报告

赫夫曼编码实验报告

实验五哈夫曼树和哈夫曼树编码学院专业班学号姓名一.实习目的1.掌握哈夫曼树的顺序存储方式;2.掌握建立哈夫曼树的方法;3.掌握由哈夫曼树构造哈夫曼编码的方法。

二.实习内容1.建立哈夫曼树的顺序存储结构;2.编程实现构建一棵哈夫曼树。

3.编程实现由哈夫曼树构造出哈夫曼编码三. 实习步骤1..程序代码#include<malloc.h> // malloc()等#include<limits.h> // INT_MAX等#include<stdio.h> //#include<stdlib.h> //#include<string.h>typedef struct{unsigned int weight;unsigned int parent,lchild,rchild;}HTNode,*HuffmanTree; // 动态分配数组存储赫夫曼树typedef char **HuffmanCode; // 动态分配数组存储赫夫曼编码表int min(HuffmanTree t,int i){ // 返回i个结点中权值最小的树的根结点序号, 函数select()调用int j,flag;unsigned int k=UINT_MAX; // 取k为不小于可能的值(无符号整型最大值) for(j=1;j<=i;j++)if(t[j].weight<k&&t[j].parent==0) // t[j]是树的根结点k=t[j].weight,flag=j;t[flag].parent=1; // 给选中的根结点的双亲赋1, 避免第2次查找该结点return flag;}void select(HuffmanTree t,int i,int &s1,int &s2){ // 在i个结点中选择2个权值最小的树的根结点序号, s1为其中序号小的那个int j;s1=min(t,i);s2=min(t,i);if(s1>s2){j=s1;s1=s2;s2=j;}}void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n) // 算法6.12{ // w存放n个字符的权值(均>0), 构造赫夫曼树HT, 并求出n个字符的赫夫曼编码HC int m,i,s1,s2,start;unsigned c,f;HuffmanTree p;char *cd;if(n<=1)return;m=2*n-1;HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); // 0号单元未用for(p=HT+1,i=1;i<=n;++i,++p,++w){(*p).weight=*w;(*p).parent=0;(*p).lchild=0;(*p).rchild=0;}for(;i<=m;++i,++p)(*p).parent=0;for(i=n+1;i<=m;++i) // 建赫夫曼树{ // 在HT[1~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;}// 从叶子到根逆向求每个字符的赫夫曼编码HC=(HuffmanCode)malloc((n+1)*sizeof(char*));// 分配n个字符编码的头指针向量([0]不用)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].lchild==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); // 释放工作空间}void main(){HuffmanTree HT;HuffmanCode HC;int *w,n,i;printf("请输入权值的个数(>1): ");scanf("%d",&n);w=(int*)malloc(n*sizeof(int));printf("请依次输入%d个权值(整型):\n",n);for(i=0;i<=n-1;i++)scanf("%d",w+i);HuffmanCoding(HT,HC,w,n);printf("huffman树存储结构: \n");for( i=1;i<2*n;i++)printf("%4d%4d%4d%4d\n", HT[i].weight,HT[i].parent,HT[i].lchild,HT[i].rchild);// 输出哈夫曼树的每个结点的权值、父亲结点序号、左孩子和右孩子序号。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
三、概要设计
1.主模块的流程及各子模块的主要功能
主函数负责提供选项功能,循环调控整个系统。
创建模块实现接收字符、权值、构建哈夫曼树,并保存文件,此功能是后续功能的基础。
编码模块实现利用已编好的哈夫曼树对每个字符进行哈夫曼编码,即对每个字符译出其密文代码,并保存文件。
译码模块实现对用户输入的密文翻译成明文,即用户所需的字符串信息。
哈弗曼编码/译码器
一、程序的功能分析
1.构造哈夫曼树及哈夫曼编码:从终端读入字符集大小n、n个字符以及n个对应的权值,建立哈夫曼树;利用已经建好的哈夫曼树求每个叶结点的哈夫曼编码,并保存。
2.编码:利用已构造的哈夫曼编码对“明文”文件中的正文进行编码,然后将结果存入“密文”文件中。
3.译码:将“密文”文件中的0、1代码序列进行译码。(读文件)
4.打印“密文”文件:将文件以紧凑格式显示在终端上,每行30个代码;同时,将此字符形式的编码文件保存。
5.打印哈夫曼树及哈夫曼编码:将已在存中的哈夫曼树以凹入表形式显示在终端上,同时将每个字符的哈夫曼编码显示出来;并保存到文件。
二、基本要求分析
1、输入输出的要求
按提示容从键盘输入命令,系统根据用户输入的需求在保证界面友好的前提下输出用户所需信息,并按要求保存文件,以便保存备份信息。
for(i=0;i<N;i++) //将文件中的数据读出放在temp[i]
//从文件中读字节到指定的存储器区域。
infile.read ((char*)&temp[i],sizeof(temp[i]));
循环实现将用户输入的字符串转换成对应的密文,并保存;
将保存结果存入密文文件;
}
(4)译码模块
(5)输出模块
从键盘接收字符;
for(i=0;i<N;i++)
{cout<<"输入字符"<<endl;
cin>>HNode[i].data;
}
接收权值;
构造哈夫曼树;
for(i=0;i<N-1;i++)
{找最小和次小两个权值;
将找出的两棵子树合并为一棵子数;
}
将已建好的哈夫曼树存入文件hfmtree.txt中;
调用哈夫曼编码子函数;
2.算法的时间复杂度
(1)创建模块 O(N^3)
(2)编码模块 O(N)
(3)译码模块 O(n) 其中n为用户输入的密文位数
(4)打印模块 O(N)
六、使用说明及测试结果
用户根据提示信息,初次使用本系统时要首先选择创建选项来初始化系统,根据提示信息输入信息,存入文件,使得后续功能顺利实现。非初次使用时,用户可根据自己的需求来选择功能选项,根据提示信息输入、获得所需信息。
字符串:whilwitchhiwwppppp 频率统计为
w
h
i
l
c
t
p
4
3
3
1
1
1
5
4.可实现多个编码文件共存以及容错处理
七、程序代码
#include<iostream.h>
#include<iomanip.h>
#include<fstream.h>
{
do:
{
界面友好设计;
cout<<各个选项功能容;
cin>>ch;
容错处理;
switch(ch)
{
case 1:
.....
}
}while();
return 0;
}
(2)系统初始化模块
void create() //系统初始化
{
for(i=0;i<2*N-1;i++) //数组HNode初始化
{};
测试:
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.自行选定一段英文文本,统计给出的字符集,实际统计字符的频度,建立哈夫曼树,构造哈夫曼编码,并实现其编码和译码。
将密文信息存入文件codefile.dat中;
}
(3)编码模块
void HfmanCode() //对用户输入的字符串进行编码
{
提示输入信息;
接收用户输入的要编译的字符串;
cin>>s;
//从文件中读取哈夫曼编码信息
infile.open ("F:\\codefile.dat",ios::in|ios::binary); //读文件
输出模块实现对已编好的哈夫曼树以凹入表的的形式输出。
2、模块之间的层次关系
四、详细设计
1.采用c语言定义的相关数据类型
(1)结点的类型定义描述如下:
#define N 叶子结点的个数
typedef strcut
{intweight;/*结点权值*/
intparent;
intlchild;
intrchild;
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).请自行选定一段英文文本,统计给出的字符集,实际统计字符的频度,建立哈夫曼树,构造哈夫曼编码,并实现其编码和译码。
}
void HaffmanCode() //对哈夫曼树进行编码
{
从hfmtree.txt文件中读出哈夫曼树的信息存入存HNodeType a[2*N-1];
求每个叶子结点的哈夫曼编码;
for(i=0;i<N;i++)
{
从叶节点回溯,回溯到根结点(parent==-1);
记录回溯路径;
}
打印出每个字符对应的密文;
五、调试分析
1.调试过程中遇到的问题和对问题的解决方法
对文件的读写操作不熟悉,调试时,将已写入的文件不能读出,以至于后续操作无法实现,对此,我有翻看C++程序设计课本,了解关于文件操作的具体容,明白二进制文件和文本文件的读写方式是有很大区别的,不可混淆操作。另外,对于程序的输出阶段开始时出现了问题,递归调用没有分析清楚,递归思想是层次分明,逐层深入。
}HNodeType;
HNodeType HNode[2*N-1];
(2)编码的类型定义描述如下:
#define MAXBIT 10
typedef struct
{intbit[MAXBIT];
intstart;
}HCodeType;
HCodeType HCode[N];
2.各模块伪算法
(1)主函数
int main()
相关文档
最新文档