哈夫曼编码译码系统

合集下载

哈夫曼编译码系统

哈夫曼编译码系统
if(bt[i].parent==0)
{
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)

哈夫曼编码译码系统实验报告,数据结构课程设计报告

哈夫曼编码译码系统实验报告,数据结构课程设计报告

v .. . ..安徽大学数据结构课程设计报告项目名称:哈弗曼编/译码系统的设计与实现姓名:鉏飞祥学号:E21414018专业:软件工程完成日期2016/7/4计算机科学与技术学院1 .需求分析1.1问题描述•问题描述:利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。

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

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

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

1.2基本要求(1)输入的形式和输入值的范围;(2)输出的形式;(3)程序所能达到的功能。

1.基本要求(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;2. 概要设计说明本程序中用到的所有抽象数据类型的定义。

主程序的流程以及各程序模块之间的层次(调用)关系。

(1)数据结构哈夫曼树的节点struct huff{int weight;int parent;int l;int r;};哈夫曼编码的存储struct huff *hufftree;(2)程序模块选择1到i-1中parent为0且权值最小的两个下标void Select(struct huff *HT, int n, int &s1, int &s2)构建哈夫曼树:void huffmancoding(struct huff *ht,int *w,int n)对原文进行编码:void code(char *c)根据报文找到原文:void decoding(char *zifu)3. 详细设计核心技术分析:1:构建哈夫曼树及生成哈夫曼编码:根据每个字符权值不同,根据最优二叉树的构建方法,递归生成哈夫曼树,并且用数组存放哈夫曼树。

哈夫曼编码译码器系统

哈夫曼编码译码器系统

具体介绍:在本课题中,我们在硬盘E盘中预先建立一个file1.txt文档,在里面编辑一篇文章(大写)。

然后运行程序,调用fileopen()函数读出该文章,显示在界面;再调用jsq()函数对该文章的字符种类进行统计,并对每个字符的出现次数进行统计,并且在界面上显示;然后以每个字符出现次数作为权值,调用ChuffmanTree()函数构建哈夫曼树;并调用print1()和print2()函数将哈夫曼的存储结构的初态和终态进行输出。

然后调用HuffmanEncoding()函数对哈夫曼树进行编码,调用coding()函数将编码写入文件;再调用decode()对编码进行译码,再输出至界面。

至此,整个工作就完成了。

测试数据:例如从文本中读到文章为:IAMASTUDENT。

则效果如下:IAMASTUDENT--------------------------------------HuffmanTree的初态:200010001000100010001000100020001000-000-000-000-000-000-000-000-000--------------------------------------字符A次数:2字符D次数:1字符E次数:1字符I次数:1字符M次数:1字符N次数:1字符S次数:1字符T次数:2字符U次数:1--------------------------------------HuffmanTree的终态:21300110001100011100111001120011200214001130021423215452156731691416810417111271713141101516--------------------------------------译码后的字符串:IAMASTUDENT********************************************************** Press any key to continue文档由风行播放器/暴风影音2014:/整理3系统(项目)设计(1)设计思路及方案本课题是用最优二叉树即哈夫曼树来实现哈夫曼编码译码器的功能。

哈夫曼编码译码系统

哈夫曼编码译码系统

《数据结构》课程设计——赫夫曼编码/译码器设计指导教师:孙树森、周维达班级:09数媒(2)班学号:E09700227姓名:曾焕凯数据结构课程设计报告书一、实验目的1、提高分析问题、解决问题的能力,进一步巩固数据结构各种原理与方法。

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

二、实验原理1、哈夫曼树的定义:假设有n 个权值,试构造一颗有n 个叶子节点的二叉树,每个叶子带权值为wi,其中树带权路径最小的二叉树成为哈夫曼树或者最优二叉树;2、哈夫曼树的构造:weight 为输入的频率数组,把其中的值赋给依次建立的HT Node 对象中的data 属性,即每一个HT Node 对应一个输入的频率。

然后根据data 属性按从小到大顺序排序,每次从data 取出两个最小和此次小的HT Node,将他们的data 相加,构造出新的HTNode 作为他们的父节点,指针parent,leftchild,rightchild 赋相应值。

在把这个新的节点插入最小堆。

按此步骤可以构造构造出一棵哈夫曼树。

通过已经构造出的哈夫曼树,自底向上,由频率节点开始向上寻找parent,直到parent 为树的顶点为止。

这样,根据每次向上搜索后,原节点为父节点的左孩子还是右孩子,来记录1 或0,这样,每个频率都会有一个01 编码与之唯一对应,并且任何编码没有前部分是同其他完整编码一样的。

三、实验步骤先统计要压缩编码的文件中的字符字母出现的次数,按字符字母和空格出现的概率对其进行哈夫曼编码。

然后读入要编码的文件,编码后存入另一个文件;接着再调出编码后的文件,并对其进行译码输出,最后存入另一个文件中。

具体步骤:1.初始化,统计文本文件中各字符的个数作为权值,生成哈夫曼树;2.根据符号概率的大小按由大到小顺序对符号进行排序;3.把概率最小的两个符号组成一个节点;4.重复步骤2. 3 ,直到概率和为1;5.从根节点开始到相应于每个符号的“树叶”,概率大的标“0”,概率小的标“1”;6.从根节点开始,对符号进行编码;7.译码时流程逆向进行,从文件中读出哈夫曼树,并利用哈夫曼树将编码序列解码。

哈夫曼编译码的设计与实现

哈夫曼编译码的设计与实现

哈夫曼编\译码的设计与实现一、简介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函数:控制整个程序的整个流程。

哈夫曼编码译码器实验报告

哈夫曼编码译码器实验报告

哈夫曼编码译码器实验报告实验名称:哈夫曼编码译码器实验一、实验目的: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.比较编码前后字符串的内容,结果正确。

五、实验总结:通过本次实验,我了解了哈夫曼编码的原理和应用,并且实现了一个简单的哈夫曼编码的编码和译码器。

在实验过程中,我充分运用了数据结构中的树的知识,构建了一个哈夫曼树,并生成了编码表。

通过编码和译码过程,我进一步巩固了对树的遍历和节点查找的理解。

实验结果表明,本次哈夫曼编码的编码和译码过程正确无误。

在实验的过程中,我发现哈夫曼编码对于频率较高的字符具有较短的编码,从而实现了对字符串的高效压缩。

同时,哈夫曼编码还可以应用于数据传输和存储中,提高数据的传输效率和存储空间的利用率。

通过本次实验,我不仅掌握了哈夫曼编码的编码和译码过程,还深入了解了其实现原理和应用场景,加深了对数据结构和算法的理解和应用能力。

数据结构实验,哈夫曼编码译码系统

数据结构实验,哈夫曼编码译码系统

数据结构实验,哈夫曼编码译码系统展开全文1. 实验名称: 二叉树的基本操作及哈夫曼编码译码系统的实现2.实验目的:创建一棵二叉树,实现先序、中序和后序遍历一棵二叉树,计算二叉树结点个数等操作。

哈夫曼编码/译码系统。

3. 实验任务:能成功演示二叉树的有关运算,运算完毕后能成功释放二叉树所有结点占用的系统内存。

4. 实验内容(1)在二叉链表上实现二叉树运算a) 设计递归算法,实现二叉树的基本运算:删除一棵二叉树,求一棵二叉树的高度,求一棵二叉树中叶子结点数,复制一棵二叉树,交换一棵二叉树的左右子树。

