【精品】数据结构课程设计:电文编码译码(哈夫曼编码)

合集下载

数据结构课程设计哈夫曼

数据结构课程设计哈夫曼

数据结构课程设计哈夫曼一、课程目标知识目标:1. 理解哈夫曼编码的基本原理和构建方法;2. 掌握哈夫曼树的结构特点及其应用;3. 学会运用哈夫曼编码进行数据压缩,并了解其优缺点。

技能目标:1. 能够运用所学知识构建哈夫曼树并进行编码;2. 能够分析给定数据集的最优哈夫曼编码方案;3. 能够运用哈夫曼编码解决实际问题,如文件压缩与解压。

情感态度价值观目标:1. 培养学生对数据结构在计算机科学中重要性的认识,激发对数据结构学习的兴趣;2. 培养学生的团队合作意识,学会在团队中发挥个人优势,共同解决问题;3. 培养学生严谨、细致的学术态度,养成良好的编程习惯。

课程性质分析:本课程为高中信息技术学科的数据结构部分,旨在让学生了解并掌握常用的数据结构及其应用。

哈夫曼编码作为数据结构中的一种重要应用,具有很高的实用价值。

学生特点分析:高中学生已经具备了一定的逻辑思维能力,能够理解抽象的概念,但实践经验不足,需要通过具体的案例和动手操作来加深理解。

教学要求:1. 理论与实践相结合,注重培养学生的动手能力;2. 以学生为主体,鼓励学生主动探究、合作学习;3. 注重培养学生的创新能力和解决问题的能力。

二、教学内容1. 引入:回顾树的基本概念,为新课哈夫曼树做好知识铺垫。

教材章节:第二章 树与二叉树2. 哈夫曼编码原理:- 哈夫曼编码的基本思想与原理- 哈夫曼树的构建过程教材章节:第二章 树与二叉树,第五节 哈夫曼编码3. 哈夫曼树的构建方法:- 构建哈夫曼树的步骤- 哈夫曼编码的生成方法教材章节:第二章 树与二叉树,第五节 哈夫曼编码4. 哈夫曼编码的应用:- 文件压缩与解压的原理- 哈夫曼编码在数据压缩中的应用案例教材章节:第二章 树与二叉树,第五节 哈夫曼编码及应用5. 实践操作:- 动手编写程序构建哈夫曼树并进行编码- 分析实际数据集,设计最优哈夫曼编码方案教材章节:第二章 树与二叉树,第五节 哈夫曼编码实践6. 总结与拓展:- 总结哈夫曼编码的特点及其在数据压缩中的应用优势- 探讨哈夫曼编码在其他领域的拓展应用教材章节:第二章 树与二叉树,第五节 哈夫曼编码拓展与应用教学内容安排与进度:1. 引言与回顾:1课时2. 哈夫曼编码原理与构建方法:2课时3. 哈夫曼编码应用与实践操作:2课时4. 总结与拓展:1课时总计:6课时三、教学方法1. 讲授法:- 在讲解哈夫曼编码的基本原理、构建方法及应用场景时,采用讲授法进行知识传授,使学生在短时间内掌握关键概念和理论。

数据结构与算法――电文的编码和译码

数据结构与算法――电文的编码和译码

数据结构与算法――电文的编码和译码电文的编码和译码在信息传输中起着重要的作用。

在传统的通信方式中,电文的编码和译码主要通过人工来完成,但是随着科技的发展,自动编码和译码系统也逐渐应用到各个领域中。

本文将介绍电文的编码和译码的常用算法和数据结构。

1.ASCII编码ASCII(American Standard Code for Information Interchange)编码是一种常用的字符编码方案,其中规定了128个常用字符的编码方式。

在ASCII编码中,每个字符用一个8位的二进制数表示,所以可以表示的字符范围是0-127、比如字符“A”的ASCII编码是65,字符“a”的ASCII编码是97、ASCII编码采用定长编码方式,编码的长度总是8位。

ASCII编码的优点是简单明了,但是只适用于表示英文字符。

2. Huffman编码Huffman编码是一种可变长度编码方式。

它根据字符出现的频率来进行编码,出现频率高的字符编码短,出现频率低的字符编码长。

Huffman编码的原理是通过构建Huffman树来实现的。

首先统计字符出现的频率,然后根据频率构建Huffman树,最后根据Huffman树生成字符的编码。

Huffman编码的长度不固定,根据字符的出现频率进行变长编码,可以更高效地利用存储空间。

Huffman编码广泛应用于无损压缩算法中。

3.LZW编码LZW(Lempel-Ziv-Welch)编码是一种基于字典的压缩算法,它通过将输入的字符序列映射为更短的编码来实现压缩。

LZW编码的原理是建立一个字典,在字典中存储常用的字符序列和对应的编码。

开始时,字典只包含单个字符;然后,从输入的字符序列中读取字符,查找是否存在字典中;如果存在,继续读取下一个字符并拼接到当前编码后面,然后继续查找;如果不存在,将当前编码输出,并将当前字符作为新的编码插入字典中。

LZW编码可以根据输入的字符序列动态生成字典,可以适用于任意类型的数据。

数据结构课程设计:电文编码译码(哈夫曼编码)

数据结构课程设计:电文编码译码(哈夫曼编码)

xx农林大学计算机与信息学院数据结构课程设计设计:xx编译码器姓名:xx专业:2013级计算机科学与技术学号:班级:完成日期:2013.12.28xx编译码器一、需求分析在当今信息爆炸时代,如何采用有效的数据压缩技术节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视,哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。

哈夫曼编码是一种编码方式,以哈夫曼树—即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。

哈夫曼编码使用一张特殊的编码表将源字符(例如某文件中的一个符号)进行编码。

