北邮数据结构实验报告实验三哈夫曼
哈夫曼实验报告实验目的(3篇)

6. 对压缩数据进行解压缩,验证哈夫曼编码的正确性。
7. 分析实验结果,对比压缩前后数据的差异。
五、实验总结
通过本次实验,我们掌握了哈夫曼编码的原理和构造方法,学会了如何使用哈夫曼编码进行数据压缩和解压缩。实验结果表明,哈夫曼编码能够有效降低数据的冗余,提高数据压缩效果。同时,本次实验也加深了我们对数据结构中树形结构及其应用的理解,提高了算法设计和实现能力。在今后的学习和工作中,我们将继续探索哈夫曼编码及其应用,为相关领域的研究和发展贡献自己的力量。
二、实验内容
1. 理解哈夫曼编码的原理,掌握哈夫曼树的构造方法。
2. 编写程序实现哈夫曼树的构建、编码和解码过程。
3. 对给定的字符集进行哈夫曼编码,并分析编码后的结果。
4. 对编码后的数据进行解码,验证解码结果的正确性。
5. 比较哈夫曼编码与其他编码方法在数据压缩方面的性能。
三、实验原理
哈夫曼编码是一种基于字符频率的变长编码方法。在哈夫曼编码中,每个字符都被赋予一个唯一的编码,编码的长度与其在原始数据中的频率成反比。频率高的字符编码较短,频率低的字符编码较长。这样,哈夫曼编码在保证数据完整性的同时,实现了数据压缩的目的。
2. 能够编写程序实现哈夫曼编码和解码,提高编程能力。
3. 分析哈夫曼编码在不同场景下的压缩效果,为实际应用提供参考。
4. 了解哈夫曼编码在实际应用中的优势和局限性,为解决实际问题提供思路。
5. 培养实验操作能力,提高解决实际问题的能力。
通过本次实验,我们希望学员能够全面掌握哈夫曼编码的原理、构造方法及其在实际应用中的价值,为今后的学习和工作打下坚实的基础。
第2篇
一、实验目的
1. 理解哈夫曼编码的原理及其在数据压缩中的应用。
北邮数据结构上机实验-哈夫曼树

int l=0;//统计不同字符出现的频度
k=0;//哈夫曼数组下标
temp=m[0];//标记?
for(int i=0;i<n;i++)
{
if(m[i]==temp)
{
void selectmin(int &x,int &y,int i);//寻找权重最小的两个数
void createcodetable();//创建哈夫曼编码表
void reverse(char m[]);//逆置编码字符,颠倒
void encode(char *s,string *d);//编码
}
x=(htree[x].weight<=htree[j].weight)?x:j;
}
htree[x].parent=-2;//防止重复
y=0;
while(htree[y].parent!=-1)
{
x++;
}
for(int j=1;j<i;j++)
{
if(htree[j].parent!=-1)
{
continue;//如果是之前找过的最小值,跳出本次循环
m[j]=m[j+1];
m[j+1]=temp;
}
}
}
int k=1;
htree[x].parent=i;
htree[y].parent=i;
htree[i].weight=htree[x].weight+htree[y].weight;
htree[i].lchild=x;
北邮信通院数据结构实验报告三哈夫曼编码器.pptx