b) 设计算法,按自上到下,自左到右的次序,即按层次遍历一棵二叉树。

c) 设计main函数,测试上述每个运算。

d) 提示:队列结构可以辅助进行层次遍历,队列的元素类型是指向二叉树结点的指针类型。

(2)哈夫曼编码和译码系统a) 设计一个菜单可以循环显示B——建树:读入字符集和各字符频度,建立哈夫曼树。

T——遍历:先序和中序遍历二叉树。

E——生成编码:产生每个字符的哈夫曼编码。

C——编码:输入由字符集中字符组成的任意字符串,利用已经生成的哈夫曼编码进行编码,显示编码结果。

D——译码:利用已建成的哈夫曼树进行译码。

X——退出。

b) 提示:修改二叉树结点类BTNode,增加一个指向双亲的parent域,修改二叉树类的函数MakeTree设置该域的值;可以通过遍历哈夫曼树生成每个叶子结点的哈夫曼编码。

5. 概要设计1) 二叉树首先定义结点类BTNode包括对结点的访问,打印,交换结点左右元素等操作。

并将二叉树类BTree声明为友元类。

二叉树类中包含了建树,判断二叉树是否为空,求结点数,求高度,删除,交换左右子树,三种次序遍历及按层次遍历,清空二叉树等函数。