这张编码表的特殊之处在于,它是根据每一个源字符出现的估算概率而建立起来的(出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的)。

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

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

哈夫曼译码输入字符串可以把它编译成二进制代码,输入二进制代码时可以编译成字符串。

二、设计要求对输入的一串电文字符实现哈夫曼编码,再对哈夫曼编码生成的代码串进行译码,输出电文字符串。

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

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

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

假设每种字符在电文中出现的次数为Wi,编码长度为Li,电文中有n种字符,则电文编码总长度为∑WiLi。

若将此对应到二叉树上,Wi为叶结点的权,Li为根结点到叶结点的路径长度。

那么,∑WiLi恰好为二叉树上带权路径长度。

因此,设计电文总长最短的二进制前缀编码,就是以n种字符出现的频率作权,构造一棵哈夫曼树,此构造过程称为哈夫曼编码。

数据结构课程设计总结报告 哈夫曼编码译码

数据结构课程设计总结报告 哈夫曼编码译码

《数据结构》课程设计实验报告题目哈夫曼编码/译码器学院数理与信息学院专业计算机科学与技术班级计科132学生姓名刘海澍 5周弘杰8徐铭瑶 3指导教师编写日期数据结构课程设计目录1 问题描述.................................................................错误!未定义书签。

2 问题分析.................................................................错误!未定义书签。

3 算法设计 (2)3.1抽象数据类型定义 (2)3.2模块划分 (3)4 详细设计 (4)4.1数据类型的定义 (4)4.2主要模块的算法描述 (4)4.3 流程图 (6)5 测试分析 (9)6 课程设计总结 (10)7 成员分工 (10)参考文献 (11)附录(源程序清单) (12)1.问题描述设计一个利用哈夫曼算法的编码和译码系统,重复地显示并处理以下项目,直到选择退出为止。

1) 初始化:键盘输入字符集大小n、n个字符和n个权值,建立哈夫曼树;2) 编码:利用建好的哈夫曼树生成哈夫曼编码;3) 输出编码;4)显示哈夫曼树;5)界面设计的优化;6) 设字符集及频度如下表:字符空格 A B C D E F频度4 9 23 2 17 15字符G H I J K频度1 2 3 3 42.问题分析(1)定义一个变量名为HTNode的结构体,用该结构体中的char data、int weight、int parent、int lchild、int rchild分别表示哈夫曼树中每个结点的权值、权重、双亲结点、左孩子、右孩子,再定义一个HTNode类型的数组ht[60]存放哈夫曼树;另外定义一个变量名为HCode的结构体,采用HCode类型变量的cd[start]~cd[n]存放当前结点的哈夫曼编码、最后定义一个HCode类型的数组hcd[30]的数组用于存放当前叶子结点ht[i]的哈夫曼编码。

数据结构 课程设计之哈夫曼编码

数据结构  课程设计之哈夫曼编码

(一) 哈夫曼树的设计思想对于一组具有确定权值的叶子结点可以构造出多个具有不同带权路径长度的二叉树,其中具有最小带权路径长度的二叉树称作哈夫曼树或者最优二叉树。

首先给定n 个权值创造n 个只含根结点的二叉树,得到一个二叉树林;再在这二叉树林里面找根结点的权值最小和次小的两棵树作成新的二叉树,其中新的二叉树的根结点的权值为摆布子根结点权值之和;最后在二叉树林中把组合过的二叉树删除,再重复第二步,直到最后就剩一颗二叉树的时候得到的这棵二叉树就是哈夫曼树。

(二)哈夫曼编码与解码的设计思想在数据通讯中,时常要将传送的文字转换为二进制字符0 和1 组成的二进制串,称这个过程为编码。

与子相对的是解码或者是译码,就是用与编码相同的方式将二进制串转换称编码前的文字的过程称作解码。

在这里是通过哈夫曼树实现编码与解码的,所以称作是哈夫曼编码与解码。

首先输入一个字符串,还有相应的在哈夫曼树里的权值,这样用哈夫曼树把字符串用二进制串代替它,这个过程要注意树和编码问题,其中树的问题在上面已经解决,主要看编码的问题,就是根据我们输入的字符串和权值建立相应的树模型,这一步完成那编码就已经完成为了,最后打印就行了;然后就是解码,完成编码相应的解码就相对简单了,就是先找到在编码的时候建的那个模型树,将编码中的二进制串再根据权值转换为相应的字符串,这样一步步解码就行了。

以上就是通过用哈夫曼树进行哈夫曼编码与解码如何实现的主要设计思想。

(一)哈夫曼树的流程图不 是图 1 哈夫曼树的流程图(二)编码与解码的流程图图 2 编码与解码的流程图图片说明: (左边)编码流程图, (右边)解码流程图。

