哈夫曼编译码___数据结构C语言版课程设计
数据结构_哈弗曼树的编译码_课程设计_实验报告

1
验报告以及科技论文的能力。只有这样,我们的综合素质才会有好的提高。
2
2 需求分析 (1)问题描述:输入权的个数,对每一个字符进行编码,编码完成后再对其编 码进行译码。 (2)问题补充:1,以字符出现字数作为权值,构建哈夫曼树,并将哈夫曼树的 存储结构的初态和终态进行输出; 2. 对每个字符进行编码并编码,然后对所编码进行破译。 (3)具体介绍:在本课题中,我们以每个字符出现次数作为权值,调用 ChuffmanTree()函数构建哈夫曼树; 并调用 print1()和 print2()函数将哈 夫曼的存储结构的初态和终态进行输出。 然后调用 HuffmanEncoding() 函数对哈夫曼树进行编码,调用 coding()函数编码;再调用 decode() 对编码进行译码,再输出至界面。至此,整个工作就完成了。 开始
ห้องสมุดไป่ตู้
6 参考文献..........................................................................................................................................9 7 附录 源程序..................................................................................................................................10
5
2:读入 n 个权值放入向量 tree 的前 n 个分量中,它们是初始森林中的 n 个孤立 的根结点上的权值。 3:对森林中的树进行 n-1 次合并,共产生 n-1 个新结点,依次放入向量 tree 的 第 t 个分量中(n+1<=t<=m) (第 t 个分量的下标为 t-1) 。每次合并的步骤是:a 在当前森林的所有结点 tree[j](0<=j<=i-1,i=t-1)中,选取具有最小权值和 次小权值的两个根结点, 分别用 p1 和 p2 记住这两个根结点在向量 tree 的下标。 B 将根结点 tree[p1]和 tree[p2]的两棵树合并, 使其成为新结点 tree[i]的左右 孩子, 得到一颗以新结点 tree[i]为根的二叉树。 同时修改 tree[p1]和 tree[p2] 的双亲域 parent, 使其指向新结点 tree[i],这意味着它们在当前森林中已不再 是根,将 tree[p1]和 tree[p2]的权值相加后,作为新结点 tree[i]的权值。 ③编码 在哈弗曼树的存储结构中, 因为增加了结点与其双亲的链接,所以在具体实现求 哈弗曼编码的过程中,可以从哈弗曼树的叶结点 di(0<=i<=n-1)出发向上回溯 的根结点。其做法是:从哈弗曼树的叶子 tree[i]出发,利用双亲指针 parent 找到 tree[i]的 tree[p-1]的左还是右孩子,若是左孩子,则生成代码 0;否则 生成代码 1;然后以 tree[p-1]为出发点,重复上述过程,直到找到根结点为止。 显然,这样生成的代码序列与要求的编码次序相反,因此,可以将生成的代码从 后往前依次存放在一个位串 bits 中。因为各字符的编码长度不同,但不会超过 n,所以,bits 的大小应为 n,并且需要一个整型变量 start 来指示编码在位串 bits[n]中的起始位置,编码的存储结构及其算法。 typedef struct { 编码在位串中的位置 }codetype; 写出哈夫曼编码 {从叶结点出发进行回塑,左子树为-1,右子树为 0 } 将 i+1 个字符的编码存入 code[i] } } ④译码 与编码过程相反, 译码过程是从哈夫曼树的根结点出发,逐个读入电文中的二进 制码, 如读入 0,则走向左孩子,否则走向右孩子,一旦达到叶结点 code[i].ch。 然后,重新从根结点出发继续译码,直到二进制电文结束。
哈夫曼编译码---数据结构C语言版课程设计

