哈夫曼编码和译码的设计与实现
- 格式:doc
- 大小:94.00 KB
- 文档页数:13
实验报告(2014 / 2015 学年第一学期)课程名称数据结构实验名称二叉树基本操作以及哈夫曼编码译码系统实验时间年月日指导单位指导教师学生姓名班级学号学院(系) 专业二叉树的基本运算:一、问题描述1.设计递归算法,实现二叉树的运算:删除一棵二叉树,求一棵二叉树的高度,求一棵二叉树中叶子节点数,复制一棵二叉树,交换一棵二叉树的左右子树2.设计算法,自上而下,自左向右即按层次遍历一棵二叉树3.设计main函数,测试上述每个运算二、系统分析和概要设计首先用maketree构造一棵二叉树,然后遍历二叉树,然后交换每个结点的左右子树,接着算出输得高度和叶子节点,最后删除。
三、详细设计2. 核心算法建立二叉树的void MakeTree(const T& x,BinaryTree<T>& left,BinaryTree<T>& right)和计算叶子节点的int Size();3. 算法分析删除一棵二叉树,求一棵二叉树的高度,求一棵二叉树中叶子节点数,复制一棵二叉树等都是用递归的方法实现。
四、程序代码流程图#include<iostream.h>template<class T>struct BTNode{BTNode(){lChild=rChild=NULL;}BTNode(const T &x){element=x;lChild=rChild=NULL;}BTNode(const T &x,BTNode<T>* l,BTNode<T>* r){element=x;lChild=l;rChild=r;}T element;BTNode<T>* lChild,* rChild;};template<class T>class BinaryTree{public:BinaryTree(){root=NULL;}~BinaryTree(){Clear();}void Copy(BinaryTree<T> &r) const;bool IsEmpty()const{return root == NULL;}void Clear();void Exchange();bool Root(T& x)const;int GetHeight();void MakeTree(const T& x,BinaryTree<T>& left,BinaryTree<T>& right);void BreakTree(T& x,BinaryTree<T>& left,BinaryTree<T>& right);void PreOrder(void (*Visit)(T &x));void LevelOrder(void (*Visit)(T& x));int Size();BinaryTree<T>(BinaryTree<T> &t)root=Copy(t.root);}// void InOrder(void (*Visit)(T &x));// void PostOrder(void (*Visit)(T &x));BTNode<T>* Copy(BTNode<T>* t);protected:BTNode<T> * root;private:static int number;void Clear(BTNode<T>* &t);void Exchange(BTNode<T>* t);int GetHeight(BTNode<T>* t);int Size(BTNode<T>* t);void PreOrder(void (*Visit)(T &x),BTNode<T>* t);void LevelOrder(void (*Visit)(T& x),BTNode<T>* t); // void InOrder(void (*Visit)(T &x),BTNode<T>* t);// void PostOrder(void (*Visit)(T &x),BTNode<T>* t); };template <class T>bool BinaryTree<T>::Root(T &x)const{if(root){x=root->element;return true;}elsereturn false;}template <class T>void BinaryTree<T>::Clear(){Clear(root);}template <class T>void BinaryTree<T>::Clear(BTNode<T>* &t){if(t)Clear(t->lChild);Clear(t->rChild);delete t;t=NULL;}}template <class T>void BinaryTree<T>::MakeTree(const T& x,BinaryTree<T>& left,BinaryTree<T>& right) {if(root||&left==&right)return;root=new BTNode <T>(x,left.root,right.root);left.root=right.root=NULL;}template <class T>void BinaryTree<T>::BreakTree(T& x,BinaryTree<T>& left,BinaryTree<T>& right) {if(!root||&left==&right||left.root||right.root)return;x=root->element;left.root=root->lChild;right.root=root->rChild;delete root;root=NULL;}template <class T>BTNode<T>* BinaryTree<T>::Copy(BTNode<T>* t){if(!t)return NULL;BTNode<T>*q=new BTNode<T>(t->element);q->lChild=Copy(t->lChild);q->rChild=Copy(t->rChild);return q;}template <class T>void Visit(T &x){cout<<x<<" ";}template <class T>void BinaryTree<T>::PreOrder(void (*Visit)(T& x)){PreOrder(Visit,root);}template <class T>void BinaryTree<T>::PreOrder(void (*Visit)(T& x),BTNode<T>* t) {if(t){Visit(t->element);PreOrder(Visit,t->lChild);PreOrder(Visit,t->rChild);}}template <class T>void BinaryTree<T>::Exchange(){Exchange(root);}template <class T>void BinaryTree<T>::Exchange(BTNode<T>* t){if(!t)return;BTNode<T>* temp;temp=t->lChild;t->lChild=t->rChild;t->rChild=temp;Exchange(t->lChild);Exchange(t->rChild);}template <class T>int BinaryTree<T>::GetHeight(){return GetHeight(root);}int BinaryTree<T>::GetHeight(BTNode<T>* t){int templ;int tempr;if(!t)return 0;templ=GetHeight(t->lChild);tempr=GetHeight(t->rChild);if(templ++>tempr++)return templ;elsereturn tempr;}template <class T>int BinaryTree<T>::number=0;template <class T>int BinaryTree<T>::Size(){Size(root);return number;}template <class T>int BinaryTree<T>::Size(BTNode<T>* t){if(t!=NULL){Size(t->lChild);if(t->lChild ==NULL&&t->rChild ==NULL)number++;Size(t->rChild);}return number;}template <class T>void BinaryTree<T>::LevelOrder(void (*Visit)(T& x)) {PreOrder(Visit,root);}void BinaryTree<T>::LevelOrder(void (*Visit)(T& x),BTNode<T>* t) {BTNode *quene[50],*p;int pre=1,rear=1;quene[++pre]=t;while(pre!=0){p=quene[++rear];cout<<p->element<<" ";if(p->lChild !=NULL)quene[++pre]=p->rChild ;if(p->rChild !=NULL)quene[++pre]=p->lChild ;}}void main(){BinaryTree <char> a,b,x,y,z;y.MakeTree('E',a,b);z.MakeTree('F',a,b);x.MakeTree('C',y,z);y.MakeTree('D',a,b);z.MakeTree('B',y,x);cout<<"二叉树z的先序遍历:"<<endl;z.PreOrder(Visit);cout<<endl;cout<<"层次遍历二叉树:";z.LevelOrder(Visit);cout<<endl;BinaryTree<char> q(z);cout<<"复制的二叉树q的先序遍历:"<<endl;q.PreOrder(Visit);cout<<endl;cout<<"树的高度:";cout<<z.GetHeight()<<endl;cout<<"叶子节点数量:";cout<<z.Size()<<endl;z.Exchange();cout<<"二叉树左右子树交换后的先序遍历:"<<endl;z.PreOrder(Visit);cout<<endl;}五、测试用例和运行结果测试用例如main函数中所示,结果如下图所示。
数据结构与算法――电文的编码和译码电文的编码和译码在信息传输中起着重要的作用。
在传统的通信方式中,电文的编码和译码主要通过人工来完成,但是随着科技的发展,自动编码和译码系统也逐渐应用到各个领域中。
本文将介绍电文的编码和译码的常用算法和数据结构。
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编码可以根据输入的字符序列动态生成字典,可以适用于任意类型的数据。
建筑大学电气与电子信息工程学院信息理论与编码课程设计报告设计题目:哈夫曼编码的分析与实现专业班级:电子信息工程101学生: _____________________________学号: ________________________________ 扌指导教师:吕卅王超________________ 设计时间:2013.11.18 —2013.11.29、设计的作用、目的《信息论与编码》是一门理论与实践密切结合的课程, 课程设计是其实践性教学环节之一,同时也是对课堂所学理论知识的巩固和补充。
其主要目的是加深对理论知识的理解,掌握查阅有关资料的技能,提高实践技能,培养独立分析问题、解决问题及实际应用的能力。
通过完成具体编码算法的程序设计和调试工作,提高编程能力,深刻理解信源编码、信道编译码的基本思想和目的,掌握编码的基本原理与编码过程,增强逻辑思维能力,培养和提高自学能力以及综合运用所学理论知识去分析解决实际问题的能力,逐步熟悉开展科学实践的程序和方法二、设计任务及要求通过课程设计各环节的实践,应使学生达到如下要求:1. 理解无失真信源编码的理论基础,掌握无失真信源编码的基本方法;2. 掌握哈夫曼编码/ 费诺编码方法的基本步骤及优缺点;3. 深刻理解信道编码的基本思想与目的,理解线性分组码的基本原理与编码过程;4. 能够使用MATLA或其他语言进行编程,编写的函数要有通用性。
三、设计容一个有8个符号的信源X,各个符号出现的概率为:X x1, x2, x3, x4, x5, x6 x7 x8P(X) 0.4 0.18 0.1 0.1 0.07 0.06 0.05 0.04 编码方法:先将信源符号按其出现的概率大小依次排列,并取概率最小的字母分别配以0和1两个码元(先0后1或者先1后0,以后赋值固定),再将这两个概率相加作为一个新字母的概率,与未分配的二进制符号的字母重新排队。
并不断重复这一过程,直到最后两个符号配以0和1为止。
数据结构课程设计报告课程设计题目:电文的编码和译码姓名:***专业:信息管理与信息系统学号:************班级:*****指导教师:*****2014年6月东华理工大学课程设计评分表学生姓名:*** 班级:**** 学号:**********课程设计题目:电文的编码与译码一、需求分析 0二.设计内容 01)问题描述 02)设计要求 03)分析与实现 (1)4)功能要求 (1)5)概要设计 (2)三. 调试 (6)1)建立哈夫曼树 (6)2)编码 (7)3)译码 (8)四. 实验心得体会 (9)一、需求分析当今社会的一些领域,电文仍然被应用着,编写一个电文编码和译码系统还是有必要的,哈夫曼编码是广泛用于数据文件压缩的十分有效的编码方法。
其压缩通常在20%~90%之间。
哈夫曼编码算法使用字符在文件中出现的频率表来建立一个用0,1串表示各字符的最优表示方式。
哈夫曼编码的应用很广泛,利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。
树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,取每条分支上路径上的“0”或“1”的序列作为各个叶子对应的字符的编码,这就是哈夫曼编码。
该设计是对输入的一串电文字符实现哈夫曼编码,或对哈夫曼编码生成的代码串进行译码,输出电文字符串。
二.设计内容1)问题描述从键盘接收一串电文字符,输出对应的哈夫曼编码。
同时能翻译有哈夫曼编码生成的代码串,输出对应的电文字符串。
2)设计要求(1)构造一颗Huffman树。
(2)实现Huffman编码,并用Huffman编码生成的代码串进行译码。
(3)程序中字符和权值时可变的,实现程序的灵活性。
3)分析与实现在电报通信中,电文是以二进制代码传送的。
在发送时,需要将电文中的字符转换成二进制代码串,即编码;在接收时,要将收到的二进制代码转化为对应的字符序列,即译码。
我们知道,字符集中的字符被使用的频率是非均匀的。
哈夫曼时间复杂度哈夫曼编码是一种常用的数据压缩算法,它通过构建最优的二叉树来实现对数据的高效编码。
在实际应用中,我们需要对哈夫曼编码的时间复杂度进行分析,以评估算法的性能和效率。
本文将讨论哈夫曼编码的时间复杂度,并对其进行详细解释。
一、哈夫曼编码的基本原理哈夫曼编码是一种变长编码方式,其基本原理是根据不同字符的出现频率构建一颗最优的二叉树,使得出现频率高的字符拥有较短的编码,而出现频率低的字符拥有较长的编码。
通过这种方式,我们可以实现对数据的高效压缩和解压缩。
二、哈夫曼编码的时间复杂度1. 构建哈夫曼树的时间复杂度:O(nlogn)构建哈夫曼树的过程主要包括以下几个步骤:(1)根据字符的出现频率构建小顶堆:O(nlogn)。
(2)通过不断合并堆顶的两个节点构建哈夫曼树:O(nlogn)。
因此,构建哈夫曼树的总时间复杂度为O(nlogn)。
2. 生成哈夫曼编码的时间复杂度:O(n)生成哈夫曼编码的过程是在哈夫曼树的基础上通过遍历每个叶子节点来得到对应的编码。
由于哈夫曼树中每个叶子节点都是对应一个字符,因此遍历每个叶子节点的时间复杂度为O(n)。
3. 压缩和解压缩数据的时间复杂度:O(n)在得到了字符对应的哈夫曼编码后,对于压缩和解压缩数据的操作,其时间复杂度主要取决于数据的长度,即O(n)。
综上所述,哈夫曼编码的总时间复杂度为O(nlogn),其中n为数据的长度。
值得注意的是,由于构建哈夫曼树的过程中涉及到了对频率进行排序的操作,因此时间复杂度比较高。
三、哈夫曼编码的应用哈夫曼编码在实际应用中被广泛使用,尤其是在数据压缩领域。
通过使用哈夫曼编码,我们可以大幅度减少数据的存储空间和传输带宽,提高数据的传输效率。
此外,哈夫曼编码还可以应用于图像压缩、音频压缩等领域。
通过对图像或音频数据进行编码,我们可以将其压缩为较小的文件大小,从而节省存储空间和提高传输效率。
总结:哈夫曼编码是一种高效的数据压缩算法,通过构建最优的二叉树实现对数据的编码和解码。
霍夫曼编码解码过程霍夫曼编码是一种基于概率的变长编码方法,主要用于无损数据压缩。
其核心思想是给出现概率较高的符号赋予较短的编码,反之则赋予较长的编码。
这样,平均码长将会接近于原始数据的熵,从而实现有效的数据压缩。
以下是霍夫曼编码和解码的过程:霍夫曼编码过程:1.首先,统计出待编码数据中每个字符出现的频率,例如,对于字符串"ABABABABA",我们可以得到字符'A'出现4次,字符'B'出现5次。
2.创建一个霍夫曼树。
这个树是一个二叉树,其中每个节点代表一个字符,节点的频率作为权重。
3.从根节点开始,对于每个节点,如果其左子节点和右子节点代表的字符不同,则将当前节点替换为一个新的字符,这个新字符的码字是左子节点和右子节点码字的组合。
需要注意的是,实际的霍夫曼编码过程中可能会有多种不同的树结构生成相同的结果,因此在具体实现时需要保证算法的稳定性和可重复性。
霍夫曼解码过程:霍夫曼解码是将霍夫曼编码后的数据进行还原的过程。
由于霍夫曼编码是前缀编码,也就是说编码后的码字没有前缀相同的后缀,因此解码过程是唯一的。
具体来说,解码步骤如下:1.从第一个字节开始,根据霍夫曼树的每个分支的权值(即字符出现的频率),从根节点向下查找对应的字符。
例如,对于码字"00",我们首先找到根节点,然后找到左子节点对应的字符'A'。
2.对于每个后续的字节,重复上述步骤。
需要注意的是,由于霍夫曼编码是前缀编码,因此我们不需要担心码字的结束位置,只要遇到一个码字,就可以一直解码下去,直到所有数据都被解码。
通过以上步骤,我们可以将霍夫曼编码的数据还原成原始的数据。
总的来说,霍夫曼编码是一种非常有效的无损数据压缩方法,尤其适用于数据中存在大量重复元素的情况。
Huffman编/解码一.问题描述1.题目内容:利用Huffman编码进行通信可以大大提高信道的利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据进行预先编码,在接收端进行解码。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/解码系统。
2.基本要求:一个完整的系统应该具有以下功能:1. I:初始化(Initialization)。
从终端读入字符集大小n,以及n 个字符和n个权值,建立Huffman树,并将它存入hfmTree中。
2. E:编码(Encoding)。
利用已经建好的Huffman树(如果不在内存,则应从文件hfmTree中读取),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
3. D:解码(Decoding)。
利用已经建立好的Huffman树将文件CodeFile中的代码进行解码,结果存入TextFile中。
4. P:打印代码文件(Print)。
将文件CodeFile以紧凑的格式显示在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件CodePrint中。
5. T:打印Huffman树(Tree Printing)。
将已经在内存中的Huffman树以直观的形式(凹入的形式)显示在终端上,同时将此字符形式的Huffman树写入文件TreePrint中。
数据机构实验报告3.测试数据:用下表给出的字符集和频度的实际统计数据建立Huffman树,并对以下报文进行编码和译码:“THIS PROGRAM IS MY FAVORITE”。
二.需求分析1. 编码结果以文本的方式存储在文件CodeFile中。
2. 用户界面可以设计为“菜单”方式:显示上述功能符号,再加上“Q”,表示退出(quit)。
请用户键入一个选择功能符。
此功能执行完毕后再显示此菜单,直至某次用户选择了Q为止。
3. 在程序的一次执行过程中,第一次执行I,D,C命令后,Huffman 树已经存在在内存中了,不必再读入。
% 1 完成对输入的序列进行各个码元的概率统计;%完成对字符串中的各字符的统计,并列出其概率分布矩阵,返回pro矩阵%s:待编码序列,S:所含的码元序列function pro=getpro(s)pro=[];a=length(s);S=unique(s);b=length(S);c=zeros(1,b); %用以存放个序列中各个码元的个数;%/////////////////////////////////////////////%进行概率计算;for i=1:bfor j=1:aif S(i)==s(j)c(i)=c(i)+1;else continue;end;end;end;pro=c./a;disp(S);disp(pro);%完成对已知编码序列的译码,以及在改变码表中的某一位值得情况下,再一次译码,计算其误码率;%Codenumber:已编码序列;huffmantable:码表;Code2:各码元的码长;pro2:各码元的概率分布矩阵;%s:原始序列;decodenumber:译码序列;function decodenumber=huffmandecode(Codenumber,huffmantable,Code2,pro2,bit)mm=unique(bit); %码元序列mm=mm(pro2(2,:));[lx,ly]=size(huffmantable);LL=size(Codenumber,2);decodenumber=[];ZF=[Codenumber,-ones(1,max(Code2))];for j=1:length(bit)for i=1:lxk=Code2(i);while(ZF(1:k)==huffmantable(i,1:k))decodenumber=[decodenumber,mm(i)];ZF=ZF(k+1:end);endendenddisp('译码序列如下:');disp(decodenumber);disp('原始序列如下:');disp(bit);end %对于译码部分所用到的部分主要是编码时生成的码表以及huffmantree,在进行编码的时候,%通过筛选后的源字符串的字符序列的下标,与码表中的每行相对应的原则,遍历编码序列;%在遍历的时候,通过码表中各行的码长,控制遍历的长度,与每行中的码表进行比较,输出相对应的字符,即完成了译码。
哈夫曼编码的平均码长1. 介绍在计算机科学中,哈夫曼编码是一种用于数据压缩的算法,通过将出现频率较高的字符用较短的编码表示,而将出现频率较低的字符用较长的编码表示,从而实现对数据的高效压缩。
哈夫曼编码的平均码长是衡量该编码算法效率的一个重要指标,本文将详细探讨哈夫曼编码的平均码长以及与其相关的概念和计算方法。
2. 哈夫曼树2.1 生成哈夫曼树的过程哈夫曼编码的核心是构建哈夫曼树。
哈夫曼树是一种特殊的二叉树,具有以下特点:- 所有的叶子节点对应输入字符集中的字符。
- 树的每个非叶子节点都有两个子节点,其中一个子节点表示频率较低的字符,另一个子节点表示频率较高的字符。
生成哈夫曼树的过程可以分为以下几步: 1. 统计字符的频率。
2. 将每个字符看作一个独立的节点,并按照字符频率构建一棵森林。
3. 从森林中选择两个频率最低的节点作为新的父节点,并将其频率设为两个子节点的频率之和。
然后将新节点插入到森林中,并删除原来的两个子节点。
4. 重复步骤3,直到森林中只剩下一个节点,即哈夫曼树的根节点。
2.2 示例以字符集{A, B, C, D, E}为例,假设每个字符的频率如下: - A: 10 - B: 6 - C: 3 - D: 2 - E: 1根据上述步骤,我们可以得到以下哈夫曼树:22/ \12 10/ \6 6/ \ / \3 3 2 43. 哈夫曼编码的计算在生成了哈夫曼树之后,我们可以根据该树来计算每个字符的哈夫曼编码。
哈夫曼编码定义为从根节点到叶子节点的路径上的0和1序列,其中0表示向左子树移动,1表示向右子树移动。
将每个字符的哈夫曼编码按照字符频率加权平均,即可得到哈夫曼编码的平均码长。
3.1 计算过程计算每个字符的哈夫曼编码的过程可以分为以下几步: 1. 从哈夫曼树的根节点开始,依次遍历每个字符的叶子节点。
2. 对于遍历到的每个叶子节点,从该叶子节点向上回溯到根节点,记录经过的路径上的0和1,即为该字符的哈夫曼编码。
算法与数据结构课程设计哈夫曼编码和译码的设计与实现1.问题描述利用哈夫曼编码进行通信可以大大提高信道的利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。
试为这样的信息收发站设计一个哈夫曼码的编/译码系统。
2.基本要求a.编/译码系统应具有以下功能:(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中。
b.测试数据(1)利用下面这道题中的数据调试程序。
某系统在通信联络中只可能出现八种字符,其概率分别为0.25,0.29,0.07,0.08,0.14,0.23,0.03,0.11,试设计哈夫曼编码。
(2)用下表给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:“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 13.需求分析3.1程序的基本功能本程序可以对任何大小的字符型文件进行Huffman编码,生成一个编码文件。
并可以在程序运行结束后的任意时间对它解码还原生成字符文件。
即:先对一条电文进行输入,并实现Huffman编码,然后对Huffman编码生成的代码串进行译码,最后输出电文数字3.2输入/输出形式当进行编码时输入为原字符文件文件名,当程序运行编码完成之后输入编码文件名(默认名为code.dll)。
当进行译码时输入为编码文件名(默认名为code.dll),从文件中读取Huffman 编码树后输入字符文件的文件名。
3.3测试数据要求本程序中测试数据主要为字符型文件。
4.概要设计1.2.功能模块说明(1).编码:提示要编码的文件文件名→读取文件→以字母出现次数为权值建立哈弗曼树→对文本进行哈弗曼编码并输出编码→提示将编码保存的文件名→保存编码文件;(2).译码:提示输入要译码的文件名→利用建立好的哈弗曼树进行译码→将译码输出→提示保存译码文件的文件名→保存译码文件;(3).退出:退出系统,程序运行结束。
5.详细设计创建哈弗曼树编码译码6.调试分析1.从叶子节点开始向上遍历二叉树,获得哈夫曼编码;2.根据哈夫曼编码遍历哈夫曼树直到叶子节点,获得译码3.算法的时间复杂度分析:程序部分用双循环嵌套结构,时间复杂度为O(n2).4.算法的空间复杂度分析:算法的空间复杂度为O(n)5. 程序需要反复调试,并且调试过程比较慢,需要有一个比较正确的调试方法,更需要我们有耐心7.用户使用说明1.输入字符的个数n2输入n个字符和n个权值3 选择(1—5)操作可对huffman树进行编码和译码以及huffman树表的打印4 退出系统8.测试结果9.附录#include "stdio.h"#include "stdlib.h"#include "string.h"#define MAX 100struct HafNode{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;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){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);}void print(){printf("************************************************************************* ******\n");printf("***** *****\n");printf("***** *****\n");printf("***** welcome to huffman coding and codeprinting *****\n");printf("***** *****\n");printf("***** *****\n");printf("*****1.init 2.coding 3.codeprinting 4.print the huffman 5.exit *****\n");printf("***** *****\n");printf("************************************************************************* ******\n");}Init(){int i,n,m;printf("now init\n");printf("please input the number of words:\n");scanf("%d",&n);m=2*n-1;myHaffTree=(struct HafNode *)malloc(sizeof(struct HafNode)*(m+1));for(i=1;i<=n;i++){printf("please input the word and the equal:\n");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:\n");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:\n");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 Caozuo_T(int n){int i;printf("word equal leftchild rightchild prents\n");for(i=1;i<=2*n-1;i++)printf("%c %d %d %d %d\n",myHaffTree[i].ch,myHaffTree[i].weight,myHaffTree[i].lchild,myHaf fTree[i].rchild,myHaffTree[i].parent);}main(){int n;char char1;print();n=Init();while(1){printf("A.coding B.codeprinting C.print the huffman D.exit\nplease input the process:\n");scanf("%s",&char1);if(char1=='D')break;switch(char1){case'A':Caozuo_C(n);break;/* 执行编码操作*/case'B':Caozuo_D(n);break;/* 执行译码操作*/case'C':Caozuo_T(n);break;/* 打印哈弗曼树*/}}}。