开始输入字符串判断权值 建立路径有最小和次小 循环建立二叉树根据树对路径分左 0右 1写出对应结点的编码结束开始初始化哈夫曼链表二叉树林找最小和次小 的二叉树组合成新的二叉树 删除用过的二叉树是不是最后一 个二叉树是结束开始找到树的根结点 输入二进制串扫描根据树的路径打印对应字符继续扫描 是否结束是输出字符串结束否下面给出的是用中缀转后缀算法实现的程序的源代码:#include "stdio.h"#include "string.h"#define MAX 100struct HaffNode{int weight;int parent;char ch;int lchild;int rchild;}*myHaffTree;struct Coding{char bit[MAX];char ch;int weight;}*myHaffCode;void Haffman(int n){int i,j,x1,x2,s1,s2;for (i=n+1;i<=2*n-1;i++) {s1=s2=10000;x1=x2=0;for (j=1;j<=i-1;j++)/*定义常量*//*权值*//*双亲结点下标*//*构造哈夫曼树*//*定义数组*//*字符的权值*//*定义结构体*//*定义哈夫曼函数*//*树的初始化*//*构造哈夫曼树的非叶子结点*/{if(myHaffTree[j].parent==0&&myHaffTree[j].weight<s1){s2=s1;x2=x1;s1=myHaffTree[j].weight;x1=j;/*分配摆布结点*/}else if(myHaffTree[j].parent==0&&myHaffTree[j].weight<s2){s2=myHaffTree[j].weight;x2=j;}}myHaffTree[x1].parent=i;myHaffTree[x2].parent=i;myHaffTree[i].weight=s1+s2;myHaffTree[i].lchild=x1;myHaffTree[i].rchild=x2;/*摆布子组合为新树*/}}void HaffmanCode(int n){int start,c,f,i,j,k;char *cd;/*构造n 个结点哈夫曼编码*/cd=(char *)malloc(n*sizeof(char));myHaffCode=(struct Coding *)malloc((n+1)*sizeof(struct Coding));cd[n-1]='\0';for(i=1;i<=n;++i) /*n 个叶子结点的哈夫曼编码*/ {start=n-1;for(c=i,f=myHaffTree[i].parent;f!=0;c=f,f=myHaffTree[f].parent)if(myHaffTree[f].lchild==c) cd[--start]='0';else cd[--start]='1';for(j=start,k=0;j<n;j++){myHaffCode[i].bit[k]=cd[j];k++;}myHaffCode[i].ch=myHaffTree[i].ch; myHaffCode[i].weight=myHaffTree[i].weight; }free(cd);}Init(){int i,n,m;printf("please input the number of words:"); scanf("%d",&n); /*取编码对应的权值*//*定义有返回值的函数*/m=2*n-1;myHaffTree=(struct HaffNode *)malloc(sizeof(struct HaffNode)*(m+1)); for(i=1;i<=n;i++){printf("please input the word and the equal:");scanf("%s%d",&myHaffTree[i].ch,&myHaffTree[i].weight); myHaffTree[i].parent=0;myHaffTree[i].lchild=0;myHaffTree[i].rchild=0;}for(i=n+1;i<=m;i++){myHaffTree[i].ch ='#';myHaffTree[i].lchild=0;myHaffTree[i].parent=0;myHaffTree[i].rchild=0;myHaffTree[i].weight=0;}Haffman(n);HaffmanCode(n);for(i=1;i<=n;i++){printf("%c %d",myHaffCode[i].ch,myHaffCode[i].weight); printf("\n");}printf("init success!\n");return n;}void Caozuo_C(int m){int n,i,j;char string[50],*p;printf("please input the words :"); scanf("%s",string);n=strlen(string);for(i=1,p=string;i<=n;i++,p++){for(j=1;j<=m;j++)if(myHaffCode[j].ch==*p)printf("%s\n",myHaffCode[j].bit); }}void Caozuo_D(int n){int i,c;char code[1000],*p;printf("please input the coding:"); scanf("%s",code);for(p=code,c=2*n-1;*p!='\0';p++) {if(*p=='0'){c=myHaffTree[c].lchild;if(myHaffTree[c].lchild==0){printf("%c",myHaffTree[c].ch);c=2*n-1;continue;/* 编码函数*//*计算字符串长度*/ /*进行编码*//*解码函数*//*输入二进制编码*//*进行解码*//*结束条件*//*赋值*//* 扫描*//*结束*/}}else if(*p=='1'){c=myHaffTree[c].rchild;if(myHaffTree[c].lchild==0){printf("%c",myHaffTree[c].ch);c=2*n-1; /*赋值*/continue;}}}printf("\n");}void main(){int n;char char1;n=Init();printf("A.coding B.codeprintingwhile(1){scanf("%c",&char1);if(char1=='c')break;switch(char1){case'A':Caozuo_C(n);break;case'B':Caozuo_D(n);break;case'C':;break;}}}/*主函数*//*定义字符*//*函数的调用*/C.exit\nplease input the process:\n");/*判断字符*//*执行编码操作*//*执行解码操作*/哈夫曼编码与解码的实现(一)中缀转后缀算法的运行结果:这部份我主要遇到了如下三个问题,其内容与解决方法如下所列:问题1:刚开始不知道如何建一个好树,因为我开始试着建了几个二叉树,不知道什么原因运行的时候那编码总是不对,跟在草稿纸上自己画的那个二叉树总是不相符,就找原因。

数据结构课程设计哈夫曼编码实验

数据结构课程设计哈夫曼编码实验

数据结构设计性实验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)练习通过普通树来构造霍夫曼树。

数据结构课程设计哈夫曼编码译码器.doc

数据结构课程设计哈夫曼编码译码器.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 超过次数限制。

数据结构课程设计哈夫曼编码译码器

数据结构课程设计哈夫曼编码译码器

哈夫曼编码译码器哈夫曼编码译码器a)需求分析:一个完整的系统应具有以下功能:(l)I:初始化。

从终端读入字符集大小n,及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmtree中。

(2)C:编码。

利用已建好的哈夫曼树(如不在内存,则从文件hfmtree 中读入),对文件tobetrans中的正文进行编码,然后将结果存入文件codefile中。

(3)D:编码。

利用已建好的哈夫曼树将文件codefile中的代码进行译码,结果存入文件textfile中。

(4)P:印代码文件。

将文件codefile以紧凑格式显示在终端上,每行50个代码。

同时将此字符形式的编码文件写入文件codeprint中。

(5)T:印哈夫曼树。