-1
2.2 关键算法分析 (1)计算出现字符的权值
利用 ASCII 码统计出现字符的次数,再将未出现的字符进行筛选,将出现的字符及頻 数存储在数组 a[]中。
void Huffman::Init() {
int nNum[256]= {0}; //记录每一个字符出现的次数 int ch = cin.get();
第2页
北京邮电大学信息与通信工程学 院
2
-1
-1
-1
5
-1
-1
-1
6
-1
-1
-1
7
-1
-1
-1
9
-1
-1
-1
weight lchild rchild parent
2
-1
-1
5
5
-1
-1
5
6
-1
-1
6
7
-1
-1
6
9
-1
-1
7
7
0
1
7
第3页
北京邮电大学信息与通信工程学 院
13
2
3
8
16
5
4
8
29
6
7
2、建立编码表(CreateTable):利用已经建好的赫夫曼树进行编码,并将每 个字符的编码输出。
3、编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的 字符串输出。
4、译码(Decoding):利用已经建好的赫夫曼树对编码后的字符串进行译 码,并输出译码结果。
5、打印(Print):以直观的方式打印赫夫曼树(选作) 6、计算输入的字符串编码前和编码后的长度,并进行分析,讨论赫夫
北邮数据结构实验3哈夫曼编码

数据结构实验报告实验名称:实验3——哈夫曼编码学生姓名:班级:班内序号:学号:日期:2013年11月24日1.实验要求利用二叉树结构实现赫夫曼编/解码器。
基本要求:1、初始化(Init):能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立赫夫曼树2、建立编码表(CreateTable):利用已经建好的赫夫曼树进行编码,并将每个字符的编码输出。
3、编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的字符串输出。
4、译码(Decoding):利用已经建好的赫夫曼树对编码后的字符串进行译码,并输出译码结果。
5、打印(Print):以直观的方式打印赫夫曼树(选作)6、计算输入的字符串编码前和编码后的长度,并进行分析,讨论赫夫曼编码的压缩效果。
2. 程序分析2.1存储结构:struct HNode{char c;//存字符内容int weight;int lchild, rchild, parent;};struct HCode{char data;char code[100];}; //字符及其编码结构class Huffman{private:HNode* huffTree; //Huffman树HCode* HCodeTable; //Huffman编码表public:Huffman(void);void CreateHTree(int a[], int n); //创建huffman树void CreateCodeTable(char b[], int n); //创建编码表void Encode(char *s, string *d); //编码void Decode(char *s, char *d); //解码void differ(char *,int n);char str2[100];//数组中不同的字符组成的串int dif;//str2[]的大小~Huffman(void);};结点结构为如下所示:三叉树的节点结构:struct HNode//哈夫曼树结点的结构体{ int weight;//结点权值int parent;//双亲指针int lchild;//左孩子指针int rchild;//右孩子指针char data;//字符};示意图为:int weight int parent int lchild int rchild Char c 编码表节点结构:struct HCode//编码表结构体{char data;//字符char code[100];//编码内容};示意图为:基本结构体记录字符和出现次数:struct node{int num;char data;};示意图为:2.关键算法分析(1).初始化:伪代码:1.输入需要编译的文本内容2.将输入的内容保存到数组str1中3.统计出现的字符数目,并且保存到变量count中4.统计出现的不同的字符,存到str2中,将str2的大小存到dif中时间复杂度O(n!)(2).创建哈夫曼树算法伪代码:1.创建一个长度为2*n-1的三叉链表2.将存储字符及其权值的链表中的字符逐个写入三叉链表的前n个结点的data域,并将对应结点的孩子域和双亲域赋为空3.从三叉链表的第n个结点开始,3.1从存储字符及其权值的链表中取出两个权值最小的结点x,y,记录其下标x,y。
数据结构哈夫曼编码实验报告

数据结构哈夫曼编码实验报告数据结构哈夫曼编码实验报告1·实验目的1·1 理解哈夫曼编码的基本原理1·2 掌握哈夫曼编码的算法实现方式1·3 熟悉哈夫曼编码在数据压缩中的应用2·实验背景2·1 哈夫曼编码的概念和作用2·2 哈夫曼编码的原理和算法2·3 哈夫曼编码在数据压缩中的应用3·实验环境3·1 硬件环境:计算机、CPU、内存等3·2 软件环境:编程语言、编译器等4·实验过程4·1 构建哈夫曼树4·1·1 哈夫曼树的构建原理4·1·2 哈夫曼树的构建算法4·2 哈夫曼编码4·2·1 哈夫曼编码的原理4·2·2 哈夫曼编码的算法4·3 实现数据压缩4·3·1 数据压缩的概念和作用4·3·2 哈夫曼编码在数据压缩中的应用方法5·实验结果5·1 构建的哈夫曼树示例图5·2 哈夫曼编码表5·3 数据压缩前后的文件大小对比5·4 数据解压缩的正确性验证6·实验分析6·1 哈夫曼编码的优点和应用场景分析6·2 数据压缩效果的评估和对比分析6·3 实验中遇到的问题和解决方法7·实验总结7·1 实验所获得的成果和收获7·2 实验中存在的不足和改进方向7·3 实验对于数据结构学习的启示和意义附件列表:1·实验所用的源代码文件2·实验中用到的测试数据文件注释:1·哈夫曼编码:一种用于数据压缩的编码方法,根据字符出现频率构建树形结构,实现高频字符用较短编码表示,低频字符用较长编码表示。
2·哈夫曼树:由哈夫曼编码算法构建的一种特殊的二叉树,用于表示字符编码的结构。
数据结构 哈夫曼编码实验报告

数据结构哈夫曼编码实验报告数据结构哈夫曼编码实验报告1. 实验目的本实验旨在通过实践理解哈夫曼编码的原理和实现方法,加深对数据结构中树的理解,并掌握使用Python编写哈夫曼编码的能力。
2. 实验原理哈夫曼编码是一种用于无损数据压缩的算法,通过根据字符出现的频率构建一棵哈夫曼树,并根据哈夫曼树对应的编码。
根据哈夫曼树的特性,频率较低的字符具有较长的编码,而频率较高的字符具有较短的编码,从而实现了对数据的有效压缩。
实现哈夫曼编码的主要步骤如下:1. 统计输入文本中每个字符的频率。
2. 根据字符频率构建哈夫曼树,其中树的叶子节点代表字符,内部节点代表字符频率的累加。
3. 遍历哈夫曼树,根据左右子树的关系对应的哈夫曼编码。
4. 使用的哈夫曼编码对输入文本进行编码。
5. 将编码后的二进制数据保存到文件,同时保存用于解码的哈夫曼树结构。
6. 对编码后的文件进行解码,还原原始文本。
3. 实验过程3.1 统计字符频率首先,我们需要统计输入文本中每个字符出现的频率。
可以使用Python中的字典数据结构来记录字符频率。
遍历输入文本的每个字符,将字符添加到字典中,并递增相应字符频率的计数。
```pythondef count_frequency(text):frequency = {}for char in text:if char in frequency:frequency[char] += 1else:frequency[char] = 1return frequency```3.2 构建哈夫曼树根据字符频率构建哈夫曼树是哈夫曼编码的核心步骤。
我们可以使用最小堆(优先队列)来高效地构建哈夫曼树。
首先,将每个字符频率作为节点存储到最小堆中。
然后,从最小堆中取出频率最小的两个节点,将它们作为子树构建成一个新的节点,新节点的频率等于两个子节点频率的和。
将新节点重新插入最小堆,并重复该过程,直到最小堆中只剩下一个节点,即哈夫曼树的根节点。
北邮-数据结构-哈夫曼树报告Word版

数据结构实验报告实验名称:哈夫曼树学生姓名:袁普班级:2013211125班班内序号:14号学号:2013210681日期:2014年12月实验目的和内容利用二叉树结构实现哈夫曼编/解码器。
基本要求:1、初始化(Init):能够对输入的任意长度的字符串 s进行统计,统计每个字符的频度,并建立哈夫曼树2、建立编码表(CreateTable):利用已经建好的哈夫曼树进行编码,并将每个字符的编码输出。
3、编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的字符串输出。
4、译码(Decoding):利用已经建好的哈夫曼树对编码后的字符串进行译码,并输出译码结果。
5、打印(Print):以直观的方式打印哈夫曼树(选作)6、计算输入的字符串编码前和编码后的长度,并进行分析,讨论赫夫曼编码的压缩效果。
7、可采用二进制编码方式(选作)测试数据:I love data Structure, I love Computer。
I will try my best to studydata Structure.提示:1、用户界面可以设计为“菜单”方式:能够进行交互。
2、根据输入的字符串中每个字符出现的次数统计频度,对没有出现的字符一律不用编码2. 程序分析2.1 存储结构用struct结构类型来实现存储树的结点类型struct HNode{int weight; //权值int parent; //父节点int lchild; //左孩子int rchild; //右孩子};struct HCode //实现编码的结构类型{char data; //被编码的字符char code[100]; //字符对应的哈夫曼编码};2.2 程序流程2.3 关键算法分析算法1:void Huffman::Count()[1] 算法功能:对出现字符的和出现字符的统计,构建权值结点,初始化编码表[2] 算法基本思想:对输入字符一个一个的统计,并统计出现次数,构建权值数组,[3] 算法空间、时间复杂度分析:空间复杂度O(1),要遍历一遍字符串,时间复杂度O(n)[4] 代码逻辑:leaf=0; //初始化叶子节点个数int i,j=0;int s[128]={0}; 用于存储出现的字符for(i=0;str[i]!='\0';i++) 遍历输入的字符串s[(int)str[i]]++; 统计每个字符出现次数for(i=0;i<128;i++)if(s[i]!=0){data[j]=(char)i; 给编码表的字符赋值weight[j]=s[i]; 构建权值数组j++;}leaf=j; //叶子节点个数即字符个数for(i=0;i<leaf;i++)cout<<data[i]<<"的权值为:"<<weight[i]<<endl;算法2:void Init();[1] 算法功能:构建哈弗曼树[2] 算法基本思想:根据哈夫曼树构建要求,选取权值最小的两个结点结合,新结点加入数组,再继续选取最小的两个结点继续构建。
数据结构哈夫曼树实验报告

数据结构哈夫曼树实验报告一、实验内容本次实验的主要内容是哈夫曼树的创建和编码解码。
二、实验目的1. 理解并掌握哈夫曼树的创建过程;2. 理解并掌握哈夫曼编码的原理及其实现方法;3. 掌握哈夫曼树的基本操作,如求哈夫曼编码和哈夫曼解码等;4. 学习如何组织程序结构,运用C++语言实现哈夫曼编码和解码。
三、实验原理哈夫曼树的创建:哈夫曼树的创建过程就是一个不断合并权值最小的两个叶节点的过程。
具体步骤如下:1. 将所有节点加入一个无序的优先队列里;2. 不断地选出两个权值最小的节点,并将它们合并成为一个节点,其权值为这两个节点的权值之和;3. 将新的节点插入到队列中,并继续执行步骤2,直到队列中只剩下一棵树,这就是哈夫曼树。
哈夫曼编码:哈夫曼编码是一种无损压缩编码方式,它根据字符出现的频率来构建编码表,并通过编码表将字符转换成二进制位的字符串。
具体实现方法如下:1. 统计每个字符在文本中出现的频率,用一个数组记录下来;2. 根据字符出现的频率创建哈夫曼树;3. 从根节点开始遍历哈夫曼树,给左分支打上0的标记,给右分支打上1的标记。
遍历每个叶节点,将对应的字符及其对应的编码存储在一个映射表中;4. 遍历文本中的每个字符,查找其对应的编码表,并将编码字符串拼接起来,形成一个完整的编码字符串。
哈夫曼解码就是将编码字符串还原为原始文本的过程。
具体实现方法如下:1. 从根节点开始遍历哈夫曼树,按照编码字符串的位数依次访问左右分支。
如果遇到叶节点,就将对应的字符记录下来,并重新回到根节点继续遍历;2. 重复步骤1,直到编码字符串中的所有位数都被遍历完毕。
四、实验步骤1. 定义编码和解码的结构体以及相关变量;3. 遍历哈夫曼树,得到每个字符的哈夫曼编码,并将编码保存到映射表中;4. 将文本中的每个字符用其对应的哈夫曼编码替换掉,并将编码字符串写入到文件中;5. 使用哈夫曼编码重新构造文本,并将结果输出到文件中。
五、实验总结通过本次实验,我掌握了哈夫曼树的创建和哈夫曼编码的实现方法,也学会了如何用C++语言来组织程序结构,实现哈夫曼编码和解码。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
bool sign=0; for(int x=0;x<t+1;x++) {
if(str[m]==dat[x]) {
wei[x]++; sign=1;
第 6页
北京邮电大学信息与通信工程学院
第 4页
北京邮电大学信息与通信工程学院
亲 HTree[i].weight=HTree[x].weight+HTree[y].weight; //新结点的权值为其孩子的权值的和
HTree[i].LChild=x;
HTree[i].RChild=y;
HTree[i].parent=-1;
}
}
时间复杂度:
2、建立编码表(CreateTable):利用已经建好的赫夫曼树进行编码,并将每 个字符的编码输出。
3、编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的 字符串输出。
4、译码(Decoding):利用已经建好的赫夫曼树对编码后的字符串进行译码, 并输出译码结果。
5、打印(Print):以直观的方式打印赫夫曼树(选作) 6、计算输入的字符串编码前和编码后的长度,并进行分析,讨论赫夫曼
4. 总结
本次实验将书上的哈夫曼只是实践在程序中,通过编写,修改等等繁复的工作,我对哈 夫曼树相关知识记得更牢,学的更扎实了。只看书上的只是难以了解很多意想不到的问题。
编写前先看了一遍书,然后在网上看了一些相关知识,最后编写,中间遇到了一些逻辑 错误较为麻烦,其他错误花了一些时间。程序上大体结构较为清晰,功能比较齐全。
北京邮电大学信息与通信工程学院
数据结构实验报告
实验名称:实验三——哈夫曼编/解码器的实现 学生姓名: 侯在鹏 班 级: 2012211120 班内序号: 13 学 号:2012210583 日 期: 2013 年 12 月 10 日
1.实验要求
利用二叉树结构实现赫夫曼编/解码器。 基本要求:
1、初始化(Init):能够对输入的任意长度的字符串 s 进行统计,统计每个 字符的频度,并建立赫夫曼树
{
for(int i=0;i<n;i++)
{
if(a[m]==HCodeTable[i].data)
{
d=strcat(d,HCodeTable[i].code);
}
}
}
cout<<"编码后的哈夫曼编码字符串为:"<<d<<endl;
}
时间复杂度:
设待编码字符串长度为 n,编码表中字符个数为 m,则复杂度为 O(n*m)
程序还有很多不足,时间以及个人能力关系,一些功能没有实现,代码上不够简洁,有 些部分效率低,都有待改进。
第 8页
} } if(sign==0) {
t++; dat[t]=str[m]; wei[t]=1; } } t++; dat[t]='\0'; } 时间复杂度: O(n)
2.3 其他
3. 程序运行结果
主函数流程图: 开始
调用菜单函数
等待用户输入 字符串
利用用户输入的字符串 创建哈夫曼树和编码表
对输入的字符串编码
2. 程序分析
第 1页
北京邮电大学信息与通信工程学院
2.1 存储结构
程序实现了基本的编解码功能 输入字符串 选择工作目标 编码 解码 相关树,表显示 编码上 根节点向下,左 0 右 1 根据不同字符在尾端相应排位,获得自己的编码,存储。 解码上 依次读取数据 0 或 1,循序寻找, 最后在存储中找到对应编码的字符,输出 再重新读取下一数字开始的数码 在哈夫曼树编码这个程序中,所有数据用的存储结构都是顺序存储结构,其中包括顺序表和 树(三叉树) 树的存储结构如下:(输入的字符串为 assddddffffffffgggggggggggggggg)
min2=HTree[j].weight; y=j; } } } 时间复杂度: 遍历链表,时间复杂度为 O(n)
2.2.2.创建哈夫曼树
算法伪代码: (1)创建一个长度为 2*n-1 的三叉链表 (2)将存储字符及其权值的链表中的字符逐个写入三叉链表的前 n 个结点的 data 域,并将
对应结点的孩子域和双亲域赋为空 (3)从三叉链表的第 n 个结点开始,i=n (3.1)从存储字符及其权值的链表中取出两个权值最小的结点 x,y,记录其下标 x,y。 (3.2)将下标为 x 和 y 的哈夫曼树的结点的双亲设置为第 i 个结点 (3.3)将下标为 x 的结点设置为 i 结点的左孩子,将下标为 y 的结点设置为 i 结点的右
if(HTree[j].parent==-1) {
if(HTree[j].weight<min1||min2==-1) {
if(min1!=-1)
第 3页
北京邮电大学信息与通信工程学院
{ min2=min1; y=x;
} min1=HTree[j].weight; x=j; } else if(HTree[j].weight<min2||min2==-1) {
2.2.4 解码函数
算法伪代码:
(1)得到指向哈夫曼树的根结点的指针和指向待解码串中的第 1 个字符的指针
(2)逐个读取待解码串中的字符,若为 0,则指向哈夫曼树当前结点的指针指向
当前结点的左孩子,若为 1,则指向当前结点的右孩子
(3)指向待解码串的指针指向解码串中的下一个字符,直到指向哈夫曼树结点的
尾。
(4) 重复以上步骤,直到所有待编码串中的字符都编码完毕
(5) 输出编码后的字符串
void Huffman::Encode(char a[],char *d,int n,int j)
//a[]为原始字符串,d 为编码后的哈
夫曼编码字符串,n 为编码表长度,j 为原始字符串的长度
{
for(int m=0;m<j;m++)
012345 ASCⅡ 9 115 100 102 103 weight 1 2 4 8 16 3 lchild -1 -1 -1 -1 -1 0 rchild -1 -1 -1 -1 -1 1 parent -5 5 -6 -7 -8 6
678
7 15 31 234 567 780
上结构图中,填充为黄色的部分为写入内存中的部分。每一行的部分为数组的下标,左 边部分为所定义的结构的成员。其中有的结点的父节点的下标是一个负数,用来说明该节点 是该节点的父节点的左孩子,正数说明的是该节点的父节点的右孩子。父节点这零的节点说 明该节点是该哈夫曼树的根节点。画出树的结构如下画所示:(结点中第一个数表示这个字 符的 ASCⅡ编码,第二个数字表示权值)
int parent=2*n-1-1;//根结点 while(HTree[parent].LChild!=-1) {
if(*s=='0') parent=HTree[parent].LChild;
else parent=HTree[parent].RChild;
s++; } *d=HCodeTable[parent].data; d++; } } 时间复杂度: 设待解码串长度为 n,则复杂度为 O(n)
a 1110 ; s 1111 ; d 110 ; f 10 ; g 02Fra bibliotek2 关键算法分析
2.2.1 选择两个最小权值的函数
算法伪代码: (1) 初始化最小权值 min1,min2.可引用变量 x,y。 (2) 遍历哈夫曼树,比较字符的权值与 min1,min2 的大小。若小于 min1,则将 min1 值赋给
min2,字符权值赋给 min1,同时改变权值最小的结点编号 x,y.若大于 min1 同时小于 min2, 则将字符权值赋给 min2,改变 y 值。 源代码: void Huffman::SelectMin(int &x,int &y,int a,int b)//选出两个权值最小的结点 { int j,min1,min2; min1=min2=-1; for(j=a;j<b;j++)
指针的孩子结点为空
(4)如果指向哈夫曼树结点的指针的孩子结点已经为空,则将叶子结点下标对应
第 5页
北京邮电大学信息与通信工程学院
的字符追加到解码串中。 (5)输出解码串 源代码: void Huffman::Decode(char *s,char *d,int n)//解码。s 为编码后的数组,d 为解码 后的数组 { while(*s!='\0') {
第 2页
北京邮电大学信息与通信工程学院
^ 31 8
0
1
^ 16 4
0 ^
15 7
0
1
102 83
^ 76
0
1
100 42
^ 3
0
97 11
5 1
115 20
红色箭头表示父指针,黑色箭头表示孩子指针 由上面的图可知,原字符串编码后的二进制编码为 11101111111111011011011010101010101010100000000000000000 字符串中出现的所有的字符的编码如下:
编码的压缩效果。
测试数据: I love data Structure, I love Computer。I will try my best to study data Structure.
提示: 1、用户界面可以设计为“菜单”方式:能够进行交互。 2、根据输入的字符串中每个字符出现的次数统计频度,对没有出现的 字符一律不用编码。