《数据结构》课程设计报告%设计题目?学院名称信息工程学院专业班级12 计本 2姓名张翠翠学号17 ______$题目:哈夫曼(Huffman)编/译码器一、问题描述利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。
试为这样的信息收发站写一个哈夫曼码的编/译码系统。
二、设计目标帮助学生熟练掌握树的应用和基本操作,重点掌握二叉树的存储,这里以哈夫曼树为设计目标进一步提高学生的设计能力及对树的理解。
三、任务要求;一个完整的系统应具有以下功能: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中。
四、需求分析~利用哈夫曼树(Huffman)编/译码(一)、初始化哈夫曼树(二)、建立哈夫曼树(三)、对哈夫曼树进行编码(四)、输出对应字符的编码(五)、译码过程五、概要设计哈夫曼树的存储结构描述~typedef struct{unsigned int weight;unsigned int parent, lchild, rchild;}HTNode, *HuffmanTree;哈弗曼树的算法void CreateHT(HTNode ht[],int n)arent=ht[i].lchild=ht[i].rchild=-1; arent==-1) eight<min1) eight;lnode=k;}}else if (ht[k].weight<min2){min2=ht[k].weight;rnode=k;}}}ht[lnode].parent=i;ht[rnode].parent=i;eight=ht[lnode].weight+ht[rnode].weight;child=lnode;ht[i].rchild=rnode; arent;while (f!=-1) child==c) arent;、}++; ata);for (k=hcd[i].start;k<=n;k++) d[k]); }printf("\n");}}#void editHCode(HTNode ht[],HCode hcd[],int n) ata)tart;k<=n;k++){printf("%c",hcd[j].cd[k]);}break; tart,j=0;k<=n;k++,j++)d[k]) ata);for(x=0;code[x-1]!='#';x++) ata=str[i];ht[i].weight=fnum[i];}(while (flag) .");getch();system("cls");break;case 'b':case 'B':system("cls");printf("请输入要进行编码的字符串(以#结束):\n"); &editHCode(ht,hcd,n);printf("\n按任意键返回...");getch();system("cls");break;case 'c':case 'C':system("cls");!DispHCode(ht,hcd,n);printf("请输入编码(以#结束):\n");deHCode(ht,hcd,n);printf("\n按任意键返回...");getch();system("cls");break;case 'd':<case 'D':flag=0;break;default:system("cls");}}}字符(空格A B C D E F G&HI J K L M频度186【64132232103211547—57153220由上表画出哈夫曼树:…由哈夫曼树得出各字符的编码:字符编码字符编码空格10|0001DA010E111111001 B011111%FC0000G01110关系调用:;该程序的流程图:`【开始结点数是否大于1将data 和权值赋给ht输出根结点和权值调用selectmin 函数 计算根结点函数父结点为两子结点之和"是否为根结点左子是否为空此时编码为0i<=2*ni++编码为1结束、否否右子是否为空是是否否|是是七、测试分析白盒:查看代码完整性¥白盒测试也称结构测试或逻辑驱动测试,它是按照程序内部的结构测试程序,通过测试来检测产品内部动作是否按照设计规格说明书的规定正常进行,检验程序中的每条通路是否都能按预定要求正确工作。
数据结构课程设计哈夫曼编码译码器.doc

数据结构课程设计哈夫曼编码译码器.题目一:哈夫曼编码与译码一、任务设计一个利用哈夫曼算法的编码和译码系统,重复地显示并处理以下项目,直到选择退出为止。
要求:1)将权值数据存放在数据文件(文件名为data.txt,位于执行程序的当前目录中) ;2)初始化:键盘输入字符集统计字符权值、自定义26个字符和26个权值、统计文件中一篇英文文章中26个字母,建立哈夫曼树;3)编码:利用建好的哈夫曼树生成哈夫曼编码;4)输出编码(首先实现屏幕输出,然后实现文件输出);5)译码(键盘接收编码进行译码、文件读入编码进行译码);6)界面优化设计。
二、流程图主菜单1.建立字符权值 2.建立并输出哈夫曼树3.建立并查看哈弗曼编码4.编码与译码0.退出系统1.从键盘输入字符集统计权值2.从文件读入字符集统计权值3.自定义字符及权值0.返回上级菜单输出哈夫曼树并保存至文件“哈夫曼树。
txt”输出哈夫曼编码并保存至文件“哈夫曼编码。
txt1.编码2.译码0.返回上级菜单1.从键盘输入字符集进行编码2.从文件读入字符集进行编码1.从键盘输入编码进行译码 2.从文件读入编码进行译码0.返回上级菜单0.返回上级菜单三、代码分解//头文件#include#include#include#include #define N 1000#define M 2*N-1#define MAXcode 6000//函数声明void count(CHar ch,HTNode ht[]);void editHCode(HTNode ht[],HCode hcd[],CHar ch,int n,char bianma[]); //编码函数void printyima(HTNode ht[],HCode hcd[],int n,char bianma[]); //译码函数void creatHT(HTNode ht[],int n);void CreateHCode (HTNode ht[],HCode hcd[],int n);void DispHCode(HTNode ht[],HCode hcd[],int n);void input_key(CHar ch);void input_file(CHar ch);void input_cw(HTNode ht[]);void bianma1(HTNode ht[],HCode hcd[],CHar ch,int n,char bianma[]);void bianma2(HTNode ht[],HCode hcd[],CHar ch,int n,char bianma[]);void yima1(HTNode ht[],HCode hcd[],int n,char bianma[]);void yima2(HTNode ht[],HCode hcd[],int n,char bianma[]);void creat_cw();void bianmacaidan();void yimacaidan();void bianmayima();int caidan(); //结构体typedef struct-省略部分-;}void bianma2(HTNode ht[],HCode hcd[],CHar ch,int n,char bianma[]){ int i; FILE*fp; char filename[20]; printf("请输入要打开的文件名(*.txt):"); scanf("%s",filename); if((fp=fopen(filename,"r"))==NULL) { printf("\n\t\t文件打开失败!!!"); return; } for(i=0;!feof(fp);i++) { fread(ch.s[i],sizeof(char),1,fp); } ch.num=strlen(ch.s); printf("\n读入成功!\n"); printf("文件中的字符集为:\n%s",ch.s); fclose(fp);editHCode(ht,hcd,ch,n,bianma); getch(); system("cls"); return;}//译码函数void yima1(HTNode ht[],HCode hcd[],int n,char bianma[]){ int i; char code[MAXcode]; printf("请输入编码进行译码(以‘#’结束):\n"); for(i=0;i四、调试结果主菜单建立字符权值选择2.从文件读入字符进行统计输入测试文件名“cs.txt”输出个字符权值建立哈夫曼树并输出至文件生成哈夫曼编码并保存至文件编码选择2.从文件读入字符集编码编码结果保存至文件译码选择2.从文件读入编码,读入上一步的编码译码完成,返回!退出系统word教育资料div ;i++) 达到当天最大量API KEY 超过次数限制。
完整word版哈夫曼编码译码器数据结构C语言模板