将已在内存中的哈夫曼树以直观的方式 (树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件treeprint 中可以根据题目要求把程序划成5个模块,设计成菜单方式,每次执行一个模块后返回菜单。

除了初始化(I)过程外,在每次执行时都经过一次读取磁盘文件数据。

这是为了如果在程序执行后一直没有进行初始化(I)过程,为了能使后面的操作顺利进行,可以通过读取旧的数据来进行工作。

比如:如果程序的工作需要的字符集和权值数据是固定的,只要在安装程序时进行一次初始(I)化操作就可以了。

在再次运行程序时,不管进行那项操作都可以把需要的数据读入到内存。

b)概要设计本程序主要用到了三个算法。

(1)哈夫曼编码在初始化(I)的过程中间,要用输入的字符和权值建立哈夫曼树并求得哈夫曼编码。

先将输入的字符和权值存放到一个结构体数组中,建立哈夫曼树,将计算所得的哈夫曼编码存储到另一个结构体数组中。

(2)串的匹配在编码(D)的过程中间,要对已经编码过的代码译码,可利用循环,将代码中的与哈夫曼编码的长度相同的串与这个哈夫曼编码比较,如果相等就回显并存入文件。

(3)二叉树的遍历在印哈夫曼树(T)的中,因为哈夫曼树也是二叉树,所以就要利用二叉树的先序遍历将哈夫曼树输出c)详细设计构造树的方法如下:初始化:每个字符就是一个结点,字符的频度就是结点的权;1、将结点按频度从小到大排序;2、选取频度最小的两个结点,以它们为儿子,构造出一个新的结点;新结点的权值就是它两个儿子的权值之和;构造之后,从原来的结点序列里删除刚才选出的那两个结点,但同时将新生成的结点加进去;3、如果结点序列里只剩下一个结点,表示构造完毕,退出。

数据结构课程设计(哈夫曼编码)要点

数据结构课程设计(哈夫曼编码)要点

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

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

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

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

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

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

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

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

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

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

这样不但有助于我们消化课堂所讲解的内容,还可以增强我们的独立思考能力和动手能力;通过编写实验代码和调试运行,我们可以逐步积累调试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) 已知某系统在通信联络中只可能出现八种字符,其频率分别为0.05,0.29,0.07,0.08,0.14,0.23,0.03,0.11,试设计赫夫曼编码。

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

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

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

哈夫曼编码译码课程设计报告

哈夫曼编码译码课程设计报告

哈夫曼编码译码课程设计报告《数据结构》课程设计——赫夫曼编码/译码器设计指导教师:李文书、周维达班级:10电信实验班学号:Q10600132姓名:王彬彬一、实验目的1、提高分析问题、解决问题的能力,进一步巩固数据结构各种原理与方法。

2、熟悉掌握一门计算机语言,能够进行数据算法设计。

二、实验原理哈夫曼编\译码器的主要功能是先建立哈夫曼树,然后利用建好的哈夫曼树生成哈夫曼编码后进行译码。

在数据通信中,经常需要将传送的文字转换成由二进制字符0、1组成的二进制串,称之为编码。

构造一棵哈夫曼树,规定哈夫曼树中的左分之代表0,右分支代表1,则从根节点到每个叶子节点所经过的路径分支组成的0和1的序列便为该节点对应字符的编码,称之为哈夫曼编码。

最简单的二进制编码方式是等长编码。

若采用不等长编码,让出现频率高的字符具有较短的编码,让出现频率低的字符具有较长的编码,这样可能缩短传送电文的总长度。

哈夫曼树课用于构造使电文的编码总长最短的编码方案。

主要流程图如下:三、实验步骤1:写好流程图,设计实验方案。

2:初始化,从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件HuofumanTree中。

3:编码。

利用已建好的哈夫曼树,对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。

4:译码。

利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件Textfile中。

5:印代码文件(Print).将文件CodeFile以紧凑格式显示在终端上,每行50个代码。

同时将此字符形式的编码文件写入文件CodePrint中。

6:印哈夫曼树(Treeprinting).将已在内存中的哈夫曼树以直观的方式(比如树)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint 中。

具体函数如下:1:Initialization() 初始化2:Encoding() 编码3:Decoding() 译码4:Print_file() 打印代码文件5:search(k,j,p) 搜索二叉树6:Print_tree() 打印二叉树7:menu() 主菜单9:main() 主函数四、实验结果与分析(1)大致个人测试案例:主界面:。

数据结构课程设计报告 哈弗曼编码

数据结构课程设计报告 哈弗曼编码

数据结构课程设计院系:班级:组别:指导教师:摘要随着计算机的普遍应用与日益发展,其应用早已不局限于简单的数值运算,而涉及到问题的分析、数据结构框架的设计以及设计最短路线等复杂的非数值处理和操作。

算法与数据结构的学习就是为以后利用计算机资源高效地开发非数值处理的计算机程序打下坚实的理论、方法和技术基础。

算法与数据结构旨在分析研究计算机加工的数据对象的特性,以便选择适当的数据结构和存储结构,从而使建立在其上的解决问题的算法达到最优。

数据结构是在整个计算机科学与技术领域上广泛被使用的术语。

它用来反映一个数据的内部构成,即一个数据由那些成分数据构成,以什么方式构成,呈什么结构。

数据结构有逻辑上的数据结构和物理上的数据结构之分。

逻辑上的数据结构反映成分数据之间的逻辑关系,而物理上的数据结构反映成分数据在计算机内部的存储安排。

数据结构是数据存在的形式。

《数据结构》主要介绍一些最常用的数据结构,阐明各种数据结构内在的逻辑关系,讨论其在计算机中的存储表示,以及在其上进行各种运算时的实现算法,并对算法的效率进行简单的分析和讨论。

数据结构是介于数学、计算机软件和计算机硬件之间的一门计算机专业的核心课程,它是计算机程序设计、数据库、操作系统、编译原理及人工智能等的重要基础,广泛的应用于信息学、系统工程等各种领域。

