数据结构实验第9次课赫夫曼编译码器

合集下载

数据结构课程设计哈夫曼编码译码器.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、如果结点序列里只剩下一个结点,表示构造完毕,退出。

北邮数据结构实验—Huffman编码解码器

北邮数据结构实验—Huffman编码解码器

数据结构实验报告实验名称:____Huffman编码/解码器_____学生姓名:__________________班级:__________________班内序号:__________________学号:__________________日期:___________________1.实验要求利用二叉树结构实现哈夫曼编/解码器。

基本要求:1.初始化(Init):能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立哈夫曼树2.建立编码表(CreateTable):利用已经建好的哈夫曼树进行编码,并将每个字符的编码输出。

3.编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的字符串输出。

4.译码(Decoding):利用已经建好的哈夫曼树对编码后的字符串进行译码,并输出译码结果。

5.计算输入的字符串编码前和编码后的长度,并进行分析,讨论赫夫曼编码的压缩效果。

2. 程序分析2.1 存储结构静态三叉链表2.2 程序流程 (或程序结构、或类关系图等表明程序构成的内容,一般为流程图等)2.2.1.流程图2.2.1.伪代码1.输入进行编码的字符串2.遍历字符串,并为叶子节点权重赋值3.依次对各字符进行哈弗曼编码,自下往上,若是双亲节点左孩子则编码前插入‘0’,若是双亲节点右孩子则编码钱插入‘1’。

4.显示各字符的哈弗曼编码。

5.对字符串进行编码,挨个遍历字符,找到相应的编码,复制到总的编码里,最后输出字符串的编码。

6.对字符串的哈弗曼码进行译码。

自上往下,若是‘0’,则递归到左孩子,若是‘1’,则递归到右孩子,知道叶子节点,输出该叶子节点代表字符,再继续遍历。

7.分析内存占用情况。

若用ASCII编码,每个字符占1个字节,即8bit,该情况下占用内存就是(字符长度)*8。

若用哈弗曼编码,占用内存是各(字符频度)*(每个字符占用位数)之和。

2.3 关键算法分析该程序关键算法即哈弗曼编码,语句如下:void CHTree::huffmancode(){int i;if(n<=1)return;m=2*n-1;for(i=1;i<=n;i++)//叶子节点的初始化{ ht[i].parent=0;ht[i].lchild=0;ht[i].rchild=0;}for(;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)//构造哈夫曼树{s1=select(i-1);//函数在ht[1]到ht[i-1]中选择parent为0且weight最小的结点,并将结点序号返s,并将ht[s1].parent设为-1s2=select(i-1);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;}int c,f;for(i=1;i<=n;++i) {for(c=i,f=ht[i].parent;f!=0;c=f,f=ht[f].parent)//逆向求叶子结点的哈夫曼编码if(ht[f].lchild==c){str[i].insert(0,"0",0,1);} //在字符串str[i]的第0位置插入字符“0”else{str[i].insert(0,"1",0,1);} //在字符串str[i]的第0位置插入字符“1”}}分析:这段语句实现的功能是根据统计出来的各字符的频度,建立哈弗曼。

哈夫曼编码译码器数据结构C语言

哈夫曼编码译码器数据结构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)利用哈夫曼方法及其编/译码技术实现对传输信息编码/译码系统二、实验内容[问题描述](设计性实验)哈夫曼树很易求出给定字符集及其概率(或频度)分布的最优前缀码。

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

该技术一般可将数据文件压缩掉20,至90,,其压缩效率取决于被压缩文件的特征。

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

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

请自行设计实现一个具有初始化、编码、译码、输入/输出等功能的哈夫曼码的编码/译码系统。

并实现以下报文的编码和译码:“this program is my favorite”。

[测试数据]某通信的电文字符集为26个英文字母及空格字符,其出现频度如下表所示:[实现提示]如何创建哈夫曼树及如何求得各结点对应的哈夫曼编码算法:参见ppt。

1、设计思想描述(1) 问题分析。

(2) 哈夫曼树中各结点的结构描述(提示:图示)。

(3) 哈夫曼树的存储结构描述(提示:分析采用顺序存储还是利用链式存储等)。

2、主要算法设计与实现[要求]1)、利用类模板来实现。

2)、类中各成员函数要求给出自行设计的算法步骤描述及主要设计思想。

3)、给出类中各成员函数算法设计实现。

4)、对自行设计的各算法进行评估(提示:时间复杂度、空间复杂度等)。

#include<iostream>#include<string>using namespace std;const int MAX = 1000;class HTree;class HTNode{friend class HTree;unsigned int weight;unsigned int parent, lchild, rchild; };class HuCode{friend class HTree;char *ch; //字符的编码char data;//被编码的字符};//动态分配数组存储哈夫曼编码表。