在主函数中调用实现这些功能。

类和类的层次设计主要算法:PreOrder:输出当前结点元素,左右孩子递归调用函数。

InOrder:左孩子递归调用函数,输出当前结点元素,右孩子递归调用。

哈夫曼编码和译码系统(附源代码)

哈夫曼编码和译码系统(附源代码)

实训报告题目:哈夫曼编码和译码系统院系:专业:姓名:学号:指导教师:日期:一.需求分析•二.概要设计(1)建立哈夫曼树、编码•(2)字符匹配•(3)哈夫曼树遍历• 3三.详细设计及编码实现•3四.流程图(1)总流程图75(2)编码实现流程图・16(3)译码实现流程图・17五.调试分析(1 )计算权值-18(1)生成哈夫曼树,建立编码表• 18 (3)将输入字符编码 19( 4 )输入新的字符串,进行译码 19( 5)输入新的二进制数将其译为字符 20六 . 系统维护 20 七.实验总结 20八. 源代码 21一.需求分析《1》问题描述:在传送电文时,人们总是希望传送时间尽可能短,这就是要求使电文代码长度尽可能短。

利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。

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

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

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

《2》打开一篇英文文章,统计该文章中每个字符出现的次数,然后以它们作为权值,对每一个字符进行编码,编码完成后再对其编码进行译码。

问题补充:1.从硬盘的一个文件里读出一段英语文章。

2.统计这篇文章中的每个字符出现的次数。

3.以字符出现字数作为权值,构建哈夫曼树,并将哈夫曼树的存储结构的初态和终态进行输出。

4.对每个字符进行编码并将所编码写入文件然后对所编码进行编译。

《3》这个哈夫曼编码译码主要是以英文字母输入进行编码与编译,编码译码过程由系统自动完成,人工操作部分就是电文的录入,和编译出来时的读操作。

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

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

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

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

《数据结构》课程设计——赫夫曼编码/译码器设计指导教师:孙树森、周维达班级:09数媒(2)班学号:E********姓名:***数据结构课程设计报告书一、实验目的1、提高分析问题、解决问题的能力,进一步巩固数据结构各种原理与方法。

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

二、实验原理1、哈夫曼树的定义:假设有n 个权值,试构造一颗有n 个叶子节点的二叉树,每个叶子带权值为wi,其中树带权路径最小的二叉树成为哈夫曼树或者最优二叉树;2、哈夫曼树的构造:weight 为输入的频率数组,把其中的值赋给依次建立的HT Node 对象中的data 属性,即每一个HT Node 对应一个输入的频率。

然后根据data 属性按从小到大顺序排序,每次从data 取出两个最小和此次小的HT Node,将他们的data 相加,构造出新的HTNode 作为他们的父节点,指针parent,leftchild,rightchild 赋相应值。

在把这个新的节点插入最小堆。

按此步骤可以构造构造出一棵哈夫曼树。