学习数据结构是为了将实际问题中所涉及的对象在计算机中表示出来并对它们进行处理。

通过课程设计可以提高学生的思维能力,促进学生的综合应用能力和专业素质的提高。

目录一.设计目的数据结构作为一门学科主要研究数据的各种逻辑结构和存储结构,以及对数据的各种操作。

因此,主要有三个方面的内容:数据的逻辑结构;数据的物理存储结构;对数据的操作(或算法)。

通常,算法的设计取决于数据的逻辑结构,算法的实现取决于数据的物理存储结构。

数据结构是信息的一种组织方式,其目的是为了提高算法的效率,它通常与一组算法的集合相对应,通过这组算法集合可以对数据结构中的数据进行某种操作。

数据结构课程设计报告哈夫曼编码译码器

数据结构课程设计报告哈夫曼编码译码器

哈弗曼编码译码器专业班级:XXXX学号:XXXX姓名:XXXX指导教师:XXXX课程设计时间:XXXX计算机专业数据结构课程设计任务书1 需求分析设计一个哈弗曼编码译码器,实现哈夫曼树的建立,树形输出,编码和解码。

2 概要设计3 运行环境(软、硬件环境)1) 硬件:PC 机main建立哈夫曼树查看哈夫曼编码树形输出哈夫哈夫曼文件编码哈夫曼文件解码帮助退出系统2)操作系统:Windows 2000/XP/20033)编译环境:Visual C++6.04 开发工具和编程语言开发工具:VISCALL c++6.0;编程语言:C语言。

5 详细设计#include<stdio.h>#include<stdlib.h>#include<string.h>typedef struct // 结点的结构{unsigned int weight; // 结点的权值unsigned int parent,lchild,rchild;}HTNode,*HuffmanTree; // 动态分配数组存储哈夫曼树typedef char **HuffmanCode; // 动态分配数组存储哈夫曼编码HuffmanTree HT;HuffmanCode HC;int n=8;const char menu[]="|1 建立哈夫曼树|\n""|2 查看哈夫曼编码|\n""|3 树形输出哈夫曼树|\n""|4 哈夫曼文件编码|\n""|5 哈夫曼文件解码|\n""|6 帮助|\n""|7 退出系统|\n";const char helpsabout[]="|主要功能: |\n""| 利用哈夫曼编码进行通信可以大大提高信道的利用率,缩短信息的传输时间,降低 |\n""|传输成本。

数据结构课程设计哈夫曼编码译码器

数据结构课程设计哈夫曼编码译码器

题目一: 哈夫曼编码与译码一、任务设计一个运用哈夫曼算法的编码和译码系统, 反复地显示并解决以下项目, 直到选择退出为止。

规定:1) 将权值数据存放在数据文献(文献名为data.txt, 位于执行程序的当前目录中) ;2) 初始化:键盘输入字符集记录字符权值、自定义26个字符和26个权值、记录文献中一篇英文文章中26个字母, 建立哈夫曼树;3) 编码: 运用建好的哈夫曼树生成哈夫曼编码;4) 输出编码(一方面实现屏幕输出, 然后实现文献输出);5)译码(键盘接受编码进行译码、文献读入编码进行译码);6) 界面优化设计。

二、流程图三、代码分解 //头文献 #include<stdio.h> #include<string.h> #include<stdlib.h> #include <conio.h> #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);字符集记录符集记录权值 权值 至文献“哈夫曼树。

