实验三哈夫曼树实验报告

合集下载

数据结构(C语言版)实验报告(哈夫曼树)

数据结构(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)利用教科书例6-2中的数据调试程序。

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

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

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

请用户键入一个选择功能符。

此功能执行完毕后再显示此菜单,直至某次用户选择了“Q”为止。

(3)在程序的一次执行过程中,第一次执行I、D或C命令之后,哈夫曼树已经在内存了,不必再读入。

哈夫曼树实验报告

哈夫曼树实验报告

数据结构实验报告实验名称:实验三哈夫曼树学生姓名:班级:班内序号:学号:日期:程序分析:2.1 存储结构:二叉树2.2 程序流程:template <class T>class BiTree{public:BiTree(); //构造函数,其前序序列由键盘输入 ~BiTree(void); //析构函数BiNode<T>* Getroot(); //获得指向根结点的指针protected:BiNode<T> *root; //指向根结点的头指针};//声明类BiTree及定义结构BiNodeData:二叉树是由一个根结点和两棵互不相交的左右子树构成二叉树中的结点具有相同数据类型及层次关系哈夫曼树类的数据域,继承节点类型为int的二叉树class HuffmanTree:public BiTree<int>data:HCode* HCodeTable;//编码表int tSize; //编码表中的总字符数二叉树的节点结构template <class T>struct BiNode //二叉树的结点结构{T data; //记录数据T lchild; //左孩子T rchild; //右孩子T parent; //双亲};编码表的节点结构struct HCode{char data; //编码表中的字符char code[100]; //该字符对应的编码};待编码字符串由键盘输入,输入时用链表存储,链表节点为struct Node{char character; //输入的字符unsigned int count;//该字符的权值bool used; //建立树的时候该字符是否使用过Node* next; //保存下一个节点的地址};示意图:2.3 关键算法分析:1.初始化函数(void HuffmanTree::Init(string Input))算法伪代码:1.初始化链表的头结点2.获得输入字符串的第一个字符,并将其插入到链表尾部,n=1(n记录的是链表中字符的个数)3.从字符串第2个字符开始,逐个取出字符串中的字符3.1 将当前取出的字符与链表中已经存在的字符逐个比较,如果当前取出的字符与链表中已经存在的某个字符相同,则链表中该字符的权值加1。

数据结构与算法实验报告_3霍夫曼树

数据结构与算法实验报告_3霍夫曼树

实验四数据结构与程序设计专题实验报告赫夫曼树学院:物理与电子学院班级:电信1105班姓名:刘岩学号:1404110729实验报告一、实验任务实验题目:数据结构与程序设计专题实验二、实验内容实验三:树的基本操作及基于霍夫曼树的编码/译码(一)实验目的:掌握结构体、指针及二叉树的生成、遍历等操作掌握霍夫曼编码/译码的原理。

(二)基本要求:熟练掌握树的操作。

(三)内容提要:给定一段字符,构建霍夫曼树;根据该树求每个字符的编码,并对该段字符串进行编码;将得到的编码进行译码;基于该霍夫曼树,通过遍历算法来输出该树中的叶子节点。

注:在实现时要求霍夫曼树的左右孩子的大小关系(左孩子节点值小于右孩子节点),在遍历的时候也可以为递归与非递归办法寻找叶子节点。

三、要点分析题目中涉及的主要知识点:1、本程序参考霍夫曼算法(由给定的权值构造赫夫曼树):(1)由给定的n个权值{w0, w1, w2, …, w n-1},构造具有n棵二叉树的集合F = {T0, T1, T2, …, T n-1},其中每一棵二叉树T i只有一个带有权值w i的根结点,其左、右子树均为空。

(2)重复以下步骤, 直到F中仅剩下一棵树为止:① 在F中选取两棵根结点的权值最小的二叉树, 做为左、右子树构造一棵新的二叉树。

置新的二叉树的根结点的权值为其左、右子树上根结点的权值之和。

② 在F中删去这两棵二叉树。

③ 把新的二叉树加入F。

2、用构造赫夫曼树以完成赫夫曼编码:把d1,d2,…, dn作为叶子结点,把w1,w2,…,wn作为叶子结点的权,构造赫夫曼树。

在赫夫曼树中结点的左分支赋0,右分支赋1,从根结点到叶子结点的路径上的数字拼接起来就是这个叶子结点字符的编码。

3、译码的过程是分解电文中的字符串,从根出发,按字符‘0’或‘1’确定找左孩子或右孩子,直至叶子节点,便求得该子串相应的字符。

四、程序的算法描述1、所用存储结构:typedef struct HfNode{int weight;int parent,lchild,rchild;}HfNode,*HuffmanTree; //动态分配数组存储霍夫曼树typedef char **HuffmanCode; //动态分配数组存储霍夫曼编码表2、程序中各函数的简要说明:(1)void Select(HuffmanTree &HT,int i,int &a,int &b)从前i个节点中选择权值最小的两个节点分别存入a,b中。

哈夫曼树的实验报告1

哈夫曼树的实验报告1

哈夫曼树的实验报告1一、需求分析1、本演示程序实现Haffman编/译码器的作用,目的是为信息收发站提供一个编/译系统,从而使信息收发站利用Haffman编码进行通讯,力求达到提高信道利用率,缩短时间,降低成本等目标。

系统要实现的两个基本功能就是:①对需要传送的数据预先编码;②对从接收端接收的数据进行译码;2、本演示程序需要在终端上读入n个字符(字符型)及其权值(整形),用于建立Huffman树,存储在文件hfmanTree.txt中;如果用户觉得不够清晰还可以打印以凹入表形式显示的Huffman树;3、本演示程序根据建好的Huffman树,对文件的文本进行编码,结果存入文件CodeFile中;然后利用建好的Huffman树将文件CodeFile中的代码进行译码,结果存入文件TextFile中;最后在屏幕上显示代码(每行50个),同时显示对CodeFile中代码翻译后的结果;4、本演示程序将综合使用C++和C语言;5、测试数据:(1)教材例6-2中数据:8个字符,概率分别是0.05,0.29,0.07,0.08,0.14,0.23,0.03,0.11,可将其的权值看为5,29,7,8,14,23,3,11(2)用下表给出的字符集和频度的实际统计数据建立Haffman树,并实现以下报文的编码和一、概要设计1、设定哈夫曼树的抽象数据类型定义ADT Huffmantree{数据对象:D={a i| a i∈Charset,i=1,2,3,……n,n≥0}数据关系:R1={< a i-1, a i >| a i-1, a i∈D, i=2,3,……n}基本操作:Initialization(&HT,&HC,w,n,ch)操作结果:根据n个字符及其它们的权值w[i],建立Huffman树HT,用字符数组ch[i]作为中间存储变量,最后字符编码存到HC中;Encodeing(n)操作结果:根据建好的Huffman树,对文件进行编码,编码结果存入到文件CodeFile 中Decodeing(HT,n)操作结果:根据已经编译好的包含n个字符的Huffman树HT,将文件的代码进行翻译,结果存入文件T extFile中} ADT Huffmantree1)主程序模块void main(){输入信息,初始化;选择需要的操作;生成Huffman树;执行对应的模块程序;输出结果;}2)编码模块——根据建成的Huffman树对文件进行编码;3)译码模块——根据相关的Huffman树对编码进行翻译;各模块的调用关系如图所示二、详细设计1、树类型定义typedef struct {unsigned int weight; //权值char ch1; //储存输入的字符unsigned int parent,lchild,rchild;}HTNode,*HuffmanTree;2、编码类型定义typedef char **HuffmanCode;哈夫曼编译器的基本操作设置如下Initialization(HuffmanTree &HT,HuffmanCode &HC,int *w,int &n,char *ch) //根据输入的n个字符及其它们的权值w[i],建立Huffman树HT,用字符数组ch[i]作为中间存储变量存储编码,最后转存到HC中;Encodeing(int n)//根据建好的包含n个字符的Huffman树,对文件进行编码,编码结果存入到文件CodeFile中Decodeing(HuffmanTree HT,int n)//根据已经编译好的包含n个字符的Huffman树HT,对文件的代码进行翻译,结果存入文件TextFile中基本操作操作的算法主函数及其他函数的算法void select(HuffmanTree HT,int n,int &s1,int &s2){ //依次比较,从哈夫曼树的中parent为0的节点中选择出两个权值最小的if(!HT[i].parent&&!HT[S1]&&!HT[S2]){if(HT[i].weight<ht[s1].weight){< p="">s2=s1; s1=i;}else if(HT[i].weight<ht[s2].weight&&i!=s1)< p=""> s2=i;}3、函数的调用关系图三、调试分析Encodeing Decoding Print PrintTreeInitialization1、本次实习作业最大的难点就是文件的读和写,这需要充分考虑到文件里面的格式,例如空格,换行等等,由于不熟悉C++语言和C语言的文件的输入和输出,给编程带来了很大的麻烦;2、原本计划将文本中的换行格式也进行编码,也由于设计函数比较复杂,而最终放弃;3、一开始考虑打印哈夫曼树的凹入表时是顺向思维,希望通过指针的顺序变迁来实现打印,但问题是从根结点到叶子结点的指针不是顺序存储的,所以未能成功,后来查找相关资料,最终利用递归的方法解决问题;4、程序中的数组均采用了动态分配的方法定义,力求达到减少空间的浪费;5、时间的复杂度主要是由查树这个步骤决定,因为无论是编码还是译码都需要对Huffman树进行查找和核对,但考虑到英文字母和空格也就是27个字符,影响不是很大;6、程序无论在屏幕显示还有文件存储方面都达到了不错的效果;7、程序不足的地方就是在文件文本格式方面处理得还是不够,或许可以通过模仿WORD的实现来改善。

哈夫曼树_实验报告

哈夫曼树_实验报告

一、实验目的1. 理解哈夫曼树的概念及其在数据结构中的应用。

2. 掌握哈夫曼树的构建方法。

3. 学习哈夫曼编码的原理及其在数据压缩中的应用。

4. 提高编程能力,实现哈夫曼树和哈夫曼编码的相关功能。

二、实验原理哈夫曼树(Huffman Tree)是一种带权路径长度最短的二叉树,又称为最优二叉树。

其构建方法如下:1. 将所有待编码的字符按照其出现的频率排序,频率低的排在前面。

2. 选择两个频率最低的字符,构造一棵新的二叉树,这两个字符分别作为左右子节点。

3. 计算新二叉树的频率,将新二叉树插入到排序后的字符列表中。

4. 重复步骤2和3,直到只剩下一个节点,这个节点即为哈夫曼树的根节点。

哈夫曼编码是一种基于哈夫曼树的编码方法,其原理如下:1. 从哈夫曼树的根节点开始,向左子树走表示0,向右子树走表示1。

2. 每个叶子节点对应一个字符,记录从根节点到叶子节点的路径,即为该字符的哈夫曼编码。

三、实验内容1. 实现哈夫曼树的构建。

2. 实现哈夫曼编码和译码功能。

3. 测试实验结果。

四、实验步骤1. 创建一个字符数组,包含待编码的字符。

2. 创建一个数组,用于存储每个字符的频率。

3. 对字符和频率进行排序。

4. 构建哈夫曼树,根据排序后的字符和频率,按照哈夫曼树的构建方法,将字符和频率插入到哈夫曼树中。

5. 实现哈夫曼编码功能,遍历哈夫曼树,记录从根节点到叶子节点的路径,即为每个字符的哈夫曼编码。

6. 实现哈夫曼译码功能,根据哈夫曼编码,从根节点开始,按照0和1的路径,找到对应的叶子节点,即为解码后的字符。

7. 测试实验结果,验证哈夫曼编码和译码的正确性。

五、实验结果与分析1. 构建哈夫曼树根据实验数据,构建的哈夫曼树如下:```A/ \B C/ \ / \D E F G```其中,A、B、C、D、E、F、G分别代表待编码的字符。

2. 哈夫曼编码根据哈夫曼树,得到以下字符的哈夫曼编码:- A: 00- B: 01- C: 10- D: 11- E: 100- F: 101- G: 1103. 哈夫曼译码根据哈夫曼编码,对以下编码进行译码:- 00101110111译码结果为:BACGACG4. 实验结果分析通过实验,验证了哈夫曼树和哈夫曼编码的正确性。

(完整word版)哈夫曼树实验报告

(完整word版)哈夫曼树实验报告

实验报告1、实验目的:(1)理解哈夫曼树的含义和性质。

(2)掌握哈夫曼树的存储结构以及描述方法。

(3)掌握哈夫曼树的生成方法。

(4)掌握哈夫曼编码的一般方法,并理解其在数据通讯中的应用.2、实验内容:哈夫曼树与哈弗曼编码、译码a。

问题描述:哈夫曼问题的提出可以参考教材P。

145。

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

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

算法提示:参见教材P.147—148算法6.12、6。

13的描述.3、实验要求:建立哈夫曼树,实现编码,译码。

错误!.初始化(Initialization)。

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

○2。

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

○3.译码(Decoding ).利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件T extFile 中。

错误!.输出代码文件(Print).将文件CodeFile以紧凑格式显示在终端上,每行50个代码。

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

错误!。

输出哈夫曼树(TreePrinting).将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。

测试数据:设权值c= (a,b, c, d , e, f,g,h)w=(5,29,7,8,14,23,3,11),n=8。

按照字符‘0’或‘1’确定找左孩子或右孩子,则权值对应的编码为:5:0001,29:11,7:1110,8:111114:110,23:01,3:0000,11:001。

哈夫曼树编码实验报告

哈夫曼树编码实验报告

哈夫曼树编码实验报告哈夫曼树编码实验报告引言:哈夫曼树编码是一种常用的数据压缩算法,通过对数据进行编码和解码,可以有效地减小数据的存储空间。

本次实验旨在探究哈夫曼树编码的原理和应用,并通过实际案例验证其有效性。

一、哈夫曼树编码原理哈夫曼树编码是一种变长编码方式,根据字符出现的频率来确定不同字符的编码长度。

频率较高的字符编码较短,频率较低的字符编码较长,以达到最佳的数据压缩效果。

1.1 字符频率统计首先,需要对待编码的数据进行字符频率统计。

通过扫描数据,记录每个字符出现的次数,得到字符频率。

1.2 构建哈夫曼树根据字符频率构建哈夫曼树,频率较低的字符作为叶子节点,频率较高的字符作为父节点。

构建哈夫曼树的过程中,需要使用最小堆来维护节点的顺序。

1.3 生成编码表通过遍历哈夫曼树,从根节点到每个叶子节点的路径上的左右分支分别赋予0和1,生成对应的编码表。

1.4 数据编码根据生成的编码表,将待编码的数据进行替换,将每个字符替换为对应的编码。

编码后的数据长度通常会减小,实现了数据的压缩。

1.5 数据解码利用生成的编码表,将编码后的数据进行解码,恢复原始数据。

二、实验过程与结果为了验证哈夫曼树编码的有效性,我们选择了一段文本作为实验数据,并进行了以下步骤:2.1 字符频率统计通过扫描文本,统计每个字符出现的频率。

我们得到了一个字符频率表,其中包含了文本中出现的字符及其对应的频率。

2.2 构建哈夫曼树根据字符频率表,我们使用最小堆构建了哈夫曼树。

频率较低的字符作为叶子节点,频率较高的字符作为父节点。

最终得到了一棵哈夫曼树。

2.3 生成编码表通过遍历哈夫曼树,我们生成了对应的编码表。

编码表中包含了每个字符的编码,用0和1表示。

2.4 数据编码将待编码的文本数据进行替换,将每个字符替换为对应的编码。

编码后的数据长度明显减小,实现了数据的压缩。

2.5 数据解码利用生成的编码表,将编码后的数据进行解码,恢复原始文本数据。

数据结构实验三哈夫曼树实验报告

数据结构实验三哈夫曼树实验报告

题目:哈夫曼编/译码器一、题目要求:写一个哈夫曼码的编/译码系统,要求能对要传输的报文进行编码和解码。

构造哈夫曼树时,权值小的放左子树,权值大的放右子树,编码时右子树编码为1,左子树编码为0.二、概要设计:数据结构:typedef struct{int bit[MAXBIT];int start;} HCodeType; /* 编码结构体 */typedef struct{int weight;int parent;int lchild;int rchild;char value;} HNode; /* 结点结构体 */函数:void DEMONHuffmanTree (HNode HuffNode[MAXNODE], int n)作用:构造一个哈夫曼树,并循环构建int main ()作用:运用已经构建好的哈弗曼树,进行节点的处理,达到成功解码编译三、详细设计:哈夫曼树的建立:void DEMONHuffmanTree (HNode HuffNode[MAXNODE], int n){int i = 0, j, m1, m2, x1, x2;char x;/* 初始化存放哈夫曼树数组 HuffNode[] 中的结点 */while (i<n){HuffNode[i].weight = 0;//权值HuffNode[i].parent =-1;HuffNode[i].lchild =-1;HuffNode[i].rchild =-1;scanf("%c",&x);scanf("%c",&HuffNode[i].value); //实际值,可根据情况替换为字母i++;}/* 输入 n 个叶子结点的权值 */scanf("%c",&x);for(i=0;i<n;i++){scanf ("%d", &HuffNode[i].weight);}for (i=n; i<2*n-1; i++){HuffNode[i].weight = 0;//权值HuffNode[i].parent =-1;HuffNode[i].lchild =-1;HuffNode[i].rchild =-1;HuffNode[i].value=i;}/* 循环构造 Huffman 树 */for (i=0; i<n-1; i++){m1=m2=MAXQZ; // m1、m2中存放两个无父结点且结点权值最小的两个结点x1=x2=0;//找出所有结点中权值最小、无父结点的两个结点,并合并之为一颗二叉树 for (j=0; j<n+i; j++){if (HuffNode[j].weight < m1 && HuffNode[j].parent==-1){m2=m1;//m1中是最小x2=x1;m1=HuffNode[j].weight;x1=j;}else if (HuffNode[j].weight < m2 && HuffNode[j].parent==-1){m2=HuffNode[j].weight;x2=j;}} /* end for *//* 设置找到的两个子结点 x1、x2 的父结点信息 */HuffNode[x2].parent = n+i;HuffNode[n+i].weight = HuffNode[x1].weight + HuffNode[x2].weight; HuffNode[n+i].lchild = x1;HuffNode[n+i].rchild = x2;}}叶子节点的哈夫曼编码的保存:for (j=cd.start+1; j<n; j++)HuffCode[i].bit[j] = cd.bit[j];HuffCode[i].start = cd.start;主函数展示:int main(){HNode HuffNode[MAXNODE];HCodeType HuffCode[MAXLEAF],cd;int i, j, c, p, n,k=0;char wen[100];char z;scanf ("%d", &n);HuffmanTree (HuffNode, n);for (i=0; i < n; i++){cd.start = n-1;c = i;p = HuffNode[c].parent;while (p != -1) /* 父结点存在 */{if (HuffNode[p].lchild == c)cd.bit[cd.start] = 0;elsecd.bit[cd.start] = 1;cd.start--; /* 求编码的低一位 */c=p;p=HuffNode[c].parent; /* 设置下一循环条件 */} /* end while */for (j=cd.start+1; j<n; j++)HuffCode[i].bit[j] = cd.bit[j];} /* end for */z=getchar();z=getchar();for(;z!='\n';z=getchar()){wen[k++]=z;for(i=0;i<n;i++){if(z==HuffNode[i].value){for (j=HuffCode[i].start+1; j < n; j++)printf ("%d", HuffCode[i].bit[j]);break;}else;}}printf("\n");for(i=0;i<k;i++){printf("%c",wen[i]);}printf("\n");return 0;}四、调试分析与心得体会:虽然哈夫曼树的建立有书上的参考,但是实际写整个代码的时候还是问题重重。

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

数据结构实验报告实验名称:实验三树学生姓名:班级:班内序号:学号:日期:2012年12月7号1、实验要求利用二叉树结构实现赫夫曼编/解码器。

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

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

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

5、打印(Print):以直观的方式打印赫夫曼树(选作)6、计算输入的字符串编码前和编码后的长度,并进行分析,讨论赫夫曼编码的压缩效果。

测试数据:I love data Structure, I love Computer。

I will try my best to study data Structure.提示:1、用户界面可以设计为“菜单”方式:能够进行交互。

2、根据输入的字符串中每个字符出现的次数统计频度,对没有出现的字符一律不用编码。

2、程序分析2.1存储结构(1)二叉树template <class T>class BiTree{public:BiTree(); //构造函数,其前序序列由键盘输入~BiTree(void); //析构函数BiNode<T>* Getroot(); //获得指向根结点的指针protected:BiNode<T> *root; //指向根结点的头指针};//声明类BiTree及定义结构BiNodeData:二叉树是由一个根结点和两棵互不相交的左右子树构成。

二叉树中的结点具有相同数据类型及层次关系。

示意图:lchild parent rchild(2)静态三叉链表struct HNode//哈夫曼树的静态三叉链表 {unsigned int weight; //结点权值unsigned int parent; //双亲指针unsigned int Lchild; //左孩子指针unsigned int Rchild; //右孩子指针};示意图:(3) 编码表的节点结构 struct HCode //字符及其编码结构{char data;char code[100];};示意图:2.2关键算法分析一:关键算法(一)初始化函数void Huffman::Init(int a[],int n)(1)算法自然语言1.创建一个长度为2*n -1的三叉链表2.将存储字符及其权值的链表中的字符逐个写入三叉链表的前n个结点的data域,并将对应结点的孩子域和双亲域赋为空3.从三叉链表的第n个结点开始,i=n3.1从存储字符及其权值的链表中取出两个权值最小的结点x,y,记录其下标x,y。

3.2将下标为x和y的哈夫曼树的结点的双亲设置为第i个结点3.3将下标为x的结点设置为i结点的左孩子,将下标为y的结点设置为i结点的右孩子,i结点的权值为x结点的权值加上y结点的权值,i结点的双亲设置为空4. 根据哈夫曼树创建编码表(2)源代码void Huffman::Init(int a[],int n) //创建哈夫曼树{ //二叉树只有度为和度为的结点时,总结点数为(n-1)个HTree=new HNode[2*n-1]; //根据权重数组a[1—>n]初始化哈夫曼树int i,x,y;for(i=0;i<n;i++) //n个叶子结点{HTree[i].weight=a[i];HTree[i].Lchild=-1;HTree[i].Rchild=-1;HTree[i].parent=-1;}for(int i=n;i<2*n-1;i++) //开始建哈夫曼树,从底层向顶层搭建{SelectMin(HTree,i,x,y); //从--(i-1)中选出两个权值最小的结点HTree[x].parent=i;HTree[y].parent=i; //左右孩子权值相加为父结点的权值HTree[i].weight=HTree[x].weight+HTree[y].weight;HTree[i].Lchild=x;HTree[i].Rchild=y;HTree[i].parent=-1;}}(3)时间复杂度在选取两个权值最小的结点的函数中要遍历链表,时间复杂度为O(n),故该函数的时间复杂度为O(n^2)(二)统计字符出现频度的代码(1)算法自然语言①用cin.getline()函数获取一段字符串。

同时设置一个权值数组weight,以及暂时统计和存放权值的数组s。

②用strlen()函数获取未编码时的字符串长度。

③从字符串的起始位置进行权值统计,即获得str[i]每个字符的ASⅡ编码,并在s[(int)str[i]]数组中进行+1统计,为字符出现一次。

④i进行自加,统计下面字符出现的频度,在相应的数组元素中进行+1统计。

⑤继续循环,直到字符串结束。

(2)源代码(在main()函数中实现)int i,j=0,v;int s[200]={0};int weight[M]; //权值数组cout<<"请输入一段字符串,按回车键结束:"<<endl;cin.getline(str,1000,'\n'); //由用户输入一段字符串cout<<endl;Len1=strlen(str); //得到未编码时的字符串长度for(i=0;str[i]!='\0';i++) //统计每个字符的权值s[(int)str[i]]++; //(int)str[i]为每个字符的ASⅡ编码for(i=0;i<200;i++)if(s[i]!=0) //如果权值不为{c[j]=i; //ASⅡ编码为i的字符写入字符数组c weight[j]=s[i]; //权值s数组赋给权值weight数组j++;}n=j; //叶子结点个数for(v=0;v<n;v++) //循环输出字符权值cout<<c[v]<<"的权值为:"<<weight[v]<<endl;(3)时间复杂度:若输入的字符串长度为n,则时间复杂度为O(n)(三)选择两个最小权值的函数(1)算法自然语言①先暂时将前两个叶子结点作为权值最小的两个结点i1,i2②从第三个叶子结点开始,每一个结点的权值与i1,i2进行比较,如果此结点权值比i1权值要小,则将i1结点赋给i2,此结点赋给i1。

③如果此结点权值比i2要小,此结点赋给i2。

④每进行一次循环,总结点个数-1.(两个结点进行权值合并)⑤继续执行循环,直到循环到根结点,循环结束。

(2)源代码void Huffman::SelectMin(HNode*hTree,int n,int &i1,int &i2){int i,j; //找一个比较的起始值for(i=0;i<n;i++) //找i1{if(hTree[i].parent==-1){i1=i;break;}}i++;for(;i<n;i++) //找i2{ //先让前两个叶子结点分别为i1,i2if(hTree[i].parent==-1){i2=i;break;}}if(hTree[i1].weight>hTree[i2].weight) //i1指向最小的{j=i2;i2=i1;i1=j;}i++;for(;i<n;i++) //开始找最小的两个{if(hTree[i].parent==-1&&hTree[i].weight<hTree[i1].weight){ //如果之后的叶子结点权值小于前两个,那么进行交换i2=i1; //把i1赋给i2i1=i;}else if(hTree[i].parent==-1&&hTree[i].weight<hTree[i2].weight){i2=i; //始终保证i2权值大于i1}}}(3)时间复杂度若输入的字符串长度为n,则时间复杂度为O(n)(四)创建编码表(1)算法自然语言1.生成一个编码表2.从终端结点开始,如果此结点是其父结点的左孩子,则标“0”;如果是其父结点的右孩子,则标“1”。

3.将父结点赋给孩子结点,并将新的孩子结点的父结点作为当前父结点,重复2操作。

4.继续循环,直到根结点,即不满足循环条件时,将编码表的最后一位置0.5.将编码字符逆置。

将编码串的最后一位置换成新编码串的第一位,倒数第二位置换成新编码串的第二位,直到置换完毕。

6.将新的编码串重新赋给编码表。

7.输出字符的哈夫曼编码。

8.循环将字符编码后的长度赋给Len3数组。

(2)源代码void Huffman::CreateTable(char data[],int n){HCodeTable=new HCode[n]; //生成编码表for(int i=0;i<n;i++){HCodeTable[i].data=data[i];int child=i;int parent=HTree[i].parent;int k=0; //从终端结点开始编码,代表每个编码串的长度while(parent!=-1){if(child==HTree[parent].Lchild)HCodeTable[i].code[k]='0'; //左孩子标“0”elseHCodeTable[i].code[k]='1'; //右孩子标“1”k++;child=parent; //向上追溯parent=HTree[child].parent;}HCodeTable[i].code[k]='\0'; //当编码到根结点时循环结束,编码串最后一位置表结束{ //将编码字符逆置char code[M];int u;for(u=0;u<k;u++)code[u]=HCodeTable[i].code[k-u-1];//上述编码串的最后一位变成新的编码表中编码串的第一位for(u=0;u<k;u++)HCodeTable[i].code[u]=code[u]; //将新的编码串重新赋给编码表cout<<c[i]<<"的哈夫曼编码为:";cout<<HCodeTable[i].code<<endl;Len3[i]=k; //每个字符编码后的长度}}}(3)时间复杂度若输入的字符串长度为n,则时间复杂度为O(n)。

相关文档
最新文档