数据库实验哈夫曼编译码器

数据库实验哈夫曼编译码器
数据库实验哈夫曼编译 码器
汇报人:XX
目录
添加目录标题
01
哈夫曼编译码器原理
02
数据库实验哈夫曼编译码 器实现
03
数据库实验哈夫曼编译码 器应用场景
04
数据库实验哈夫曼编译码 器与其他编译码器的比较
05
数据库实验哈夫曼编译码 器的发展趋势和未来展望
06
添加章节标题
哈夫曼编译码器 原理
哈夫曼编码原理
感谢您的观看
汇报人:XX
与算术编译码的比较
编码方式:哈夫曼编码采用可变长 度编码,而算术编码采用固定长度 编码
编码效率:哈夫曼编码通常比算术 编码更高效,因为它可以更好地利 用数据分布信息
精度:算术编码具有更高的精度, 因为它可以将概率估计精确到小数 点后多位
适用场景:哈夫曼编码适用于数据 量较小且概率分布不均的情况,而 算术编码适用于数据量较大且概率 分布均匀的情况
哈夫曼编码算法的改进方向
优化编码效率:提高哈夫曼编码的压缩比和编码速度 动态调整编码表:根据数据特征自适应调整哈夫曼编码表 降低误码率:改进哈夫曼编码的解码算法,降低解码错误率 跨平台兼容性:提高哈夫曼编码在不同平台和环境下的兼容性和稳定性
哈夫曼编码与其他技术的结合应用
哈夫曼编码与 压缩技术结合: 提高数据压缩
效率
哈夫曼编码与 加密技术结合: 增强数据传输
安全性
哈夫曼编码与 云计算技术结 合:实现大规
模数据处理
哈夫曼编码与 人工智能技术 结合:优化算 法提高编码效

哈夫曼编码在物联网和云计算领域的应用前景
物联网中的数据传输:哈夫曼编码能够有效地压缩数据,降低传输成本和提高传输效率,尤其在物联网领 域中,对于大量数据的处理和传输具有重要意义。

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

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

哈夫曼编码译码器实验报告实验名称:哈夫曼编码译码器实验一、实验目的: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) 将权值数据存放在数据文件(文件名为data.txt,位于执行程序的当前目录中) ;2) 初始化:键盘输入字符集统计字符权值、自定义26个字符和26个权值、统计文件中一篇英文文章中26个字母,建立哈夫曼树;3) 编码:利用建好的哈夫曼树生成哈夫曼编码;4) 输出编码(首先实现屏幕输出,然后实现文件输出);5)译码(键盘接收编码进行译码、文件读入编码进行译码);6) 界面优化设计。

二、流程图主菜单1.建立字符权值2.建立并输出哈夫曼树3.建立并查看哈弗曼编码4.编码与译码0.退出系统1.从键盘输入字符集统计2.从文件读入字符集统计权值3.自定义字符及权值0.返回上级菜单输出哈夫曼树并保存至文件“哈夫曼树。

t xt”1.编码2.译码0.返回上级菜单1.从键盘输入字符集进行编码2.从文件读入字符集进行编码1.从键盘输入编码进行译码2.从文件读入编码进行译码0.返回上级菜单0.返回上级菜单三、代码分解//头文件#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);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);ch.num=strlen(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);}ch.num=strlen(ch.s);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");return;}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<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.从文件读入编码,读入上一步的编码译码完成,返回!退出系统。

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