t xt” 菜单1.从键盘输入字符集进行编码2.从文献读入字符集进行编码1.从键盘输入编码进行译码2.从文献读入编码进行译码0.返回上级菜单 0.返回上级菜单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{char data;int parent;int weight;int lchild;int rchild;}HTNode;typedef struct{char cd[N];int start;}HCode;typedef struct{char s[N];int num;}CHar;CHar ch;HTNode ht[M];HCode hcd[N];//主函数int main(){int xh;while(1){system("color 1f"); //操作菜单背景颜色 xh=caidan(); //调用菜单函数switch(xh) //switch语句 {case 1:system("cls");creat_cw();break;case 2:system("cls");creatHT(ht,n);break;case 3:system("cls");CreateHCode(ht,hcd,n);DispHCode(ht,hcd,n);break;case 4:system("cls");bianmayima();break;case 0:system("cls");printf("\n\n\n\n\n\n\n\n\n\t\t\t\t感谢使用本系统!\n\n\n\n\n\n\n \t\t\t");exit(0);default:system("cls");putchar('\a');printf("\n\t\t输入有误, 请重新输入:\n");break;}}return 0;}//菜单函数int caidan() //菜单函数模块//{int xh;printf("\n\n\n");printf("\t\t 欢迎使用哈夫曼编码译码系统\n");printf("\t\t \n");printf("\t\t*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*\n");printf("\t\t*= =*\n");printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*= =*\n");printf("\t\t*= 1.建立字符权值=*\n");printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*= =*\n"); printf("\t\t*= 2.建立并输出哈夫曼树=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*= =*\n"); printf("\t\t*= 3.生成并查看哈夫曼编码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*= =*\n"); printf("\t\t*= 4.编码与译码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*= =*\n"); printf("\t\t*= 0.退出系统=*\n"); printf("\t\t*= =*\n"); printf("\t\t*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*\n"); printf("\n\t\t请输入序号进行选择:");scanf("%d", &xh);return xh; //返回从键盘接受的选项}void bianmayima(){int xh;while(1){printf("\n\n\n\n\n");printf("\t\t 编码与译码\n"); printf("\t\t \n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n");printf("\t\t*= 1.编码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 2.译码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 0.返回上级菜单=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\n\t\t请输入序号进行选择:");scanf("%d",&xh);switch(xh) //switch语句{case 1:system("cls");bianmacaidan();break;case 2:system("cls");yimacaidan();break;case 0:system("cls");return;default:system("cls");putchar('\a');printf("\n\t\t输入有误, 请重新输入:\n");break;}}}void yimacaidan(){int xh;while(1){printf("\n\n\n\n\n");printf("\t\t 译码\n"); printf("\t\t \n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 1.键盘输入编码进行译码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 2.文献读入编码进行译码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 0.返回上级菜单=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\n\t\t请输入序号进行选择:");scanf("%d",&xh);switch(xh) //switch语句{case 1:system("cls");yima1(ht,hcd,n,bianma);break;case 2:system("cls");yima2(ht,hcd,n,bianma);break;case 0:system("cls");return;default:system("cls");putchar('\a');printf("\n\t\t输入有误, 请重新输入:\n");break;}}}void bianmacaidan(){int xh;while(1){printf("\n\n\n\n\n");printf("\t\t 编码\n"); printf("\t\t \n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 1.键盘输入字符集编码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 2.文献读入文章编码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 0.返回上级菜单=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\n\t\t请输入序号进行选择:");scanf("%d",&xh);switch(xh) //switch语句{case 1:system("cls");bianma1(ht,hcd,ch,n,bianma);break;case 2:system("cls");bianma2(ht,hcd,ch,n,bianma);break;case 0:system("cls");return;default:system("cls");putchar('\a');printf("\n\t\t输入有误, 请重新输入:\n");break;}}}void creat_cw(){int xh2;while(1){printf("\n\n\n\n\n");printf("\t\t 建立字符权值\n"); printf("\t\t \n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 1.从键盘输入字符集进行记录=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 2.从文献读入字符集记录=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 3.自定义字符权值=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 0.返回上级菜单=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\n\t\t请输入序号进行选择:");scanf("%d",&xh2);switch(xh2) //switch语句{case 1:system("cls");input_key(ch);break;case 2:system("cls");input_file(ch);break;case 3:system("cls");input_cw(ht);break;case 0:system("cls");return;default:system("cls");putchar('\a');printf("\n\t\t输入有误, 请重新输入:\n");break;}}}//建立字符权值模块void input_key(CHar &ch){int i,j=0;char st[N];printf("请输入字符集(以‘#’结束):\n");for(i=0;i<N;i++){scanf("%c",&st[i]);if(st[i]=='#'){st[i]='\0';break;}}strcpy(ch.s,st);count(ch,ht);printf("按任意键返回!");getch();system("cls");return;}void input_file(CHar &ch){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);}printf("读入成功!\n");printf("文献中的字符集为:%s\n",ch.s);fclose(fp);count(ch,ht);printf("按任意键返回!");getch();system("cls");return;}void input_cw(HTNode ht[]){int i,w,s,j;char a;printf("要输入的字符总个数是?:");scanf("%d",&s);n=s;printf("请输入字符及其权值:\n");for(i=0;i<s;i++){printf("请输入第%d个字母:",i+1);scanf("%s",&a);ht[i].data=a;printf("请输入其权值:");scanf("%d",&w);ht[i].weight=w;}FILE *fp;if((fp=fopen("data.txt","w"))==0){printf("\n\t\t文献打开失败");return;}printf("\n定义权值成功!\n\n");printf("各字符及其权值为:\n\n");fprintf(fp,"各字符及其权值为:\n");printf(" 字符\t权值");fprintf(fp," 字符\t权值");for(j=0;j<i;j++){ printf("\n");fprintf(fp,"\n");printf(" %-8c%-8d",ht[j].data,ht[j].weight);fprintf(fp," %-8c%-8d%",ht[j].data,ht[j].weight); }printf("\n");printf("\n字符权值已输出至文献“data.txt”!");fclose(fp);printf("输入完毕, 按任意键返回!");getch();system("cls");return;}//记录字符权值函数void count(CHar &ch,HTNode ht[]){int i,j,m=0;char c[N];int sum[N]={0};for(i=0;ch.s[i]!='\0';i++){for(j=0;j<m;j++)if(ch.s[i]==c[j]||(c[j]>='a'&&c[j]<='z'&&ch.s[i]+32==c[j])) break;if(j<m)sum[j]++;else{if(ch.s[i]>='A'&&ch.s[i]<='Z')c[j]=ch.s[i]+32;else c[j]=ch.s[i];sum[j]++;m++;}}for(i=0;i<m;i++){ht[i].data=c[i];ht[i].weight=sum[i];}n=m;FILE *fp;if((fp=fopen("data.txt","w"))==0) {printf("\n\t\t文献打开失败"); return;}printf("\n记录权值成功!\n\n"); printf("各字符及其权值为:\n\n"); fprintf(fp,"各字符及其权值为:\n"); printf(" 字符\t权值");fprintf(fp," 字符\t权值");for(j=0;j<m;j++){ printf("\n");fprintf(fp,"\n");printf(" %-8c%-8d",ht[j].data,ht[j].weight);fprintf(fp," %-8c%-8d%",ht[j].data,ht[j].weight);}printf("\n");printf("\n字符权值已输出至文献“data.txt”!");fclose(fp);}//构造哈夫曼树void creatHT(HTNode ht[],int n){FILE *fp;if((fp=fopen("哈夫曼树.txt","w"))==0){printf("\n\t\t文献打开失败");return;}int i,j,k,lnode,rnode;int min1,min2;for (i=0;i<2*n-1;i++)ht[i].parent=ht[i].lchild=ht[i].rchild=-1;for (i=n;i<2*n-1;i++){min1=min2=32767;lnode=rnode=-1;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;ht[i].weight=ht[lnode].weight+ht[rnode].weight;ht[i].lchild=lnode;ht[i].rchild=rnode;}printf("建立huffman树成功!\n");printf("输出huffman树:\n");fprintf(fp,"输出huffman树:\n");printf("\t字符\t权值\t父节点\t 左子节点\t右子节点");fprintf(fp,"\t字符\t权值\t父节点\t 左子节点\t右子节点");for(j=1;j<i;j++){ printf("\n");fprintf(fp,"\n");printf("\t %-8c%-8d%-10d%-14d%-10d",ht[j].data,ht[j].weight,ht[j].parent,ht[i]. lchild,ht[j].rchild);fprintf(fp,"\t %-8c%-8d%-10d%-14d%-10d",ht[j].data,ht[j].weight,ht[j].parent,h t[i].lchild,ht[j].rchild);}printf("\n");printf("哈夫曼树已输出至文献“哈夫曼树.txt”!按任意键返回!");fclose(fp);getch();system("cls");return;}//生成哈夫曼编码void CreateHCode (HTNode ht[],HCode hcd[],int n){int i,f,c,j=0;HCode hc;for(i=0;i<n;i++){hc.start=n;c=i;hc.cd[hc.start--]='0';f=ht[i].parent;while(f!=-1){if (ht[f].lchild==c)hc.cd[hc.start--]='0';elsehc.cd[hc.start--]='1';c=f;f=ht[f].parent;}hc.start++;for(j=0;j<hc.start;j++)hc.cd[j]=' ';hcd[i]=hc;}}void DispHCode(HTNode ht[],HCode hcd[],int n) {FILE *fp;if((fp=fopen("哈夫曼编码.txt","w"))==0){printf("\n\t\t文献打开失败");return;}int i,k;int sum=0,m=0,j;printf("输出字符哈夫曼编码:\n"); fputs("输出字符哈夫曼编码:\n",fp); for (i=0;i<n;i++){j=0;printf("%c:\t",ht[i].data);fprintf(fp,"\n%c:\t",ht[i].data);for (k=hcd[i].start;k<=n;k++){printf("%c",hcd[i].cd[k]);j++;fprintf(fp,"%c",hcd[i].cd[k]); }m+=ht[i].weight;sum+=ht[i].weight*j;printf("\n");}printf("\n哈夫曼编码已保存至文献“哈夫曼编码.txt!按任意键返回!”");fclose(fp);getch();system("cls");}//编码函数void bianma1(HTNode ht[],HCode hcd[],CHar &ch,int n,char bianma[]){int i;char str[N];printf("请输入要编码的字符集(以‘#’结束):\n");for(i=0;i<N;i++){scanf("%c",&str[i]);if(str[i]=='#'){str[i]='\0';break;}}strcpy(ch.s,str);ch.num=strlen(str);editHCode(ht,hcd,ch,n,bianma);getch();system("cls");}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);system("cls");return;}//译码函数void yima1(HTNode ht[],HCode hcd[],int n,char bianma[]) {int i;char code[MAXcode];printf("请输入编码进行译码(以‘#’结束):\n");for(i=0;i<MAXcode;i++){scanf("%c",&code[i]);if(code[i]=='#'){code[i]='\0';break;}}strcpy(bianma,code);printyima(ht,hcd,n,bianma);printf("\n译码完毕!按任意键返回!");getch();system("cls");return;}void yima2(HTNode ht[],HCode hcd[],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(&bianma[i],sizeof(char),1,fp);}printf("读入成功!\n");printf("文献中的编码是:%s\n",bianma);printyima(ht,hcd,n,bianma);printf("\n译码完毕!按任意键返回!");getch();system("cls");}四、调试结果主菜单建立字符权值选择2.从文献读入字符进行记录输入测试文献名“cs.txt”输出个字符权值建立哈夫曼树并输出至文献生成哈夫曼编码并保存至文献编码选择2.从文献读入字符集编码编码结果保存至文献译码选择2.从文献读入编码, 读入上一步的编码译码完毕, 返回!退出系统。