通过已经构造出的哈夫曼树,自底向上,由频率节点开始向上寻找parent,直到parent 为树的顶点为止。

这样,根据每次向上搜索后,原节点为父节点的左孩子还是右孩子,来记录1 或0,这样,每个频率都会有一个01 编码与之唯一对应,并且任何编码没有前部分是同其他完整编码一样的。

三、实验步骤先统计要压缩编码的文件中的字符字母出现的次数,按字符字母和空格出现的概率对其进行哈夫曼编码。

然后读入要编码的文件,编码后存入另一个文件;接着再调出编码后的文件,并对其进行译码输出,最后存入另一个文件中。

具体步骤:1.初始化,统计文本文件中各字符的个数作为权值,生成哈夫曼树;2.根据符号概率的大小按由大到小顺序对符号进行排序;3.把概率最小的两个符号组成一个节点;4.重复步骤2. 3 ,直到概率和为1;5.从根节点开始到相应于每个符号的“树叶”,概率大的标“0”,概率小的标“1”;6.从根节点开始,对符号进行编码;7.译码时流程逆向进行,从文件中读出哈夫曼树,并利用哈夫曼树将编码序列解码。

四、实验结果与分析哈夫曼编码是动态变长编码,临时建立概率统计表和编码树。

概率小的码比较长,概率小的码比较长。

概率大的码短,这样把一篇文件编码后,就会压缩许多。

从树的角度看,哈夫曼编码方式是尽量把短码都利用上。

首先,把一阶节点全都用上,如果码字不够时,然后,再从某个节点伸出若干枝,引出二阶节点作为码字,以此类推,显然所得码长最短,再根据建立的概率统计表合理分布和放置,使其平均码长最短就可以得到最佳码。

实验截图:五、实验心得本次实验结合了之前所学的赫夫曼算法,并利用其原理实现赫夫曼编码/译码系统;实验难度较之前的几次实验有所增加,所以花了比较多的时间来编写,测试代码。

期间参考了网上的一些程序,通过结合分析,了解其他人在实现这个算法时的思想,也借鉴了其中的一些东西,同时加入了自己的想法。

最终完成饿了本次的作业。

通过这次实验,我了解了一个算法到一个可以执行的程序之间还有很多工作需要做,深刻体会到实践出真知的到了,看似简单的算法在实现时却话费了这么多时间,但是这个过程中也让我学到了很多。