测试数据: 测试数据: 字符集和频度 字符 频度 186 空格 A 64 B 13 C 22 D 32 E 103 F 21 G 15 H 47 I 57 J 1 K 5 L 32 M 20 N 57 O 63 P 15 Q 1 R 48 S 51 T 80 U 23 V 8 W 18 X 1 Y 16 Z 1
HT weight parent lchild rchild
HC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
5 29 7 8 14 23 3 11
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
例:已知某系统在通信联络中只可能出现8种字符, 已知某系统在通信联络中只可能出现 种字符, 种字符 其概率分别是: 其概率分别是:0.05, 0.29, 0.07, 0.08, 0.14, 0.23, 0.03, 0.11, 试设计赫夫曼编码
归一化处理: W={5, 29, 7, 8, 14, 23, 3, 11}, n=8, 归一化处理 : , m=15
void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC, CharSet CA[],int n,int &m){ HuffmanTree p; int i,s1,s2,start,c,f; char *cd; if(n<=1) return; m=2*n-1; HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); HT[0].weigth=MaxWeight; for(p=HT+1,i=1;i<=n;++i,++p){ p->ch=CA[i-1].ch; p->weigth=CA[i-1].weigth; p->lchild=0; p->rchild=0; p->parent=0; } for(;i<=m;++i,++p){ p->ch=' '; p->weigth=0; p->lchild=0; p->rchild=0; p->parent=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].weigth=HT[s1].weigth+HT[s2].weigth; }
#include<stdio.h> #include<stdlib.h> #include<string.h> #define MaxWeight 2000 typedef struct{ char ch; int weigth; }CharSet;
typedef struct{ char ch; int weigth; int parent,lchild,rchild; }HTNode,*HuffmanTree; typedef char **HuffmanCode; char ToBeTran[100]="THIS PROGRAM IS MY FAVORITE"; char CodeFile[1000];
第9次课 赫夫曼编 译码器 次课 赫夫曼编/译码器
一、实验目的: 实验目的: 掌握最优二叉树概念,最优二叉树在编码问题中应用。 1. 掌握最优二叉树概念,最优二叉树在编码问题中应用。 了解二叉树静态二叉链表的存储方式。 2. 了解二叉树静态二叉链表的存储方式。 掌握通过文件读入数据的方法。 3. 掌握通过文件读入数据的方法。
for(i=1;i<=n;i++){ printf("%c",HT[i].ch); printf(" %s\n",HC[i]); } free(cd); return; }
void Select(HuffmanTree HT,int up,int &s1, int &s2){ int i; s1=s2=0; for(i=1;i<=up;i++) if(HT[i].parent==0) if(HT[i].weigth<HT[s1].weigth) {s2=s1;s1=i;} else if(HT[i].weigth<HT[s2].weigth) s2=i; return; }
●二叉树用于编码 设每种字符在电文中出现的次 数为wi,其编码长度为li, 数为 , 其编码长度为 ,电文中 只有n种字符 种字符, 只有 种字符,则电文的总长度为
n
0
1
电文总长度= 电文总长度
∑ wl
i =1
i i
A
0 1 C 0 B 1 D
若置wi为叶子结点, li恰为从根 若置 为叶子结点, 恰为从根 为叶子结点 到叶子的路径长度, 则电文总长 到叶子的路径长度 , 度为二叉树上的带权路径长度。 度为二叉树上的带权路径长度 。 设计电文总长度最短的二进制前 缀编码的问题,转换为以n种字符 缀编码的问题 ,转换为以 种字符 出现的频率作权, 出现的频率作权 , 设计一棵赫夫 曼树的问题。 曼树的问题。
\*为每个分支结点找它的左右孩子 为每个分支结点找它的左右孩子
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; for(c=i, f=HT[i].parent; f!=0; c=f, f= HT[f].parent) if(HT[f].lchild==c) cd[- -start]=’0’; elde cd[- -start]=’1’; HC[i]= (char*)malloc((n-start)* sizeof(char)); strcpy(HC[i], &cd[start]); } free(cd); }
\*动态分配数组存储赫夫曼编码 动态分配数组存储赫夫曼编码
在赫夫曼树的存储中, 注:在赫夫曼树的存储中,没有使用相对位置来描述结点之间 的相互关系,而是采用明示的方式来表示. 的相互关系,而是采用明示的方式来表示.
void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n){ if(n<=1) return; m=2*n-1; HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); for(p=HT+1,i=1; i<=n; ++i, ++p, ++w) *p={*w,0,0,0}; for( ; i<=m; ++p,++i) *p={0,0,0,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].weigth= HT[s1]. weigth+ HT[s2]. weigth; }
void ReadCharSet(int &n,CharSet CA[]); void Select(HuffmanTree HT,int up,int &s1, int &s2); void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC, CharSet CA[],int n,int &m); void Encoding(HuffmanCode HC); void Decoding(HuffmanTree HT,int m);
1 2 3 4 5 6 7 8
●建立赫夫曼树和生成赫夫曼编码
一棵有n个叶子结点的赫夫曼树共有 个结点, 一棵有 个叶子结点的赫夫曼树共有2n-1个结点 , 存储在一个 个叶子结点的赫夫曼树共有 个结点 大小为2n-1的一维数组中。 的一维数组中。 大小为 的一维数组中 typedef struct{ unsigned int weight; unsigned int parent, lchild, rchild; }HTNode, *HuffmanTree; typedef char *CharPointer; typedef CharPointer *HuffmanCode;
main(){ CharSet CharArray[100]; HuffmanTree HT; HuffmanCode HC; int n,m; ReadCharSet(n,CharArray); n=n+1; HuffmanCoding(HT,HC, CharArray,n,m); Encoding(HC); Decoding(HT,m)malloc((n+1)*sizeof(char*)); 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'; else cd[--start]='1'; HC[i]=(char*)malloc((n-start)*sizeof(char)); strcpy(HC[i],&cd[start]); }
相关文档
最新文档