数据结构课程设计哈夫曼编码译码器

数据结构课程设计哈夫曼编码译码器

哈夫曼编码译码器哈夫曼编码译码器a)需求分析:一个完整的系统应具有以下功能:(l)I:初始化。

从终端读入字符集大小n,及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmtree中。

(2)C:编码。

利用已建好的哈夫曼树(如不在内存,则从文件hfmtree 中读入),对文件tobetrans中的正文进行编码,然后将结果存入文件codefile中。

(3)D:编码。

利用已建好的哈夫曼树将文件codefile中的代码进行译码,结果存入文件textfile中。

(4)P:印代码文件。

将文件codefile以紧凑格式显示在终端上,每行50个代码。

同时将此字符形式的编码文件写入文件codeprint中。

(5)T:印哈夫曼树。

将已在内存中的哈夫曼树以直观的方式 (树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件treeprint 中可以根据题目要求把程序划成5个模块,设计成菜单方式,每次执行一个模块后返回菜单。

除了初始化(I)过程外,在每次执行时都经过一次读取磁盘文件数据。

这是为了如果在程序执行后一直没有进行初始化(I)过程,为了能使后面的操作顺利进行,可以通过读取旧的数据来进行工作。

比如:如果程序的工作需要的字符集和权值数据是固定的,只要在安装程序时进行一次初始(I)化操作就可以了。

在再次运行程序时,不管进行那项操作都可以把需要的数据读入到内存。

b)概要设计本程序主要用到了三个算法。

(1)哈夫曼编码在初始化(I)的过程中间,要用输入的字符和权值建立哈夫曼树并求得哈夫曼编码。

先将输入的字符和权值存放到一个结构体数组中,建立哈夫曼树,将计算所得的哈夫曼编码存储到另一个结构体数组中。