一、需求分析目前,进行快速远距离通信的主要手段是电报,即将需传送的文字转化成由二级制的字符组成种字符,只需两个字符的串,便可”,它只有4的字符串。
例如,假设需传送的电文为“ABACCDA,00010010101100”则上述和11,7个字符的电文便为“以分辨。
假设A、B、C、D、的编码分别为00,01,10 14位,对方接受时,可按二位一分进行译码。
总长当然,在传送电文时,希望总长尽可能地短。
如果对每个字符设计长度不等的编码,且让电文DC、中出现次数较多的字符采用尽可能短的编码,则传送电文的总长便可减少。
如果设计A、B、。
但是,000011010”,则上述7个字符的电文可转换成总长为9的字符串“的编码分别为0,00,1,01”就可以有很多种译法,0000个字符的字串“这样的电文无法翻译,例如传送过去的字符串中前4”等。
因此,若要设计长短不等的编码,则必须是任一字ABAAAAA”或者“BB”,或者“或是“符的编码都不是另一个字符的编码的前缀,这种编码称作前缀编码。
然而,如何进行前缀编码就是利用哈夫曼树来做,也就有了现在的哈夫曼编码和译码。
二、概要设计译码利用哈夫曼树编/ 、建立哈夫曼树(一)、对哈夫曼树进行编码(二)、输出对应字符的编码(三)、译码过程(四)主要代码实现://结构体的定义struct code{char a;int w;int parent;int lchild;int rchild;};void creation(code *p,int n,int m); //建立哈夫曼树//编码void coding(code *p,int n);//输出函数void display(code *p,int n,int m);//译码void translate(char **hc,code *p,int n);详细设计三、(一)、建立哈夫曼树10序号:5 3 4 2 7 6 1* * *c *字符:db a 4 6 6 权值:10 6 4 2 3 3 1 d **33333 c*c * * 1 2 2 1 2 1 abb a 3-3图3-1 图b a 3-2 图1(二)、对哈夫曼树进行编码主要代码实现:从叶子到根逆向求编码for(c=i,f=p[i].parent;f!=0;c=f,f=p[f].parent){*'0'//左孩子编码为if(p[f].lchild==c) 1 { d* cd[--start]='0'; 0 1} c* 1 0 '1'else //右孩子编码为{ bacd[--start]='1';3-4图}}(三)、输出对应字符的码编码字符110 a111 b10 c3-1表d(四)、译码过程主要代码实现:0 比较两个字符串是否相等,相等则输出if(strcmp(a,hc[i])==0) //{或'1'确定找左孩子或右孩子//从根出发,按字符'0' for(c=2*n-1,j=0;a[j]!='\0';j++){if(a[j]=='0') //左孩子从跟到叶子顺向求字符{*c=p[c].lchild;1 0}d * else 1 0{c *右孩子c=p[c].rchild; // 1 0}ba }3-5 图2调试分析四、、数字的输入判断(一)4-1 图、字母的输入判断(二)4-2 图(三)、程序是否继续进行的判断4-3 图用户手册五、;提示输(一)、首先根据提示输入初始化数据,提示输入一个数字,请输入一个数a,0<a<9999中的一个字符;请勿在输入一个数字后再输入一个入一个字母,则请输入一个字母(a~z)或者(A~Z) 字符,或者在输入一个字符后再输入一个数字。
数据结构课程设计赫夫曼编译码器C

