数据结构哈夫曼树的实现
数据结构哈夫曼编码实验报告
![数据结构哈夫曼编码实验报告](https://img.taocdn.com/s3/m/1f8c772d6d85ec3a87c24028915f804d2b16878f.png)
数据结构哈夫曼编码实验报告一、实验目的:通过哈夫曼编、译码算法的实现,巩固二叉树及哈夫曼树相关知识的理解掌握,训练学生运用所学知识,解决实际问题的能力。
二、实验内容:已知每一个字符出现的频率,构造哈夫曼树,并设计哈夫曼编码。
1、从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树。
2、打印每一个字符对应的哈夫曼编码。
3、对从终端读入的字符串进行编码,并显示编码结果。
4、对从终端读入的编码串进行译码,并显示译码结果。
三、实验方案设计:(对基本数据类型定义要有注释说明,解决问题的算法思想描述要完整,算法结构和程序功能模块之间的逻辑调用关系要清晰,关键算法要有相应的流程图,对算法的时间复杂度要进行分析)1、算法思想:(1)构造两个结构体分别存储结点的字符及权值、哈夫曼编码值:(2)读取前n个结点的字符及权值,建立哈夫曼树:(3)根据哈夫曼树求出哈夫曼编码:2、算法时间复杂度:(1)建立哈夫曼树时进行n到1次合并,产生n到1个新结点,并选出两个权值最小的根结点:O(n²);(2)根据哈夫曼树求出哈夫曼编码:O(n²)。
(3)读入电文,根据哈夫曼树译码:O(n)。
四、该程序的功能和运行结果:(至少有三种不同的测试数据和相应的运行结果,充分体现该程序的鲁棒性)1、输入字符A,B,C,D,E,F及其相应权值16、12、9、30、6、3。
2、输入字符F,E,N,G,H,U,I及其相应权值30、12、23、22、12、7、9。
3、输入字符A,B,C,D,E,F,G,H,I,G及其相应权值19、23、25、18、12、67、23、9、32、33。
哈夫曼树的建立及操作
![哈夫曼树的建立及操作](https://img.taocdn.com/s3/m/7253dfcd85868762caaedd3383c4bb4cf7ecb721.png)
哈夫曼树的建立及操作哈夫曼树是一种用于数据压缩的树形数据结构,可以有效地压缩数据并减小存储空间。
本文将介绍哈夫曼树的建立方法和相关操作。
一、哈夫曼树的建立方法:1.首先,我们需要统计给定数据中每个字符出现的频率。
频率越高的字符将被赋予较短的编码,从而实现数据的压缩。
可以使用一个字典或哈希表来记录字符及其频率。
2.创建一个包含所有字符频率的节点列表。
每个节点包含一个字符及其对应的频率。
3.排序节点列表,按照频率从小到大的顺序进行排序。
4.创建一个空的二叉树,并将频率最低的两个节点作为子节点,合并为一个新的节点。
新节点的频率为两个子节点的频率之和。
将这个新节点插入到节点列表中。
5.从节点列表中移除原先的两个子节点,插入新节点。
保持列表的有序性。
6.重复步骤4和5,直到节点列表中只剩下一个节点。
7.最后剩下的节点即为哈夫曼树的根节点。
二、哈夫曼树的操作:1.获取哈夫曼编码:根据哈夫曼树的结构,可以通过遍历树的路径来获取每个字符的编码。
左子树表示0,右子树表示1、从根节点出发,依次遍历所有叶子节点,记录下每个字符对应的路径即可得到编码。
2.数据压缩:将原始数据中的每个字符替换为对应的哈夫曼编码,从而实现数据压缩。
根据频率,越常见的字符编码越短,可以大幅减小数据存储的空间。
3.数据解压:使用相同的哈夫曼树,将压缩后的二进制编码解码为原始字符,从而还原数据。
4. 哈夫曼树的存储和传输:为了实现数据的压缩和解压缩,哈夫曼树需要存储和传输。
可以使用二进制格式存储树的结构和频率信息,并在解压缩时重新构建树。
还可以考虑使用霍夫曼编码的变种,如Adaptive Huffman Coding(自适应哈夫曼编码),使得树结构可以随着数据的变化进行更高效的编码和解码。
总结:哈夫曼树是一种用于数据压缩的树形数据结构,可以通过统计字符频率来生成树,并生成对应的编码。
通过编码,可以实现原始数据的高效压缩和解压缩。
在实际应用中,哈夫曼树被广泛应用于数据压缩,如文件压缩、图像压缩等。
数据结构 课程设计之哈夫曼编码
![数据结构 课程设计之哈夫曼编码](https://img.taocdn.com/s3/m/6cc08612ae45b307e87101f69e3143323968f58d.png)
(一) 哈夫曼树的设计思想对于一组具有确定权值的叶子结点可以构造出多个具有不同带权路径长度的二叉树,其中具有最小带权路径长度的二叉树称作哈夫曼树或者最优二叉树。
首先给定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:刚开始不知道如何建一个好树,因为我开始试着建了几个二叉树,不知道什么原因运行的时候那编码总是不对,跟在草稿纸上自己画的那个二叉树总是不相符,就找原因。
哈夫曼树_实验报告
![哈夫曼树_实验报告](https://img.taocdn.com/s3/m/bee43899ba4cf7ec4afe04a1b0717fd5370cb264.png)
一、实验目的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. 实验结果分析通过实验,验证了哈夫曼树和哈夫曼编码的正确性。
哈夫曼树设计性实验报告
![哈夫曼树设计性实验报告](https://img.taocdn.com/s3/m/5a860fb569dc5022aaea0084.png)
专业:计算机科学与技术年级/班级:10级2011—2012学年第一学期
课程名称
数据结构
指导教师
王岁花
本组成员
学号姓名
1008114082左雪敬
实验地点
215机房
实验时间
ห้องสมุดไป่ตู้第12、13、14周
项目名称
哈夫曼编/译码系统的设计与实现
实验类型
设计性
一、实验目的
1:理解哈夫曼树的特征及其应用;在对哈夫曼树进行理解的基础上,构造哈夫曼树,并用构造的哈夫曼树进行编码和译码;通过该实验,使学生对数据结构的应用有更深层次的理解。
2:结果要求达到输入一串字符可以对应显示相应的编码。
二、实验仪器或设备:
一台微型计算机
三、总体设计(设计原理、设计方案及流程等)
1:总体设计
构建整体框架选择程序需要使用的变量以及算法
编码译码。
四、实验步骤(包括主要步骤、代码分析等)
五、结果分析与总结
教师签名:
年月日
数据结构哈夫曼树例题
![数据结构哈夫曼树例题](https://img.taocdn.com/s3/m/40884f3e30b765ce0508763231126edb6f1a76b1.png)
哈夫曼树是一种特殊的树形结构,主要用于数据压缩和编码等领域。
它通过构建最优二叉树,使得树中每个节点的两个子树权值之和最小,从而在编码过程中达到数据压缩的效果。
下面是一个使用Python实现哈夫曼树的例题:```pythonclass Node:def __init__(self, frequency):self.frequency = frequencyself.left = Noneself.right = Nonedef calculate_frequency(file_data):frequency_map = {}for char in file_data:if char not in frequency_map:frequency_map[char] = 0frequency_map[char] += 1return frequency_mapdef huffman_tree(frequency_map):queue = [Node(frequency) for frequency in frequency_map.values()]while len(queue) > 1:node1 = queue.pop(0)node2 = queue.pop(0)merged = Node(node1.frequency + node2.frequency)merged.left = node1merged.right = node2queue.append(merged)return queue[0] # 返回根节点def encode(huffman_tree, file_data):result = ""for char in file_data:node = huffman_tree.find(char) # 查找对应节点result += chr(int(node.weight) + ord(' ')) # 将权值转化为字符,添加到结果中return resultdef decode(huffman_tree):return huffman_tree.left # 直接使用左子树解码,可以得到原数据```解题思路:1. 首先需要统计文件的字符频率,构造一个字符到频率的映射,也就是构建哈夫曼树的节点。
数据结构哈夫曼树课件
![数据结构哈夫曼树课件](https://img.taocdn.com/s3/m/345a6b6eec630b1c59eef8c75fbfc77da26997a4.png)
总结词
优化、提升
详细描述
基于哈夫曼树的网络流量分类算法的优化策 略主要从以下几个方面进行优化和提升:一 是优化哈夫曼树的构造算法,提高树的构造 效率和准确性;二是利用多级哈夫曼编码技 术,降低编码和解码的时间复杂度;三是引 入机器学习算法,对网络流量特征进行自动
提取和分类,进一步提升分类准确率。
THANKS
基于堆排序的构造算法
总结词:堆排序是一 种基于比较的排序算 法,它利用了堆这种 数据结构的特点,能 够在O(nlogn)的时间 内完成排序。在哈夫 曼树的构造中,堆排 序可以用来找到每个 节点的父节点,从而 构建出哈夫曼树。
详细描述:基于堆排 序的构造算法步骤如 下
1. 定义一个最大堆, 并将每个节点作为一 个独立的元素插入到 堆中。每个元素包含 了一个节点及其权值 。
哈夫曼编码的基本概念
哈夫曼编码是一种用于无损数据压缩的熵编码算法,具有较高的编码效率和较低的 编码复杂度。
它利用了数据本身存在的冗余和相关性,通过构建最优的前缀编码来实现高效的数 据压缩。
哈夫曼编码是一种可变长编码,其中每个符号的编码长度取决于它在输入序列中出 现的频率。
哈夫曼编码的实现方法
构建哈夫曼树
节ቤተ መጻሕፍቲ ባይዱ。
优化编码长度
在分配码字时,通过一些策略优化 编码长度,例如给高频符号更短的 码字。
可变长度编码
为了提高压缩比,可以使用可变长 度编码,即对于高频符号赋予更短 的码字,对于低频符号赋予更长的 码字。
04
哈夫曼树在数据压 缩中的应用
基于哈夫曼编码的数据压缩算法
哈夫曼编码是一种可变长度的 编码方式,通过统计数据的出 现频率来构建哈夫曼树,实现 数据压缩。
数据结构哈夫曼编码实验报告
![数据结构哈夫曼编码实验报告](https://img.taocdn.com/s3/m/5014c4c5aff8941ea76e58fafab069dc5022471f.png)
数据结构哈夫曼编码实验报告【正文】1.实验目的本实验旨在研究哈夫曼编码的原理和实现方法,通过实验验证哈夫曼编码在数据压缩中的有效性,并分析其应用场景和优缺点。
2.实验原理2.1 哈夫曼编码哈夫曼编码是一种无损数据压缩算法,通过根据字符出现的频率构建一颗哈夫曼树,将频率较高的字符用较短的编码表示,频率较低的字符用较长的编码表示。
哈夫曼编码的编码表是唯一的,且能够实现前缀编码,即一个编码不是另一个编码的前缀。
2.2 构建哈夫曼树构建哈夫曼树的过程如下:1) 将每个字符及其频率作为一个节点,构建一个节点集合。
2) 每次从节点集合中选择出现频率最低的两个节点,构建一个新节点,并将这两个节点从集合中删除。
3) 将新节点加入节点集合。
4) 重复以上步骤,直到节点集合中只有一个节点,这个节点就是哈夫曼树的根节点。
2.3 编码过程根据哈夫曼树,对每个字符进行编码:1) 从根节点开始,根据左子树为0,右子树为1的规则,将编码依次加入编码表。
2) 对于每个字符,根据编码表获取其编码。
3) 将编码存储起来,得到最终的编码序列。
3.实验步骤3.1 数据读取与统计从输入文件中读取字符序列,并统计各个字符的频率。
3.2 构建哈夫曼树根据字符频率构建哈夫曼树。
3.3 构建编码表根据哈夫曼树,构建每个字符的编码表。
3.4 进行编码根据编码表,对输入的字符序列进行编码。
3.5 进行解码根据哈夫曼树,对编码后的序列进行解码。
4.实验结果与分析4.1 压缩率分析计算原始数据和压缩后数据的比值,分析压缩率。
4.2 编码效率分析测试编码过程所需时间,分析编码效率。
4.3 解码效率分析测试解码过程所需时间,分析解码效率。
4.4 应用场景分析分析哈夫曼编码在实际应用中的优势和适用场景。
5.结论通过本次实验,我们深入了解了哈夫曼编码的原理和实现方法,实践了哈夫曼编码的过程,并对其在数据压缩中的有效性进行了验证。
实验结果表明,哈夫曼编码能够实现较高的压缩率和较高的编解码效率。
数据结构哈夫曼树编码
![数据结构哈夫曼树编码](https://img.taocdn.com/s3/m/7de64d17dc36a32d7375a417866fb84ae45cc3c1.png)
数据结构哈夫曼树编码一、引言二、哈夫曼树的定义1. 节点的概念2. 哈夫曼树的定义三、哈夫曼编码的概念1. 编码方式2. 码长和平均码长四、哈夫曼编码的实现方法1. 构建哈夫曼树a. 构建思路及步骤b. 构建示例图解2. 编码过程a. 编码步骤及示例图解b. 编码实现代码示例3. 解码过程a. 解码步骤及示例图解b. 解码实现代码示例五、哈夫曼编码的优缺点1. 优点2. 缺点六、应用实例七、总结一、引言:随着信息技术的飞速发展,数据处理已经成为当今社会中一个不可或缺的部分。
在数据处理中,如何高效地压缩数据是一个非常重要的问题。
而哈夫曼树编码作为一种高效的压缩算法,在数据传输和存储方面有着广泛应用。
二、哈夫曼树的定义:1. 节点的概念:哈夫曼树是一种二叉树,由根节点、左子树和右子树组成。
每个节点可以有零个或两个子节点。
叶子节点是指没有子节点的节点,而非叶子节点则至少有一个子节点。
2. 哈夫曼树的定义:哈夫曼树是一种特殊的二叉树,它的所有叶子节点都带有权值。
对于任意一个哈夫曼树,将其所有叶子节点按照权值从小到大排列,则可得到一组序列W={w1,w2,...,wn}。
哈夫曼树的构建过程就是将这组序列转化为一棵二叉树。
三、哈夫曼编码的概念:1. 编码方式:哈夫曼编码是一种前缀编码方式,即每个字符的编码都不是其他字符编码的前缀。
2. 码长和平均码长:对于一个字符c,其在哈夫曼编码中所占用的位数称为其码长Lc。
而整个字符串的平均码长Lavg则是所有字符在哈夫曼编码中所占用位数之和除以字符串长度n。
四、哈夫曼编码的实现方法:1. 构建哈夫曼树a. 构建思路及步骤:(1)将所有字符按照权值从小到大排序,构成初始节点集合。
(2)从节点集合中选出两个权值最小的节点作为左右子节点,构建一棵新的二叉树,并将该二叉树的根节点插入到节点集合中。
(3)重复步骤2,直到只剩下一个节点为止。
b. 构建示例图解:2. 编码过程a. 编码步骤及示例图解:(1)遍历哈夫曼树,对于每个叶子节点记录其路径上所有非叶子节点的左右分支信息,用0表示左分支,用1表示右分支。
数据结构课程设计实验报告哈夫曼
![数据结构课程设计实验报告哈夫曼](https://img.taocdn.com/s3/m/264c682caf1ffc4ffe47acb9.png)
数据结构课程设计实验报告哈夫曼树的应用计算机学院信管专业数据结构课程设计题目:哈夫曼树的应用班级:姓名:学号:同组人姓名:起迄日期:课程设计地点:指导教师:完成日期:2012年12月目录一、需求分析 (3)二、概要设计 (4)三、详细设计 (6)四、调试分析和测试结果 (7)五、心得体会和总结 (10)六、参考文献 (10)七、附录 (11)一、需求分析(一)实验要求要求用到数据结构课上学到的线性表的知识,所以就要充分而清晰的理解关于线性表的知识。
要求实现的基本功能很简单,只有删除和插入,增加功能也不过是加上修改。
这些在数据结构课上已经讲过,只要能够理解关于线性表的几个相关的基本算法就可以了。
问题是将输入的信息保存入文件和从文件输出。
这里基本是自学的内容,而且要考虑到是否要自行选择保存的磁盘。
综上,做这个课题,要具备的知识就是线性表的基本算法,文件的保存和读取算法,必要的C或者C++知识(本次我将使用C++实现),以及丰富的程序调适经验。
(二)实验任务一个完整的系统应具有以下功能:功能1.从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树并将它存于文件hfmTree中.将已在内存中的哈夫曼树以直观的方式(比如树)显示在终端上;功能2.利用已经建好的哈夫曼树(如不在内存,则从文件htmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中,并输出结果,将文件CodeFile以紧凑格式先是在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件CodePrint中。
功能3.利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中,并输出结果。
(三)实验步骤分步实施:1)初步完成总体设计,搭好框架,确定人机对话的界面,确定函数个数;2)完成最低要求:完成功能1;3)进一步要求:完成功能2和3。
有兴趣的同学可以自己扩充系统功能。
数据结构——哈夫曼(Huffman)树+哈夫曼编码
![数据结构——哈夫曼(Huffman)树+哈夫曼编码](https://img.taocdn.com/s3/m/51df2e94ed3a87c24028915f804d2b160b4e86b5.png)
数据结构——哈夫曼(Huffman)树+哈夫曼编码前天acm实验课,⽼师教了⼏种排序,抓的⼀套题上有⼀个哈夫曼树的题,正好之前离散数学也讲过哈夫曼树,这⾥我就结合课本,整理⼀篇关于哈夫曼树的博客。
哈夫曼树的介绍Huffman Tree,中⽂名是哈夫曼树或霍夫曼树,它是最优⼆叉树。
定义:给定n个权值作为n个叶⼦结点,构造⼀棵⼆叉树,若树的带权路径长度达到最⼩,则这棵树被称为哈夫曼树。
这个定义⾥⾯涉及到了⼏个陌⽣的概念,下⾯就是⼀颗哈夫曼树,我们来看图解答。
(01) 路径和路径长度定义:在⼀棵树中,从⼀个结点往下可以达到的孩⼦或孙⼦结点之间的通路,称为路径。
通路中分⽀的数⽬称为路径长度。
若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。
例⼦:100和80的路径长度是1,50和30的路径长度是2,20和10的路径长度是3。
(02) 结点的权及带权路径长度定义:若将树中结点赋给⼀个有着某种含义的数值,则这个数值称为该结点的权。
结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。
例⼦:节点20的路径长度是3,它的带权路径长度= 路径长度 * 权 = 3 * 20 = 60。
(03) 树的带权路径长度定义:树的带权路径长度规定为所有叶⼦结点的带权路径长度之和,记为WPL。
例⼦:⽰例中,树的WPL= 1*100 + 2*50 +3*20 + 3*10 = 100 + 100 + 60 + 30 = 290。
⽐较下⾯两棵树上⾯的两棵树都是以{10, 20, 50, 100}为叶⼦节点的树。
左边的树WPL=2*10 + 2*20 + 2*50 + 2*100 = 360 右边的树WPL=350左边的树WPL > 右边的树的WPL。
你也可以计算除上⾯两种⽰例之外的情况,但实际上右边的树就是{10,20,50,100}对应的哈夫曼树。
⾄此,应该堆哈夫曼树的概念有了⼀定的了解了,下⾯看看如何去构造⼀棵哈夫曼树。
数据结构哈夫曼编码
![数据结构哈夫曼编码](https://img.taocdn.com/s3/m/10013f1ebf23482fb4daa58da0116c175e0e1e4f.png)
数据结构哈夫曼编码
哈夫曼编码是一种用于数据压缩的算法,它基于哈夫曼树(HuffmanTree)进行编码。
哈夫曼编码的基本思想是:对于出现频率高的字符,其编码长度较短;而对于出现频率低的字符,其编码长度较长。
这样,通过调整字符的编码长度,可以有效地压缩数据。
哈夫曼编码的具体步骤如下:
1.统计原始数据中每个字符的出现频率。
2.构建哈夫曼树。
在构建过程中,每次将两个权值最小的节点合并,并将它们的权值相加。
同时,将新生成的节点的权值作为新字符的出现频率。
3.根据哈夫曼树生成哈夫曼编码。
对于哈夫曼树中的每个字符,从根节点到该字符所在节点的路径可以形成一个二进制编码。
通常约定左分支标记为0,右分支标记为1。
这样,从根节点到每个叶节点的路径就可以形成一个二进制编码,该编码即为对应字符的哈夫曼编码。
4.使用哈夫曼编码对原始数据进行压缩。
对于原始数据中的每个字符,根据其哈夫曼编码进行编码,最终得到压缩后的数据。
需要注意的是,哈夫曼编码是一种无损压缩算法,即压缩和解压过程中可以完全还原原始数据。
同时,由于哈夫曼编码是基于字符出现频率进行编码的,因此对于出现频率高的字符,其编码长度较短;而对于出现频率低的字符,其编码长度较长。
这样可以有效地减少数据的存储空间,提高数据压缩率。
数据结构实验哈夫曼树及哈夫曼编码c语言
![数据结构实验哈夫曼树及哈夫曼编码c语言](https://img.taocdn.com/s3/m/9222096bec630b1c59eef8c75fbfc77da369975e.png)
数据结构实验报告:哈夫曼树及哈夫曼编码一、实验目的1. 理解哈夫曼树及哈夫曼编码的概念和原理;2. 掌握C语言中哈夫曼树及哈夫曼编码的实现方法;3. 分析和讨论哈夫曼编码在实际应用中的优势和不足。
二、实验内容和步骤1. 哈夫曼树的构建1.1 通过C语言实现哈夫曼树的构建算法;1.2 输入一组权值,按哈夫曼树构建规则生成哈夫曼树;1.3 输出生成的哈夫曼树结构,并进行可视化展示。
2. 哈夫曼编码的实现2.1 设计哈夫曼编码的实现算法;2.2 对指定字符集进行编码,生成哈夫曼编码表;2.3 对给定字符串进行哈夫曼编码,并输出编码结果。
三、实验过程及结果1. 哈夫曼树的构建在C语言中,通过定义结构体和递归算法实现了哈夫曼树的构建。
根据输入的权值,依次选择权值最小的两个节点构建新的父节点,直至构建完成整棵哈夫曼树。
通过调试和可视化展示,确认了程序正确实现了哈夫曼树的构建。
2. 哈夫曼编码的实现经过分析和设计,利用哈夫曼树的特点实现了哈夫曼编码的算法。
根据生成的哈夫曼树,递归地生成字符对应的哈夫曼编码,并输出编码结果。
对指定的字符串进行了编码测试,验证了哈夫曼编码的正确性和有效性。
四、实验结果分析1. 哈夫曼编码在数据传输和存储中具有较高的压缩效率和可靠性,能够有效减少数据传输量和存储空间;2. 哈夫曼树及哈夫曼编码在通信领域、数据压缩和加密等方面有着广泛的应用和重要意义;3. 在实际应用中,哈夫曼编码的构建和解码算法需要较大的时间和空间复杂度,对于大规模数据的处理存在一定的局限性。
五、实验总结通过本次实验,深入理解了哈夫曼树及哈夫曼编码的理论知识,并掌握了C语言中实现哈夫曼树及哈夫曼编码的方法。
对哈夫曼编码在实际应用中的优势和局限性有了更深入的认识,这对今后的学习和工作有着积极的意义。
六、参考文献1. 《数据结构(C语言版)》,严蔚敏赵现军著,清华大学出版社,2012年;2. 《算法导论》,Thomas H. Cormen 等著,机械工业出版社,2006年。
数据结构哈夫曼树实验报告
![数据结构哈夫曼树实验报告](https://img.taocdn.com/s3/m/9b72ae46abea998fcc22bcd126fff705cd175c42.png)
数据结构哈夫曼树实验报告一、实验目的本次实验的主要目的是深入理解和掌握哈夫曼树的数据结构及其相关算法,并通过实际编程实现来提高对数据结构的应用能力和编程技能。
二、实验环境本次实验使用的编程环境为具体编程语言名称,操作系统为具体操作系统名称。
三、实验原理哈夫曼树,又称最优二叉树,是一种带权路径长度最短的二叉树。
其基本原理是通过构建一棵二叉树,使得权值较大的节点距离根节点较近,权值较小的节点距离根节点较远,从而达到带权路径长度最小的目的。
在构建哈夫曼树的过程中,首先需要将所有的节点按照权值从小到大进行排序。
然后,选取权值最小的两个节点作为左右子树,构建一个新的父节点,该父节点的权值为左右子节点权值之和。
重复这个过程,直到所有的节点都被构建到哈夫曼树中。
哈夫曼编码是基于哈夫曼树的一种编码方式。
对于每个叶子节点,从根节点到该叶子节点的路径上,向左的分支编码为 0,向右的分支编码为 1,这样就可以得到每个叶子节点的哈夫曼编码。
四、实验步骤1、定义节点结构体```ctypedef struct HuffmanNode {char data;int weight;struct HuffmanNode left;struct HuffmanNode right;} HuffmanNode;```2、实现节点排序函数```cvoid sortNodes(HuffmanNode nodes, int n) {for (int i = 0; i < n 1; i++){for (int j = 0; j < n i 1; j++){if (nodesj>weight > nodesj + 1>weight) {HuffmanNode temp = nodesj;nodesj = nodesj + 1;nodesj + 1 = temp;}}}}```3、构建哈夫曼树```cHuffmanNode buildHuffmanTree(HuffmanNode nodes, int n) {while (n > 1) {sortNodes(nodes, n);HuffmanNode left = nodes0;HuffmanNode right = nodes1;HuffmanNode parent =(HuffmanNode )malloc(sizeof(HuffmanNode));parent>data ='\0';parent>weight = left>weight + right>weight;parent>left = left;parent>right = right;nodes0 = parent;nodes1 = nodesn 1;n;}return nodes0;}```4、生成哈夫曼编码```cvoid generateHuffmanCodes(HuffmanNode root, int codes, int index) {if (root>left) {codesindex = 0;generateHuffmanCodes(root>left, codes, index + 1);}if (root>right) {codesindex = 1;generateHuffmanCodes(root>right, codes, index + 1);}if (!root>left &&!root>right) {printf("%c: ", root>data);for (int i = 0; i < index; i++){printf("%d", codesi);}printf("\n");}}```5、主函数```cint main(){HuffmanNode nodes5 ={(HuffmanNode )malloc(sizeof(HuffmanNode)),(HuffmanNode )malloc(sizeof(HuffmanNode)),(HuffmanNode )malloc(sizeof(HuffmanNode)),(HuffmanNode )malloc(sizeof(HuffmanNode)),(HuffmanNode )malloc(sizeof(HuffmanNode))};nodes0>data ='A';nodes0>weight = 5;nodes1>data ='B';nodes1>weight = 9;nodes2>data ='C';nodes2>weight = 12;nodes3>data ='D';nodes3>weight = 13;nodes4>data ='E';nodes4>weight = 16;HuffmanNode root = buildHuffmanTree(nodes, 5);int codes100;generateHuffmanCodes(root, codes, 0);return 0;}```五、实验结果与分析通过运行上述程序,得到了每个字符的哈夫曼编码:A: 00B: 01C: 10D: 110E: 111分析实验结果可以发现,权值较小的字符A 和B 对应的编码较短,而权值较大的字符D 和E 对应的编码较长。
数据结构与算法:哈夫曼树
![数据结构与算法:哈夫曼树](https://img.taocdn.com/s3/m/802add7326284b73f242336c1eb91a37f1113243.png)
数据结构与算法:哈夫曼树哈夫曼树给定N个权值作为N个叶⼦结点,构造⼀棵⼆叉树,若该树的带权路径长度达到最⼩,称这样的⼆叉树为最优⼆叉树,也称为哈夫曼树(Huffman Tree)。
哈夫曼树是带权路径长度最短的树,权值较⼤的结点离根较近。
重要概念路径:从⼀个节点到它往下可以达到的节点所经shu过的所有节点,称为两个节点之间的路径路径长度:即两个节点的层级差,如A节点在第⼀层,B节点在第四层,那它们之间的路径长度为4-1=3权重值:为树中的每个节点设置⼀个有某种含义的数值,称为权重值(Weight),权重值在不同算法中可以起到不同的作⽤节点的带权路径长度:从根节点到该节点的路径长度与该节点权重值的乘积树的带权路径长度:所有叶⼦节点的带权路径长度之和,也简称为WPL哈夫曼树判断判断⼀棵树是不是哈夫曼树只要判断该树的结构是否构成最短带权路径。
在下图中3棵同样叶⼦节点的树中带权路径最短的是右侧的树,所以右侧的树就是哈夫曼树。
代码实现案例:将数组{13,7,8,3,29,6,1}转换成⼀棵哈夫曼树思路分析:从哈夫曼树的概念中可以看出,要组成哈夫曼树,权值越⼤的节点必须越靠近根节点,所以在组成哈夫曼树时,应该由最⼩权值的节点开始。
步骤:(1) 将数组转换成节点,并将这些节点由⼩到⼤进⾏排序存放在集合中(2) 从节点集合中取出权值最⼩的两个节点,以这两个节点为⼦节点创建⼀棵⼆叉树,它们的⽗节点权值就是它们的权值之和(3) 从节点集合中删除取出的两个节点,并将它们组成的⽗节点添加进节点集合中,跳到步骤(2)直到节点集合中只剩⼀个节点public class HuffmanTreeDemo {public static void main(String[] args) {int array[] = {13,7,8,3,29,6,1};HuffmanTree huffmanTree = new HuffmanTree();Node root = huffmanTree.create(array);huffmanTree.preOrder(root);}}//哈夫曼树class HuffmanTree{public void preOrder(Node root){if (root == null){System.out.println("哈夫曼树为空,⽆法遍历");return;}root.preOrder();}/*** 创建哈夫曼树* @param array 各节点的权值⼤⼩* @return*/public Node create(int array[]){//先将传⼊的各权值转成节点并添加到集合中List<Node> nodes = new ArrayList<>();for (int value : array){nodes.add(new Node(value));}/*当集合中的数组只有⼀个节点时,即集合内所有节点已经组合完成,剩下的唯⼀⼀个节点即是哈夫曼树的根节点*/while (nodes.size() > 1){//将节点集合从⼩到⼤进⾏排序//注意:如果在节点类没有实现Comparable接⼝,则⽆法使⽤Collections.sort(nodes);//在集合内取出权值最⼩的两个节点Node leftNode = nodes.get(0);Node rightNode = nodes.get(1);//以这两个节点创建⼀个新的⼆叉树,它们的⽗节点的权值即是它们的权值之和Node parent = new Node(leftNode.weight + rightNode.weight);parent.left = leftNode;parent.right = rightNode;//再从集合中删除已经组合成⼆叉树的俩个节点,并把它们俩个的⽗节点加⼊到集合中nodes.remove(leftNode);nodes.remove(rightNode);nodes.add(parent);}//返回哈夫曼树的根节点return nodes.get(0);}}//因为要在节点的集合内,以节点的权值value,从⼩到⼤进⾏排序,所以要实现Comparable<>接⼝class Node implements Comparable<Node>{int weight;//节点的权值Node left;Node right;public Node(int weight) {this.weight = weight;}public void preOrder(){System.out.println(this);if (this.left != null){this.left.preOrder();}if (this.right != null){this.right.preOrder();}}@Overridepublic String toString() {return "Node{" +"weight=" + weight +'}';}@Overridepublic int compareTo(Node o) {return this.weight - o.weight;}}哈夫曼编码定长编码固定长度编码⼀种⼆进制信息的信道编码。
哈夫曼树与哈夫曼树编码实验原理
![哈夫曼树与哈夫曼树编码实验原理](https://img.taocdn.com/s3/m/3e11915e1fd9ad51f01dc281e53a580216fc500e.png)
哈夫曼树与哈夫曼树编码实验原理哈夫曼树(Huffman Tree)是一种用于数据压缩的树形数据结构。
它的主要原理是通过构建一个最优的二叉树来实现编码和解码的过程。
以下是哈夫曼树和哈夫曼编码的实验原理:1. 构建哈夫曼树:- 给定一组需要进行编码的字符及其出现频率。
通常,这个频率信息可以通过统计字符在原始数据中的出现次数来得到。
- 创建一个叶节点集合,每个叶节点包含一个字符及其对应的频率。
- 从叶节点集合中选择两个频率最低的节点作为左右子节点,创建一个新的父节点。
父节点的频率等于左右子节点频率的和。
- 将新创建的父节点插入到叶节点集合中,并将原来的两个子节点从集合中删除。
- 重复上述步骤,直到叶节点集合中只剩下一个节点,即根节点,这个节点就是哈夫曼树的根节点。
2. 构建哈夫曼编码:- 从哈夫曼树的根节点开始,沿着左子树走一步就表示编码的0,沿着右子树走一步表示编码的1。
- 遍历哈夫曼树的每个叶节点,记录从根节点到叶节点的路径,得到每个字符对应的编码。
由于哈夫曼树的构建过程中,频率较高的字符在树中路径较短,频率较低的字符在树中路径较长,因此哈夫曼编码是一种前缀编码,即没有任何一个字符的编码是其他字符编码的前缀。
3. 进行数据压缩:- 将原始数据中的每个字符替换为其对应的哈夫曼编码。
- 将替换后的编码串连接起来,形成压缩后的数据。
4. 进行数据解压缩:- 使用相同的哈夫曼树,从根节点开始,按照压缩数据中的每个0或1进行遍历。
- 当遇到叶节点时,就找到了一个字符,将其输出,并从根节点重新开始遍历。
- 继续按照压缩数据的编码进行遍历,直到所有的编码都解压为字符。
通过构建最优的哈夫曼树和对应的编码表,可以实现高效的数据压缩和解压缩。
频率较高的字符使用较短的编码,从而达到减小数据大小的目的。
而频率较低的字符使用较长的编码,由于其出现频率较低,整体数据大小的增加也相对较小。
哈夫曼树实验报告
![哈夫曼树实验报告](https://img.taocdn.com/s3/m/33c62a02814d2b160b4e767f5acfa1c7ab00821d.png)
一、实验目的1. 理解哈夫曼树的基本概念和构造方法。
2. 掌握哈夫曼编码的原理和实现过程。
3. 通过实验加深对数据结构中树型结构应用的理解。
二、实验原理哈夫曼树(Huffman Tree)是一种带权重的二叉树,用于实现哈夫曼编码。
其基本思想是:将字符按照在数据集中出现的频率进行排序,然后选取两个最小频率的字符合并成一个新节点,其频率为两个字符频率之和,重复此过程,直到只剩下一个节点,即为哈夫曼树的根节点。
哈夫曼编码是一种基于哈夫曼树的编码方法,其原理是将每个字符映射到一个唯一的二进制序列,序列的长度与字符在数据集中出现的频率成反比。
频率越高,编码的长度越短,从而提高信息传输的效率。
三、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发环境:Visual Studio 2019四、实验步骤1. 初始化(1)从数据文件中读取字符及其频率。
(2)构建一个优先队列(最小堆),将字符和频率存储在队列中。
2. 构建哈夫曼树(1)从优先队列中取出两个频率最小的节点,合并成一个新节点,其频率为两个节点频率之和。
(2)将新节点插入优先队列中。
(3)重复步骤(1)和(2),直到优先队列中只剩下一个节点,即为哈夫曼树的根节点。
3. 哈夫曼编码(1)遍历哈夫曼树,从根节点到叶子节点的路径上,左子树表示0,右子树表示1。
(2)将每个叶子节点的字符和对应的编码存储在哈夫曼编码表中。
4. 编码(1)读取待编码的文本。
(2)根据哈夫曼编码表,将文本中的每个字符映射到对应的编码。
(3)将编码序列写入文件。
5. 译码(1)读取编码文件。
(2)从哈夫曼树的根节点开始,根据编码序列的每一位,判断是左子树还是右子树。
(3)当到达叶子节点时,输出对应的字符。
(4)重复步骤(2)和(3),直到编码序列结束。
五、实验结果与分析1. 实验结果(1)成功构建了哈夫曼树,并生成了哈夫曼编码表。
(2)对给定的文本进行了编码和译码,验证了编码的正确性。
哈夫曼树合并有序表最多比较次数
![哈夫曼树合并有序表最多比较次数](https://img.taocdn.com/s3/m/3308bcbf760bf78a6529647d27284b73f2423620.png)
哈夫曼树是一种经典的树形数据结构,它被广泛应用于信息编码和压缩算法中。
哈夫曼树的构建过程是通过合并有序表来实现的,而最多比较次数是衡量哈夫曼树构建效率的重要指标之一。
一、哈夫曼树的构建原理1. 哈夫曼树的定义在介绍哈夫曼树合并有序表最多比较次数之前,需要先了解哈夫曼树的构建原理。
哈夫曼树是一种特殊的二叉树,它的叶子节点对应着待编码的字符或符号,而非叶子节点则是通过合并两个权值最小的节点而得到的新节点。
通过不断地合并和重排,最终得到一棵哈夫曼树,从而实现对字符进行高效编码。
2. 哈夫曼树的构建过程哈夫曼树的构建过程是通过合并有序表来实现的。
将待编码的字符按照其出现频率的大小进行排序,得到一个初始的有序表。
依次选择权值最小的两个节点进行合并,并更新有序表。
不断重复这个过程,直到只剩下一个节点,即得到了完整的哈夫曼树。
二、哈夫曼树合并有序表最多比较次数哈夫曼树合并有序表的最多比较次数是一个重要的性能指标,它直接影响着哈夫曼树的构建效率和编码的质量。
在构建哈夫曼树的过程中,每次选择权值最小的节点进行合并都需要进行比较操作,而最多比较次数则是衡量这一过程的关键指标。
在给定的有序表中,有$n$个节点需要合并,根据哈夫曼树的构建原理可知,合并过程需要进行$(n-1)$次比较。
哈夫曼树合并有序表的最多比较次数可以通过以下公式进行计算:$$N_{\text{max}} = n - 1$$其中,$N_{\text{max}}$表示哈夫曼树合并有序表的最多比较次数,$n$表示给定的有序表中节点的个数。
这个公式的推导过程较为简单,但是却能够有效地帮助我们评估和分析哈夫曼树构建过程的效率。
三、哈夫曼树合并有序表最多比较次数的影响因素1. 节点个数$n$的影响哈夫曼树合并有序表最多比较次数直接依赖于节点个数$n$,因此节点个数的大小对最多比较次数有着显著的影响。
一般来说,节点个数越多,最多比较次数也会相应增加,因为需要进行更多次的合并操作才能得到完整的哈夫曼树。
数据结构哈夫曼树实验报告
![数据结构哈夫曼树实验报告](https://img.taocdn.com/s3/m/cfdb1e106edb6f1aff001fee.png)
2009级数据结构实验报告实验名称:实验3——哈夫曼树学生姓名:陈家斌班级:2009211121班内序号:16学号:09210619日期:2010年12月3日1.实验要求【实验目的】通过选择下面两个题目之一进行实现,掌握如下内容:➢掌握二叉树基本操作的实现方法➢了解赫夫曼树的思想和相关概念➢学习使用二叉树解决实际问题的能力【题目】利用二叉树结构实现赫夫曼编/解码器。
【基本要求】1、初始化(Init):能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立赫夫曼树2、建立编码表(CreateTable):利用已经建好的赫夫曼树进行编码,并将每个字符的编码输出。
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、根据输入的字符串中每个字符出现的次数统计频度,对没有出现的字符一律不用编码。
【代码要求】1、必须要有异常处理,比如删除空链表时需要抛出异常;2、保持良好的编程的风格:➢代码段与段之间要有空行和缩近➢标识符名称应该与其代表的意义一致➢函数名之前应该添加注释说明该函数的功能➢关键代码应说明其功能3、递归程序注意调用的过程,防止栈溢出2. 程序分析【算法实现】程序第一遍统计原数据中各字符出现的频率,利用得到的频率值创建哈夫曼树,并把树的信息保存起来,以便解压时创建同样的哈夫曼树进行解压;第二遍,根据第一遍扫描得到的哈夫曼树进行编码,并把编码后的码字存储。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
typedef char *HuffmanCode; //动态分配数组存储哈夫曼编码表
int m,s1,s2; HuffmanTree HT;
void Select(int n){ //选择两个权值最小的结点
int i,j;
for(i=1;i<=n;i++){
HC[i]=(char *)malloc((n-start)*sizeof(char));
strcpy(HC[i],&cd[start]);
}
free(cd);
}
void PTree(int n){//打印树的结构
int r=2*n-1;
printf("树的结构为(0表示无孩子):\n");
for(;r>0;r--){
HT[i].lchild = s1;
HT[i].rchild = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight;
HT[i].ch=j;
}
//-----从叶子到根逆向求每个字符的哈夫曼编码
cd=(char *)malloc(n*sizeof(char));
printf("输入%d个结点的权值\n",n);
for(i=0;i<n;i++){
scanf("%d",&w[i]);
}
HuffmanCoding(HC,w,n);
puts("\n各结点的哈夫曼编码为:");
for(i=1;i<=n;i++){
c=(char)i+64;
cout<<c<<'('<<w[i-1]<<')'<<HC[i]<<endl;
cout<<HT[r].lchild<<"<--"<<r<<"-->"<<HT[r].rchild<<endl;
}
}
void trans(){//译码
int i=m;
char a;
printf("输入0/1进行译码,输入'!'进行编码");
cin>>a;
while(a=='0'||a=='1'){
if(a=='0')
s1=i;
}
}
for(j=1;j<=n;j++){
if((HT[s2].weight>HT[j].weight)&&(!HT[j].parent)&&(s1!=j))
s2=j;
}
}
void HuffmanCoding(HuffmanCode HC[], int *w, int n) { // w存放n个字符的权值(均>0),构造哈夫曼树HT,//并求出n个字符的哈夫曼编码HC
}
PTree(n);
printf("\n各结点的哈夫曼译码为:\n");
trans();
cout<<"请输入源码:";//从trans函数返回进行编码
cin>>b;
j=(int)(b-64);
while(j){
cout<<HC[j];
cin>>b;
j=(int)(b-64);
}
cout<<endl;
i=HT[i].lchild;
else if(a=='1')
i=HT[i].rchild;
if(HT[i].lchild==0){
cout<<(char)(HT[i].ch+64);i=m;
}
else if(a=='!')
return;//当接收到的输入为"!"时返回主函数进行编码
cin>>a;
}
}
void main() {
HuffmanTree HT;
HuffmanCode *HC;
int *w,n,i,j;
char b,c;puts("输入结点数:");
scanf("%d",&n);
HC=(HuffmanCode *)malloc(n*sizeof(HuffmanCode));
w=(int *)malloc(n*sizeof(int));
if(!HT[i].parent){
s1 = i;break;
}
}
for(j=i+1;j<=n;j++){
if(!HT[j].parent){
s2 = j;break;
}
}
for(i=1;i<=n;i++){
if((HT[s1].weight>HT[i].weight)&&(!HT[i].parent)&&(s2!=i)){
cd[n-1]='\0';
for(i=1;i<=n;++i){
start=n-1;
HT[i].ch=i;
for(unsigned int 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';
HT[i].weight=w[i-1];
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
HT[i].ch=0;
}
for (i=n+1; i<=m; i++) {//初始化
HT[i].weight=0;
HT[i].parent=0;
HT[i].lchild=0;
system("pause");
}
#include<string>
#include<stdlib.h>
#include<stdio.h>
#include<iostream>
using namespace std;
typedef struct {
unsigned int weight;
unsigned int parent,lchild,rchild,ch;
HT[i].rchild=0;
HT[i].ch=0;
}
for (j=1,i=n+1; i<=m; i++,j++) { //建哈夫曼树//在HT[1..i-1]中选择parent为0且weight最小的两个结点,//其序号分别为s1和s2
Select(i-1);
HT[s1].parent = i;
HT[s2].parent = i;
int i, j;
char *cd;
int p;
in (n<=1) return;
m = 2 * n - 1;
HT = (HuffmanTree)malloc((m+1) * sizeof(HTNode)); // 0号单元未用
for (i=1; i<=n; i++) {//初始化