(2)串的匹配在编码(D)的过程中间,要对已经编码过的代码译码,可利用循环,将代码中的与哈夫曼编码的长度相同的串与这个哈夫曼编码比较,如果相等就回显并存入文件。

(3)二叉树的遍历在印哈夫曼树(T)的中,因为哈夫曼树也是二叉树,所以就要利用二叉树的先序遍历将哈夫曼树输出c)详细设计构造树的方法如下:初始化:每个字符就是一个结点,字符的频度就是结点的权;1、将结点按频度从小到大排序;2、选取频度最小的两个结点,以它们为儿子,构造出一个新的结点;新结点的权值就是它两个儿子的权值之和;构造之后,从原来的结点序列里删除刚才选出的那两个结点,但同时将新生成的结点加进去;3、如果结点序列里只剩下一个结点,表示构造完毕,退出。

数据结构课程设计哈夫曼编码译码器

数据结构课程设计哈夫曼编码译码器

数据结构课程设计哈夫曼编码译码器个节点的权值、父节点、左孩子和右孩子,然后通过选择最小的两个节点合并,构建Huffman树;3:Huffman编码:通过遍历Huffman树,对每个叶子节点进行编码,将编码结果存入新的文件中;4:译码:读取存放Huffman编码的文件,通过遍历Huffman树进行译码,将译码结果存入新的文件中;5:结果验证:比较原文件和译码结果文件的内容是否一致,输出结果;3.函数说明1:CrtHuffmanTree():创建Huffman树;2:HuffmanCoding():对Huffman树进行遍历,生成Huffman编码;3:HuffmanDecoding():对Huffman编码进行译码,生成原文件内容;4:CompareFile():比较原文件和译码结果文件的内容是否一致;五、详细设计1.统计字符频率:定义结构体typedef struct strchar data;char num;str;其中data域存放字符名称,num域存放字符出现频率,读取文件ywq1.txt,通过循环比较将结果赋入S2[128]中;2.创建Huffman树:定义结构体typedef structchar data;int weight;int parent;int lchild;int rchild;HTNode,HuffmanTree[M+1];作为Huffman树存储节点类型,调用CrtHuffmanTree()函数,初始化各个节点的权值、父节点、左孩子和右孩子,然后通过选择最小的两个节点合并,构建Huffman树;3.Huffman编码:通过遍历Huffman树,对每个叶子节点进行编码,将编码结果存入新的文件中;4.译码:读取存放Huffman编码的文件,通过遍历Huffman树进行译码,将译码结果存入新的文件中;5.结果验证:比较原文件和译码结果文件的内容是否一致,输出结果;六、测试1.测试数据测试文件:ywq1.txt(包含英文字母、数字和符号)2.测试结果测试结果正确,能够正确地对文件进行Huffman编码和译码,生成的译码结果文件与原文件内容一致;七、总结通过本次课程设计,我深入了解了Huffman编码/译码器的实现原理和过程,掌握了Huffman树的创建、存储和遍历方法,提高了动手能力,同时也为数据压缩问题提供了一种有效的解决方法。

数据结构与算法——电文的编码和译码

数据结构与算法——电文的编码和译码

电文的编码和译码1.问题描述从键盘接受一串电文字符,输出对应的哈夫曼编码;同时能翻译由哈夫曼编码生成的代码串,输出对应的电文字符串。

2.设计要求(1)构造一棵哈夫曼树。

(2)实现哈夫曼编码,并用哈夫曼编码生成的代码进行译码。

(3)程序中字符和权值是可变的,实现程序的灵活性。

3.数据结构本课程设计采用结构体数组作为数据结构,来储存哈夫曼树及其编码。

4.分析与实现在电报通信中,电文是以二进制代码传送的。

在发送时,需要将电文中的字符转换成二进制代码串,即编码;在接收时,要将收到的二进制代码串转化成对应的字符序列,即译码。

字符被使用的频率是非均匀的。

在传送电文时,要想使电文总长尽可能短,就需要让使用频率高的字符编码长度尽可能短。

因此,若对某字符集进行不定长编码设计,则要求任一一个字符编码都不能使其他字符编码的前缀,这种编码称作前缀编码。

由哈弗曼树求得的编码是最优前缀码,也称哈夫曼编码。

给出字符集和各个字符的概率分布,构造哈弗曼树,将哈夫曼树中每个分支结点的左分支标0,右分支标1,从根到每个叶子的路径上的标号连起来就是给叶子所代表字符的编码。

(1)构造哈夫曼树根据哈弗曼算法,若已知n个叶结点,则构造的哈弗曼树有2n-1个结点。

第一步:先输入字符集中的n个字符(叶结点)和表示其概率分布的权值,储存在ht (HuffNode型)数组的前n个数组元素中。

然后将2n-1个结点的双亲和孩子结点均置为0。

第二步:在所有的结点中,选取双亲为零且具有最小权值m1和次小权值m2的两个结点,用p1和p2指示这两个结点在数组中的位置。

将根为ht[p1]和ht[p2]的两棵树合并,使其成为新结点ht[i]的左右孩子,ht[i]的权值为最小权值m1和次小权值m2之和;ht[p1]和ht[p2]的双亲指向i。

共进行n-1次合并,产生n-1个结点,依次放入ht数组中数组下标从n+1到2n-1。

这样就构成了一棵哈夫曼树。

(2)编码基本思想是:从哈弗曼树的叶结点ht[i] (1≤i≤n)出发,通过双亲parent找到其双亲ht[f],通过ht[f]的域left和right,可知ht[i]是ht[f]的左分支还是右分支,若是左分支,生成的代码0;若是右分支,生成代码1。

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