赫夫曼编\译码器摘要本次课程设计过程中我主要根据课本中的实现思想及算法编写程序,体现以课本知识的应用为主,在学习了线性表、栈、队列、二叉树、树和图等结构的基础上,以能够更加熟练的应用所学知识,并能结合一些著名算法来实现对一些实际问题的应用,例如,赫夫曼树等,从而更为深刻理解数据结构的内涵,熟悉它们各自的应用场合及方法。
有些在平时课程中并没有掌握的内容在这次课程设计中都是先通过看课本学懂了,然后再在课程设计中加深印象,实现算法的应用和扩展。
这次课程设计的设计内容主要是通过实际的例子和程序来实现课本中所学习的算法的应用。
程序设计设计语言采用C++,程序运行平台为Windows XP。
赫夫曼编\译码器的主要功能是先建立赫夫曼树,然后利用建好的赫夫曼树生成哈夫曼编码后进行译码。
赫夫曼编译系统分为五个功能模块:原始数据载入,打印编码规则、编码、译码。
以二叉树的应用为基础,包括统计信息,并通过构建赫夫曼树、对信息进行赫夫曼编码,将编码信息等存入文档。
关键字数据结构栈和队列赫夫曼树赫夫曼编码目录1引言 (1)1.1课程设计目的 (1)1.2课程设计背景 (1)1.3课程设计主要内容 (1)2需求分析 (3)3 概要设计 (4)3.1 设计思想 (4)3.2 函数间的关系 (4)3.3数据结构与算法设计 (4)4详细设计 (6)4.1 赫夫曼的主要结构 (6)5 调试分析 (8)6 测试并列出测试结果 (9)6.1 测试方式 (9)6.2 测试结果 (9)7 总结 (13)致谢 (14)参考文献 (14)附录 (15)1 引言当今社会,计算机技术和通信技术已不断发展,处理和传输的数据量越来越庞大。
如何采用有效的数据压缩技术引起了人们的极大重视。
从而产生了哈夫曼编码,它是一种应用广泛且非常有效的数据压缩技术,该技术一般可将数据压缩20%至90%,通常我们将压缩技术称为编码,解压缩过程称为解码。
树状结构简称为树,是一种以分支关系进行定义的层次结构,是十分重要的非线性数据结构,在计算机软件设计方面,有着广泛的应用。
哈夫曼编码译码器数据结构C语言

哈夫曼编码译码器数据结构C语言哈夫曼编码译码器数据结构C语言⒈简介本文档旨在介绍一个使用C语言实现的哈夫曼编码译码器的数据结构。
哈夫曼编码是一种用于数据压缩的算法,它通过将频率较高的字符用较短的编码表示,从而实现数据的压缩和解压缩。
⒉哈夫曼编码(Huffman Coding)基本概念⑴字符频率统计在进行哈夫曼编码之前,我们首先需要统计每个字符在待编码的数据中出现的频率。
通过遍历数据,记录每个字符的出现次数,我们可以得到一个字符频率的统计表。
⑵构建哈夫曼树通过字符频率的统计表,我们可以构建一个哈夫曼树。
哈夫曼树是一种二叉树,其中每个叶节点表示一个字符,而每个内部节点表示一个权重,即两个子节点的频率之和。
⑶哈夫曼编码在哈夫曼树构建完成后,我们可以根据树的结构每个字符的编码。
哈夫曼编码的特点是没有任何一个字符的编码是另一个字符编码的前缀,这种编码方式称为前缀编码。
⑷哈夫曼译码根据字符的哈夫曼编码,我们可以将编码后的数据进行解码,还原为原始的数据。
通过遍历哈夫曼树,从根节点开始,根据每个二进制位的取值进行向左或向右的移动,直至叶节点,然后获取该叶节点对应的字符。
⒊数据结构设计⑴结点结构定义一个哈夫曼树的结点结构,包含以下字段:●`char data`:字符●`int frequency`:字符的频率●`int is_leaf`:是否为叶节点●`struct Node left_child`:左子节点●`struct Node right_child`:右子节点⑵频率统计表使用一个数组或链表来记录每个字符的频率统计信息,包含以下字段:●`char data`:字符●`int frequency`:字符的频率⑶编码表使用一个数组或链表来记录每个字符的哈夫曼编码,包含以下字段:●`char data`:字符●`char code`:编码⒋算法流程⑴字符频率统计算法步骤:⒈初始化频率统计表为空。
⒉读取待编码的数据。
数据结构课程设计哈夫曼编码译码器