六、主要代码Huffman_Tree.h:#ifndef Huffman_Tree_h#define Huffman_Tree_h#endif#include <stdio.h>typedef struct {unsigned int weight;unsigned int parent,lchild,rchild;}HTNode, * HuffmanTree; //存储赫夫曼树的结点类型typedef char * * HuffmanCode; //用于存储字符集中各个字符相应的赫夫曼编码void strcpy(char *S1,char *S2){ //将字符串S2复制到S1int i = 0;while( S2[i] != '\0' ){S1[i] = S2[i];i++;}S1[i] = '\0';}//在HT[1]到HT[t-1]中找出权值最小的两个S1和S2----------------------------------------------- void Select(HuffmanTree HT,int t,int &s1,int &s2){int i = 1;s1 = s2 = 0;HT[0].weight = 50000;while( i <= t ){ //遍历查找权值最小的结点S1if( HT[i].parent == 0 && HT[i].weight < HT[s1].weight )s1 = i;i++;}i = 1;while( i <= t ){ //遍历查找除S1外权值最小的结点S2if( i != s1 && HT[i].parent == 0 && HT[i].weight < HT[s2].weight )s2 = i;i++;}}//根据各个字符的权值构造赫夫曼树HT,将对应的赫夫曼编码存储在HC中------------------------------------------------int HuffmanCoding( HuffmanTree &HT,HuffmanCode &HC,int *w,int n){int s1,s2,m,i,start;unsigned int c,f;HTNode * p;char *cd;if( n <= 1 ) return 0;m = 2 * n - 1; //赫夫曼树的总结点树为mHT = (HuffmanTree)malloc((m + 1) * sizeof(HTNode)); //申请存储赫夫曼树的空间for(p = HT + 1, i = 1; i <= n; ++i, ++p, ++w){ //将各个叶子结点的weight赋以相应的权值,parent,lchild,rchild均赋为0p->weight = *(w+1);p->parent = p->lchild = p->rchild = 0;}for( ; i <= m; ++i, ++p ){ //将各个非叶子结点的weight,parent,lchild,rchild均赋为0p->weight = p->parent = p->lchild = p->rchild = 0;}for( i = n + 1; i <= m; ++i ){ //构造赫夫曼树,给各个非叶子结点赋值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 *)); //用于存储指向存储各个字符相应赫夫曼编码的字符数组的指针cd = (char *)malloc(n * sizeof(char)); //分配工作所需空间cd[n - 1] = '\0'; //编码结束符for( i = 1; i <= n; ++i) //逐个字符求赫夫曼编码{start = n -1; //编码在数组cd[]中的最前位置//从叶子到根逆向求编码,初始值;停止条件;一次循环后对上一个节点做循环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[]数组的start位置到n-1位置复制给HC[i]}free(cd); //释放空间return 1;}Test.cpp:#include <stdio.h>#include <stdlib.h>#include "Huffman_Tree.h"#define Yes 1 //当程序已经调用过初始化赫夫曼树的InitHuff_T()函数,或已从htfTree文件读取过,则将Init_Mode置为Yes,否则为No#define No 0void InitHuff_T( HuffmanTree &HT, HuffmanCode &HC, char ch[],int &n ){ //初始化赫夫曼数,要求用户输入字符和相应权值int i = 1,w[100],temp,j;char a[20]; //数字转字符时,用于储存赫夫曼编码FILE *save;printf("请输入编码字符集的大小:");scanf("%d",&n); //获取用户输入的字符集个数while( i <= n ){ //获取用户输入的字符和相应权值,分别存储在ch[]和w[]数组中printf("请输入第%d个字符和该字符的权值:",i);fflush(stdin); //刷新标准输入缓冲区,把输入缓冲区里的东西丢弃scanf("%c%d",&ch[i],&w[i]);i++;}ch[i] = '\0';//哈夫曼树保存-------------------------------------------------------------------------------------------- HuffmanCoding(HT,HC,w,n); //根据用户的输入,生成赫夫曼数及各个字符相应的赫夫曼编码,分别存在HT树和HC中if(( save = fopen("hfmTree.TXT","w")) == NULL ){ //打开用于存储赫夫曼树的文件printf("Open file fail......\n");exit(0);}temp = n; //将字符集大小转换成字符形式写入到文件hfmTree.TXT中j = 0;while( temp != 0 ){//计算数字位数temp = temp / 10;j++;}temp = n; //数字转字符a[j] = '\0';while( temp != 0 ){a[j - 1] = (char)(temp % 10 + 48);temp = temp / 10;j--;}fputs(a,save);printf("%d\n",n); //向屏幕输出字符集大小nfputc('\n',save); //换行for( i = 1; i <= n; i++ ){ //分别向文件和屏幕输出各个字符和相应的赫夫曼编码fputc(ch[i],save); printf("%c\t",ch[i]); //字符fputc('\t',save);fputs(HC[i],save); printf("%s\n",HC[i]); //编码fputc('\n',save);}for(i = 1; i <= 2 * n - 1; i++ ){ //将赫夫曼树各个结点的parent,lchild,rchild分别写入到文件中temp = HT[i].parent; //将i结点的parent转换成字符并写入到文件中if(temp == 0){fputc(temp + 48,save);fputc(' ',save);}else{j = 0; //计算HT[i].parent数字位数while( temp != 0 ){temp = temp / 10;j++;}temp = HT[i].parent; //数字转字符a[j] = '\0';while( temp != 0 ){a[j - 1] = (char)(temp % 10 + 48);temp = temp / 10;j--;}fputs(a,save);fputc(' ',save);}temp = HT[i].lchild; //将i结点的lchild转换成字符并写入到文件中if(temp == 0){fputc(temp + 48,save);fputc(' ',save);}else{j = 0; //计算HT[i].lchild数字位数while( temp != 0 ){temp = temp / 10;j++;}temp = HT[i].lchild; //数字转字符a[j] = '\0';while( temp != 0 ){a[j - 1] = (char)(temp % 10 + 48);temp = temp / 10;j--;}fputs(a,save);fputc(' ',save);}temp = HT[i].rchild; //将i结点的rchild转换成字符并写入到文件中if(temp == 0){fputc(temp + 48,save);fputc('\n',save);}else{j = 0; //计算HT[i].lchild数字位数while( temp != 0 ){temp = temp / 10;j++;}temp = HT[i].rchild; //数字转字符a[j] = '\0';while( temp != 0 ){a[j - 1] = (char)(temp % 10 + 48);temp = temp / 10;j--;}fputs(a,save);fputc('\n',save);}}fclose(save);}//编码,并将所得编码存储到文件-----------------------------------void Encoding(HuffmanTree &HT, HuffmanCode &HC, char ch[]){FILE *ToBeTran,*CodeFile;int i;char c;if(( ToBeTran = fopen("ToBeTran.TXT","r")) == NULL ){printf("Open file fail......\n");exit(0);}if(( CodeFile = fopen("CodeFile.TXT","w")) == NULL ){printf("Open file fail......\n");exit(0);}c = fgetc(ToBeTran); //从文件读取一个字符while( c != EOF ){ //对文件中的各个字符进行编码,直至文件结尾i = 1;while( c != ch[i] && ch[i] != '\0' ) //在ch[]数组中查找从文件读取的字符i++;if(ch[i] == '\0'){ //未找到,c不在ch[]数组中,c无法被识别,退出printf("字符%c无法识别\n",c);exit(0);}fputs(HC[i],CodeFile); //若找到,则将c相应的赫夫曼编码写入到文件中printf("%s",HC[i]); //将c相应的赫夫曼编码输出到屏幕c = fgetc(ToBeTran); //读入文件中的下一个字符}printf("\n");fclose(ToBeTran);fclose(CodeFile);}//译码,翻译成相应的字符表示,并存储到文件------------------------------int p,i = 1;void Decoding(HuffmanTree &HT, char ch[] , int n){char code[1000],c;p = 2 * n - 1; //n为叶子数量,2*n-1即为根节点的节点号FILE *CodeFile,*TextFile;if(( CodeFile = fopen("CodeFile.TXT","r")) == NULL ){printf("Open file fail......\n");exit(0);}if(( TextFile = fopen("TextFile.TXT","w")) == NULL ){printf("Open file fail......\n");exit(0);}c = fgetc(CodeFile);while( c != EOF ){ //从文件读取字符,存储在code[]数组中code[i] = c;i++;c = fgetc(CodeFile);}code[i] = '\0';i = 1;while ( code[i] != '\0' && p != 0 ){ //对数组code[]中的赫夫曼编码进行译码,p储存节点号if ( code[i] == '0' )p=HT[p].lchild; //进入左分支elsep = HT[p].rchild; //进入右分支if (!HT[p].lchild&& !HT[p].rchild){ //不再有叶子节点时(进入叶子结点)fputc(ch[p],TextFile); //将相应的字符写入到文件中printf("%c",ch[p]); //将相应的字符输出到屏幕p = 2 * n - 1; //重新从树根出发进行译码}i++;}printf("\n");}//从文件读取赫夫曼树-------------------------------------------------------------------------------------void ReadHuff_T( HuffmanTree &HT, HuffmanCode &HC, char ch[], int &n){FILE *hfmTree;char c[100],ch1;int i,j,t;if(( hfmTree = fopen("hfmTree.TXT","r")) == NULL ){ //打开存有赫夫曼树信息的文件printf("Open file fail......\n");exit(0);}fgets(c,10,hfmTree); //获取赫夫曼树叶子结点个数(字符串)i = 0; //将字符串形式转换成整数形式while( c[i] != '\n' )i++;n = 0;for( j = 0; j < i; j++ )n = 10 * n + c[j] - '0'; //求出叶子结点数nHC = (HuffmanCode)malloc((n + 1) * sizeof(char *)); //申请HC空间HT = (HuffmanTree)malloc((2 * n) * sizeof(HTNode)); //申请赫夫曼树存储空间i = 1;while( i <= n ){ch[i] = fgetc(hfmTree); //读取字符集中的一个字符HC[i] = (char *)malloc((10)*sizeof(char)); //申请用于存储读取到的字符集中的字符的赫夫曼编码的空间fgetc(hfmTree); //将‘\t’读取并输出ch1 = fgetc(hfmTree); //读取赫夫曼编码,存储在相应的HC[i][]数组里int j = 0;while( ch1 != '\n' ){HC[i][j] = ch1;j++;ch1 = fgetc(hfmTree);}HC[i][j] = '\0';i++;}ch[i] = '\0';i = 0;while( i < 2 * n - 1 ){ //读取赫夫曼树的各个结点的parent,lchild,rchild.并赋值到赫夫曼树HT中ch1 = fgetc(hfmTree); //读取parent的字符串形式,存储在c[]中,并将其转换成整数形式,赋给HT[i].parent j = 0;while( ch1 != ' ' ){ //遇到空格前将读取的字符都保存在c[]中c[j] = ch1;j++;ch1 = fgetc(hfmTree);}HT[i+1].parent = 0; //初始化for( t = 0; t < j; t++ ) //字符转整型HT[i+1].parent = 10 * HT[i+1].parent + c[t] - '0';ch1 = fgetc(hfmTree); //读取lchild的字符串形式,并将其转换成整数形式,赋给HT[i].lchild j = 0;while( ch1 != ' ' ){ //遇到空格前将读取的字符都保存在c[]中c[j] = ch1;j++;ch1 = fgetc(hfmTree);}HT[i+1].lchild = 0; //初始化for( t = 0; t < j; t++ ) //字符转整型HT[i+1].lchild = 10 * HT[i+1].lchild + c[t] - '0';ch1 = fgetc(hfmTree); //读取rchild的字符串形式,并将其转换成整数形式,赋给HT[i].rchild j = 0;while( ch1 != '\n' ){ //换行前将读取的字符都保存在c[]中c[j] = ch1;j++;ch1 = fgetc(hfmTree);}HT[i+1].rchild = 0; //初始化for( t = 0; t < j; t++ ) //字符转整型HT[i+1].rchild = 10 * HT[i+1].rchild + c[t] - '0';i++;}}//显示规定格式编码,并将所得编码存储到文件-----------------------------------void CodePrin(){FILE *CodePrin,*CodeFile;char c;int prin[200];int k=0;if(( CodeFile = fopen("CodeFile.TXT","r")) == NULL ){printf("Open file fail......\n");exit(0);}if(( CodePrin = fopen("CodePrin.TXT","w")) == NULL ){printf("Open file fail......\n");exit(0);}c = fgetc(CodeFile); //从文件读取一个字符while( c != EOF ){ //对文件中的各个字符进行编码,直至文件结尾if(c=='1') prin[k]=1;else prin[k]=0;fputc(c,CodePrin); //将c相应的赫夫曼编码写入到文件中printf("%d",prin[k]); //将c相应的赫夫曼编码输出到屏幕c = fgetc(CodeFile); //读入文件中的下一个字符k++;if(k%50==0){ //50个字符时,换行printf("\n");fputc('\n',CodePrin);}}printf("\n");fclose(CodePrin);fclose(CodeFile);}//显示并打印赫夫曼树----------------------------------------------------------------void TreePrint(HuffmanTree &HT, int n) {FILE *TreePrint;char a[20];int temp;int j;if(( TreePrint = fopen("TreePrint.TXT","w")) == NULL ){ //打开用于存储赫夫曼树的文件printf("Open file fail......\n");exit(0);}for(i = 1; i <= 2 * n - 1; i++ ){ //将赫夫曼树各个结点的parent,lchild,rchild分别显示printf("%d ",HT[i].parent);printf("%d ",HT[i].lchild);printf("%d",HT[i].rchild);printf("\n");temp = HT[i].parent; //将i结点的parent转换成字符并写入到文件中if(temp == 0){fputc(temp + 48,TreePrint);fputc(' ',TreePrint);}else{j = 0; //计算HT[i].parent数字位数while( temp != 0 ){temp = temp / 10;j++;}temp = HT[i].parent; //数字转字符a[j] = '\0';a[j - 1] = (char)(temp % 10 + 48);temp = temp / 10;j--;}fputs(a,TreePrint);fputc(' ',TreePrint);}temp = HT[i].lchild; //将i结点的lchild转换成字符并写入到文件中if(temp == 0){fputc(temp + 48,TreePrint);fputc(' ',TreePrint);}else{j = 0; //计算HT[i].lchild数字位数while( temp != 0 ){temp = temp / 10;j++;}temp = HT[i].lchild; //数字转字符a[j] = '\0';while( temp != 0 ){a[j - 1] = (char)(temp % 10 + 48);temp = temp / 10;j--;}fputs(a,TreePrint);fputc(' ',TreePrint);}temp = HT[i].rchild; //将i结点的rchild转换成字符并写入到文件中if(temp == 0){fputc(temp + 48,TreePrint);fputc('\n',TreePrint);}else{j = 0; //计算HT[i].lchild数字位数while( temp != 0 ){temp = temp / 10;j++;}temp = HT[i].rchild; //数字转字符a[j] = '\0';a[j - 1] = (char)(temp % 10 + 48);temp = temp / 10;j--;}fputs(a,TreePrint);fputc('\n',TreePrint);}}fclose(TreePrint);}//主函数----------------------------------------------------------------------int main(){HuffmanTree HT;HuffmanCode HC;char ch[100]; //用于存储字符集int n,Init_Mode = No; //n为字符集的大小,Init_Mode = No 表示内存中没有赫夫曼树的信息char mode; //让用户选择不同的操作printf("请输入你要选择的功能(命令需要大写)\n");printf("I -- 初始化 E -- 编码\n");printf("D -- 译码P -- 显示并打印编码\n");printf("T -- 显示并打印赫夫曼树Q -- 退出程序\n");scanf("%c",&mode); //获得用户选择的操作while( mode != 'Q' ){ //当用户输入不为Q时,执行相应操作switch(mode){case 'I' :InitHuff_T(HT,HC,ch,n);Init_Mode = Yes;break;case 'E' :if( No == Init_Mode )ReadHuff_T(HT,HC,ch,n);Encoding(HT,HC,ch);Init_Mode = Yes;break;case 'D' :if( No == Init_Mode )ReadHuff_T(HT,HC,ch,n);Decoding(HT,ch,n);Init_Mode = Yes;break;case 'P' :CodePrin();break;case 'T' :if( No == Init_Mode )ReadHuff_T(HT,HC,ch,n);TreePrint(HT,n);Init_Mode = Yes;break;default :printf("您的输入有错,请重新选择.\n");}printf("请输入你要选择的功能\n");printf("I -- 初始化 E -- 编码\n");printf("D -- 译码P -- 显示并打印编码\n"); printf("T -- 显示并打印赫夫曼树Q -- 退出程序\n");fflush(stdin);scanf("%c",&mode); //继续选择相应的操作,直至用户选择退出}return 0;}成绩评定表。

相关文档
最新文档