西安郵電學院数据结构课程设计报告题目1:哈夫曼编码/译码器题目2:学生信息管理系统系部名称:通信工程系专业名称:通信工程班级:****学号:*****学生姓名:****指导教师:*****时间:2009年12月16日至2009年12月25日题目1.哈夫曼编码/译码器一、课程设计目的通过对哈夫曼编码/译码器的实现,熟悉了解Huffman树的创建过程以及存储结构,对Huffman编码/译码过程及原则有了更深层次的认识,锻炼了动手能力,使知识更好的学以致用,为解决数据压缩问题提供方法。
二、课程设计内容通过统计文件中各字符的出现频率,建立Huffman树,再通过建立的已经Huffman的树,对文件中各字符进行编码,将结果存入新的文件中,然后从文件中读取Huffman编码,进行解码,结果存入新的文件中,并与源文件进行比较。
三、需求分析1.统计字符频率:存文件中读入字符,并对各字符出现频率进行统计;2.建立Huffman树:将各字符出现的频率作为权值,建立Huffman树;3.Huffman编码:通过已经建立的Huffman树,对个各字符进行编码,并存入新的文件中;4.译码:读取存放Huffman编码的文件,对文件中编码进行译码,把译码结果存入新的文件中;5.结果验证:将译码结果与原文件内容进行比较;四、概要设计1. 系统结构图(功能模块图)2.功能模块说明1:统计字符频率:定义结构体typedef struct str{char data;char num;}str;其中data域存放字符名称,num域存放字符出现频率,读取文件ywq1.txt,通过循环比较将结果赋入S2[128]中;2:创建Huffman树: 定义结构体typedef struct{char data;int weight;int parent;int lchild;int rchild;}HTNode,HuffmanTree[M+1];作为Huffman树存储节点类型,调用CrtHuffmanTree()函数,初始化各节点均为 0;然后将存储字符频率的数组S2的值赋值给各节点,字符出现频率作为权值,创建Huffman树;3:对文件编码:定义结构体typedef struct{char data;char bits[N+1];}CodeNode,HuffmanCode[N];作为HuffmanCode的存储类型,调用CrtHuffmanCode()函数,从叶子节点向上回溯,是lchild则赋值‘0’,是rchild则赋值为‘1’,对各字符编码,再调用WriteToFile()函数,将结果写入文件ywq2.txt中;4:对文件译码:读取编码文件ywq2.txt中数据,调用DecodHuffmanCode()函数,从根节点开始,读取‘1’,走向rchild,读取‘0’, 走向lchild,直到叶子节点,将叶子节点data域的值写入文件ywq3.txt中;五、详细设计及运行结果1.读文件统计字符频率(read()函数中实现):打开源文件ywq1.txt读文件内的字符,初始化数组s1文件是否结束将字符存入数组S1[ch].num++读下一个字符给数组末尾加上结束标志“\0”关闭文件是否开始结束源文件ywq1.txt:运行结果:2:创建Huffman树,CrtHuffmanTree():运行结果:初始化结构体数组htCrtHuffmanTree()有n棵二叉树n > 1选权值最小2个二叉树权值相加得新二叉树n - 1n = 1建立Huffman树结束3:Huffman 编码,CrtHuffmanCode();运行结果:编码文件ywq2.txt :CrtHuffmanCode()根cd[--start] = ‘0’ cd[--start] = ‘1’否LchildRchildcd[start] 赋给hc[i].bits是结束对应字符编码写入文件ywq2.txt3:译码,DecodHuffmanCode():运行结果:DecodHuffmanCode()打开文件ywq2.txt读取字符ch文件结束否否找根节点ch = ‘0’, 找lchild;ch = ‘1’, 找rchild;叶子节点是是保存ywq3.txt是结束文件ywq3.txt:4:结果验证:比较源文件ywq1.txt 与译码文件ywq3.txt 可知,译码结果与源文件一致。
哈夫曼编_译码器数据结构课程设计报告

摘要哈夫曼编码是根据字符的使用率的高低对字符进行不等长的编码,从而使使用率高的字符占用较少的空间,从而在传输的过程中大大提高了数据的空间传输效率。
本设计采用二叉链表的存储结构,建立哈夫曼树;用递归调用的方式对哈夫曼树的节点进行编码,生成与字符对应的哈夫曼编码。
本设计完全采用C++语言进行编程,并在XCode 6编译器上调试运行通过。
本程序使用中文界面,并有相应的提示信息,便于操作和程序运行。
关键词:哈夫曼树;哈夫曼编码;递归调用;二叉链表AbstractHuffman coding is based on the level of usage of characters ranging from long coding, so that high usage rate of the characters occupy less storage space , in the course of transmission has greatly enhanced the efficiency of data transmission space. This design build the Huffman tree by using Binary Tree storage structure, encoded Huffman tree nodes by recursive calling, and the characters generate the corresponding Huffman coding. The procedure completely write with C++ language and has Chinese explanatory note. What’s more, i t was debugged in XCode 6 debugger and run well. The whole procedure, with Chinese interface and the corresponding tips ,is convenient to run and easy to be operated.Keywords: Huffman Tree; Huffman code; Recursive call; Binary List目录摘要 0ABSTRACT (1)一、问题描述(内容格式参考下面的描述,以下类似) (3)1、问题描述: (3)2、基本要求: (3)二、需求分析 (3)2.1设计目标 (3)2.2设计思想 (3)三、概要设计 (4)3.1程序结构 (4)3.2初始化算法: (4)3.3编码算法: (4)3.4译码算法: (4)四、数据结构设计 (4)五、算法设计 (5)1、算法分析(必须要用语言进行描述) (5)2、算法实现 (6)六、程序测试与实现 (11)1、主程序 (11)2、测试数据 (12)3、测试结果 (14)生成哈夫曼树运行结果图: (14)哈夫曼编码运行结果图: (15)编码函数运行结果图: (15)译码函数运行结果图: (15)平均编码长度函数运行结果图: (15)七、调试分析 (15)程序调试的步骤: (15)调试体会: (16)八、遇到的问题及解决办法 (16)九、心得体会 (16)一、问题描述(内容格式参考下面的描述,以下类似)1、问题描述:利用哈夫曼编码进行信息通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
所有的胜利,与征服自己的胜利比起来,都是微不足道。
《数据结构》课程设计报告设计题目哈夫曼 (Huffman) 编/译码器学院名称信息工程学院专业班级 12 计本 2 姓名张翠翠学号 1212210217 ______题目:哈夫曼(Huffman)编/译码器一、问题描述利用哈夫曼编码进行通信可以大大提高信道利用率缩短信息传输时间降低传输成本但是这要求在发送端通过一个编码系统对待传数据预先编码在接收端将传来的数据进行译码(复原)对于双工信道(即可以双向传输信息的信道)每端都需要一个完整的编/译码系统试为这样的信息收发站写一个哈夫曼码的编/译码系统二、设计目标帮助学生熟练掌握树的应用和基本操作重点掌握二叉树的存储这里以哈夫曼树为设计目标进一步提高学生的设计能力及对树的理解三、任务要求一个完整的系统应具有以下功能: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中四、需求分析利用哈夫曼树(Huffman)编/译码(一)、初始化哈夫曼树(二)、建立哈夫曼树(三)、对哈夫曼树进行编码(四)、输出对应字符的编码(五)、译码过程五、概要设计哈夫曼树的存储结构描述typedef struct{unsigned int weight;unsigned int parentlchildrchild;}HTNode*HuffmanTree;哈弗曼树的算法void CreateHT(HTNode ht[]int n) //调用输入的数组ht[]和节点数n{int iklnodernode;int min1min2;for (i=0;i<2*n-1;i++)ht[i].parent=ht[i].lchild=ht[i].rchild=-1; //所有结点的相关域置初值-1 for (i=n;i<2*n-1;i++) //构造哈夫曼树{min1=min2=32767; //int的范围是-32768-32767lnode=rnode=-1; //lnode和rnode记录最小权值的两个结点位置for (k=0;k<=i-1;k++){if (ht[k].parent==-1) //只在尚未构造二叉树的结点中查找{if (ht[k].weight<min1) //若权值小于最小的左节点的权值{min2=min1;rnode=lnode;min1=ht[k].weight;lnode=k;}else if (ht[k].weight<min2){min2=ht[k].weight;rnode=k;}}}ht[lnode].parent=i;ht[rnode].parent=i; //两个最小节点的父节点是iht[i].weight=ht[lnode].weight+ht[rnode].weight; //两个最小节点的父节点权值为两个最小节点权值之和ht[i].lchild=lnode;ht[i].rchild=rnode; //父节点的左节点和右节点}}哈弗曼编码void CreateHCode(HTNode ht[]HCode hcd[]int n){int ifc;HCode hc;for (i=0;i<n;i++) //根据哈夫曼树求哈夫曼编码{hc.start=n;c=i;f=ht[i].parent;while (f!=-1) //循序直到树根结点结束循环{if (ht[f].lchild==c) //处理左孩子结点hc.cd[hc.start--]='0';else //处理右孩子结点hc.cd[hc.start--]='1';c=f;f=ht[f].parent;}hc.start++; //start指向哈夫曼编码hc.cd[]中最开始字符hcd[i]=hc;}}void DispHCode(HTNode ht[]HCode hcd[]int n) //输出哈夫曼编码的列表{int ik;printf(" 输出哈夫曼编码:\n");for (i=0;i<n;i++) //输出data中的所有数据即A-Z{printf(" %c:\t"ht[i].data);for (k=hcd[i].start;k<=n;k++) //输出所有data中数据的编码 {printf("%c"hcd[i].cd[k]);}printf("\n");}}void editHCode(HTNode ht[]HCode hcd[]int n) //编码函数{char string[MAXSIZE];int ijk;scanf("%s"string); //把要进行编码的字符串存入string数组中printf("\n输出编码结果:\n");for (i=0;string[i]!='#';i++) //#为终止标志{for (j=0;j<n;j++){if(string[i]==ht[j].data) //循环查找与输入字符相同的编号相同的就输出这个字符的编码{for (k=hcd[j].start;k<=n;k++){printf("%c"hcd[j].cd[k]);}break; //输出完成后跳出当前for循环}}}}哈弗曼译码void deHCode(HTNode ht[]HCode hcd[]int n) //译码函数{char code[MAXSIZE];int ijlkmx;scanf("%s"code); //把要进行译码的字符串存入code数组中while(code[0]!='#')for (i=0;i<n;i++){m=0; //m为想同编码个数的计数器for (k=hcd[i].startj=0;k<=n;k++j++) //j为记录所存储这个字符的编码个数{if(code[j]==hcd[i].cd[k]) //当有相同编码时m值加1m++;}if(m==j) //当输入的字符串与所存储的编码字符串个数相等时则输出这个的data数据{printf("%c"ht[i].data);for(x=0;code[x-1]!='#';x++) //把已经使用过的code数组里的字符串删除{code[x]=code[x+j];}}}}主函数void main(){int n=26i;char orzbackflag=1;char str[]={'A''B''C''D''E''F''G''H''I''J''K''L''M''N''O''P''Q''R''S''T''U''V''W''X''Y''Z'}; //初始化int fnum[]={1866413223210321154757123220576315148518023818116}; //初始化HTNode ht[M]; //建立结构体HCode hcd[N]; //建立结构体for (i=0;i<n;i++) //把初始化的数据存入ht结构体中 {ht[i].data=str[i];ht[i].weight=fnum[i];}while (flag) //菜单函数当flag为0时跳出循环显示部分源程序:{printf("\n");printf(" ********************************");printf("\n ** 1---------------显示编码 **");printf("\n ** 2---------------进行编码 **");printf("\n ** 3---------------进行译码 **");printf("\n ** 4---------------退出 **\n");printf(" * **********************************");printf("\n");printf(" 请输入选择的编号:");scanf("%c"&orz);switch(orz){case 'a':case 'A':system("cls"); //清屏函数 CreateHT(htn);CreateHCode(hthcdn);DispHCode(hthcdn);printf("\n按任意键返回...");getch();system("cls");break;case 'b':case 'B':system("cls");printf("请输入要进行编码的字符串(以#结束):\n"); editHCode(hthcdn);printf("\n按任意键返回...");getch();system("cls");break;case 'c':case 'C':system("cls");DispHCode(hthcdn);printf("请输入编码(以#结束):\n");deHCode(hthcdn);printf("\n按任意键返回...");getch();system("cls");break;case 'd':case 'D':flag=0;break;default:system("cls");}}}六、详细设计字符空格ABCDEFGHIJKLM频度1866413223210321154757153220由上表画出哈夫曼树:由哈夫曼树得出各字符的编码:字符编码字符编码空格10D0001A010E1111B011111F11001C0000G01110关系调用:该程序的流程图:七、测试分析白盒:查看代码完整性白盒测试也称结构测试或逻辑驱动测试它是按照程序内部的结构测试程序通过测试来检测产品内部动作是否按照设计规格说明书的规定正常进行检验程序中的每条通路是否都能按预定要求正确工作这一方法是把测试对象看作一个打开的盒子测试人员依据程序内部逻辑结构相关信息设计或选择测试用例对程序所有逻辑路径进行测试通过在不同点检查程序的状态确定实际的状态是否与预期的状态一致黑盒:测试是否可以正确的创建删除插入打印查找等操作黑盒测试也称功能测试它是通过测试来检测每个功能是否都能正常使用在测试中把程序看作一个不能打开的黑盒子在完全不考虑程序内部结构和内部特性的情况下在程序接口进行测试它只检查程序功能是否按照需求规格说明书的规定正常使用程序是否能适当地接收输入数据而产生正确的输出信息黑盒测试着眼于程序外部结构不考虑内部逻辑结构主要针对软件界面和软件功能进行测试八、使用说明1) 输入n个字符的权值2) 输入对应的字符3) 得出各字符的编码九、测试数据用下表给出的字符集和频度的实际统计数据建立哈夫曼树并实现以下报文的编码和译码:"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注:学生在测试数据时需要写出测试用例和截图十、该程序的源代码#include <stdio.h>#include <stdlib.h> //要用system函数要调用的头文件#include<conio.h> //用getch()要调用的头文件#include <string.h>#define N 50 //义用N表示50叶节点数#define M 2*N-1 //用M表示节点总数当叶节点数位n时总节点数为2n-1 #define MAXSIZE 100typedef struct{char data; //结点值int weight; //权值int parent; //双亲结点int lchild; //左孩子结点int rchild; //右孩子结点}HTNode;typedef struct{char cd[N]; //存放哈夫曼码int start; //从start开始读cd中的哈夫曼码}HCode;void CreateHT(HTNode ht[]int n) //调用输入的数组ht[]和节点数n{int iklnodernode;int min1min2;for (i=0;i<2*n-1;i++)ht[i].parent=ht[i].lchild=ht[i].rchild=-1; //所有结点的相关域置初值-1 for (i=n;i<2*n-1;i++) //构造哈夫曼树{min1=min2=32767; //int的范围是-32768-32767lnode=rnode=-1; //lnode和rnode记录最小权值的两个结点位置for (k=0;k<=i-1;k++){if (ht[k].parent==-1) //只在尚未构造二叉树的结点中查找{if (ht[k].weight<min1) //若权值小于最小的左节点的权值{min2=min1;rnode=lnode;min1=ht[k].weight;lnode=k;}else if (ht[k].weight<min2){min2=ht[k].weight;rnode=k;}}}ht[lnode].parent=i;ht[rnode].parent=i; //两个最小节点的父节点是iht[i].weight=ht[lnode].weight+ht[rnode].weight; //两个最小节点的父节点权值为两个最小节点权值之和ht[i].lchild=lnode;ht[i].rchild=rnode; //父节点的左节点和右节点}}void CreateHCode(HTNode ht[]HCode hcd[]int n){int ifc;HCode hc;for (i=0;i<n;i++) //根据哈夫曼树求哈夫曼编码{hc.start=n;c=i;f=ht[i].parent;while (f!=-1) //循序直到树根结点结束循环{if (ht[f].lchild==c) //处理左孩子结点hc.cd[hc.start--]='0';else //处理右孩子结点hc.cd[hc.start--]='1';c=f;f=ht[f].parent;}hc.start++; //start指向哈夫曼编码hc.cd[]中最开始字符hcd[i]=hc;}}void DispHCode(HTNode ht[]HCode hcd[]int n) //输出哈夫曼编码的列表{int ik;printf(" 输出哈夫曼编码:\n");for (i=0;i<n;i++) //输出data中的所有数据即A-Z{printf(" %c:\t"ht[i].data);for (k=hcd[i].start;k<=n;k++) //输出所有data中数据的编码 {printf("%c"hcd[i].cd[k]);}printf("\n");}}void editHCode(HTNode ht[]HCode hcd[]int n) //编码函数{char string[MAXSIZE];int ijk;scanf("%s"string); //把要进行编码的字符串存入string数组中printf("\n输出编码结果:\n");for (i=0;string[i]!='#';i++) //#为终止标志{for (j=0;j<n;j++){if(string[i]==ht[j].data) //循环查找与输入字符相同的编号相同的就输出这个字符的编码{for (k=hcd[j].start;k<=n;k++){printf("%c"hcd[j].cd[k]);}break; //输出完成后跳出当前for循环}}}}void deHCode(HTNode ht[]HCode hcd[]int n) //译码函数{char code[MAXSIZE];int ijlkmx;scanf("%s"code); //把要进行译码的字符串存入code数组中while(code[0]!='#')for (i=0;i<n;i++){m=0; //m为想同编码个数的计数器for (k=hcd[i].startj=0;k<=n;k++j++) //j为记录所存储这个字符的编码个数{if(code[j]==hcd[i].cd[k]) //当有相同编码时m值加1m++;}if(m==j) //当输入的字符串与所存储的编码字符串个数相等时则输出这个的data数据{printf("%c"ht[i].data);for(x=0;code[x-1]!='#';x++) //把已经使用过的code数组里的字符串删除{code[x]=code[x+j];}}}}void main(){int n=26i;char orzbackflag=1;char str[]={'A''B''C''D''E''F''G''H''I''J''K''L''M''N''O''P''Q''R''S''T''U''V''W''X''Y''Z'}; //初始化int fnum[]={1866413223210321154757123220576315148518023818116}; //初始化HTNode ht[M]; //建立结构体HCode hcd[N]; //建立结构体for (i=0;i<n;i++) //把初始化的数据存入ht结构体中 {ht[i].data=str[i];ht[i].weight=fnum[i];}while (flag) //菜单函数当flag为0时跳出循环{printf("\n");printf(" **************************************");printf("\n ** A---------------显示编码 **");printf("\n ** B---------------进行编码 **");printf("\n ** C---------------进行译码 **");printf("\n ** D---------------退出 **\n");printf(" ****************************************");printf("\n");printf(" 请输入选择的编号:");scanf("%c"&orz);switch(orz){case 'a':case 'A':system("cls"); //清屏函数 CreateHT(htn);CreateHCode(hthcdn);DispHCode(hthcdn);printf("\n按任意键返回...");getch();system("cls");break;case 'b':case 'B':system("cls");printf("请输入要进行编码的字符串(以#结束):\n");editHCode(hthcdn);printf("\n按任意键返回...");getch();system("cls");break;case 'c':case 'C':system("cls");DispHCode(hthcdn);printf("请输入编码(以#结束):\n");deHCode(hthcdn);printf("\n按任意键返回...");getch();system("cls");break;case 'd':case 'D':flag=0;break;default:system("cls");}}}:该程序的截图:初始化界面截图如下选A时的显示结果截图如下选择B时的显示结果截图如下选C时的显示结果截图如下十一、使用说明(给出软件如何使用使用时的注意事项)VC++6.0编程环境使用1、 VC++6.0程序启动2、新建工程Project3、设定工程Project名称、保存位置4、设定工程Project的类型5、工程Project的描述信息生成6、空工程Project建立完毕7)向工程Project中添加(新建)源代码文件的类型、名称、保存位置8、设定源代码文件的类型、名称9、源代码文件被添加到工程中10、在源代码文件中添加程序代码11、程序代码编译完成后编译、链接过程注意事项:(1)一个工程project中可以有多个源文件(.cpp)、多个头文件(.h);但这些源代码文件中只能出现一个main函数作为整个程序运行的入口;(2)必须关闭前一次程序运行结果窗口才能进行下一次程序运行;(3)书写标识符时忽略了大小写字母的区别(4 ) 忘记加分号(5)多加分号十二、课程设计总结本次课程设计的题目是:哈夫曼(Huffman)编/译码器通过这次课程设计我了解到自己在编写程序方面还有很多不足在实践过程中老师给了我很大的帮助在这次课程设计中虽然不会成功的编写一个完整的程序但是在看程序的过程中不断的上网查资料以及翻阅相关书籍通过不断的模索测试发现问题解决问题和在老师的帮助下一步一步慢慢的正确运行程序终于完成了这次课程设计虽然这次课程设计结束了但是总觉得自已懂得的知识很是不足学无止境以后还会更加的努力深入的学习????????1。