数据结构哈夫曼编码实验报告
数据结构哈夫曼编码实验报告

数据结构实验报告――实验五简单哈夫曼编/译码的设计与实现本实验的目的是通过对简单哈夫曼编/译码系统的设计与实现来熟练掌握树型结构在实际问题中的应用。
此实验可以作为综合实验,阶段性实验时可以选择其中的几个功能来设计和实现。
一、【问题描述】利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码,此实验即设计这样的一个简单编/码系统。
系统应该具有如下的几个功能:1、接收原始数据。
从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件中。
2、编码。
利用已建好的哈夫曼树(如不在内存,则从文件中读入),对文件中的正文进行编码,然后将结果存入文件中。
3、译码。
利用已建好的哈夫曼树将文件中的代码进行译码,结果存入文件中。
4、打印编码规则。
即字符与编码的一一对应关系。
二、【数据结构设计】1、构造哈夫曼树时使用静态链表作为哈夫曼树的存储。
在构造哈夫曼树时,设计一个结构体数组HuffNode保存哈夫曼树中各结点的信息,根据二叉树的性质可知,具有n个叶子结点的哈夫曼树共有2n-1个结点,所以数组HuffNode 的大小设置为2n-1,描述结点的数据类型为:typedef struct{int weight;eight=0;HaffNode[i].parent=-1;HaffNode[i].lchild=-1;HaffNode[i].rchild=-1;HaffNode[i].inf='0';}for(i=0;i<n;i++){cout<<"请输入字符"<<endl;cin>>HaffNode[i].inf;cout<<"请输入该字符的权值"<<endl;cin>>HaffNode[i].weight;}for(i=0;i<n-1;i++)arent==-1&&HaffNode[j].weight<m1){m2=m1;x2=x1;m1=HaffNode[j].weight;x1=j;}else{if(HaffNode[j].parent==-1&&HaffNode[j].weight<m2){m2=HaffNode[j].weight;x2=j;}}}arent=n+i;HaffNode[x2].parent=n+i;HaffNode[n+i].weight=HaffNode[x1].weight+HaffNode[x2].weight;HaffNode[n+i].lchild=x1;HaffNode[n+i].rchild=x2;HaffNode[n+i].inf=NULL;}cout<<"显示存储的哈弗曼树信息:"<<endl;cout<<"权值左孩子右孩子双亲"<<endl;for(i=0;i<2*n-1;i++){cout<<HaffNode[i].weight<<" ";cout<<HaffNode[i].lchild<<" ";cout<<HaffNode[i].rchild<<" ";cout<<HaffNode[i].parent<<" ";cout<<HaffNode[i].inf<<endl;}arent;while(p!=-1){if(HaffNode[p].lchild==c)[]=0;else[]=1;;c=p;p=HaffNode[c].parent;}for(j=+1;j<n;j++)HaffCode[i].bit[j]=[j];HaffCode[i].start=;}for(i=0;i<n;i++){outfile<<HaffNode[i].inf;for(j=HaffCode[i].start+1;j<n;j++)outfile<<HaffCode[i].bit[j];}cout<<"字符信息--编码信息"<<endl;for(i=0;i<n;i++){cout<<HaffNode[i].inf<<"---";for(j=HaffCode[i].start+1;j<n;j++)cout<<HaffCode[i].bit[j];cout<<endl;}();cout<<"请输入要编码的字符串,基本元素为(";for(i=0;i<n;i++)cout<<HaffNode[i].inf<<",";cout<<")"<<endl;char inf[100];cin>>inf;int f=strlen(inf);fstream outfile1;("E:\\",ios::out|ios::binary);nf){for(j=HaffCode[i].start+1;j<n;j++){((char*)&HaffCode[i].bit[j],sizeof(HaffCode[i].bit[j]));cout<<HaffCode[i].bit[j];}}}}}cout<<endl;cout<<"编译后的代码串已经存入文件中!"<<endl;cout<<endl;();delete []HaffNode;delete []HaffCode;}void decode( int &n)child!=-1&&HaffNode[m].rchild!=-1)if(tempcode[i]==0){m=HaffNode[m].lchild;i++;}else if(tempcode[i]==1){m=HaffNode[m].rchild;i++;}}cout<<HaffNode[m].inf;outfile<<HaffNode[m].inf;m=2*n-2;}cout<<endl;();cout<<"译码后的结果已经存入中!"<<endl;delete []HaffNode;}int main(){int n;cout<<"************* 欢迎进入编/译码系统!*********************"<<endl;int ch1;do{cout<<" 1.建树"<<endl;cout<<" 2:编码,并显示字符和对应的编码"<<endl;cout<<" 3:译码"<<endl;cout<<" 0:退出"<<endl;cout<<"********************************************************"<<end l;cout<<"请选择(0~3):";cin>>ch1;while(!(ch1<=3&&ch1>=0)) //输入不在0到4之间无效{cout<<"数据输入错误,请重新选择(0~4):";cin>>ch1;switch(ch1){case 1:{cout<<"\t\t\t请输入编码个数"<<endl;//叶子结点个数cin>>n;Creat_Haffmantree(n);break;}case 2: HaffCode(n); break;case 3: decode(n); break;}}while(ch1!=0);return 0;}五、【运行与测试】1、令叶子结点个数n为4,权值集合为{1,3,5,7},字符集合为{A,B,C,D},并有如下对应关系,A――1、B――3,C――5,D――7,调用初始化功能模块可以正确接收这些数据。
数据结构哈夫曼编码实验报告

数据结构哈夫曼编码实验报告一、实验目的:通过哈夫曼编、译码算法的实现,巩固二叉树及哈夫曼树相关知识的理解掌握,训练学生运用所学知识,解决实际问题的能力。
二、实验内容:已知每一个字符出现的频率,构造哈夫曼树,并设计哈夫曼编码。
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。
数据结构大作业-哈夫曼编码实验报告

一.构造过程①统计可知,字符串全长共59个字符,其中字符‘A’-‘F’的出现频数及对应概率(保留两位小数)如图所示:②将每个字符出现概率作为权重,则对于上述给定的6个权值{25,15,14,20,17,9},依次构造6棵只有根节点的二叉树,共同构成森林F;③在森林F中,选取权重最小和次小的两颗树,分别作为新二叉树的左子树、右子树,且该树根节点权值赋左右子树权值之和;④从森林F中删除已选中的两棵子树,把新得到的二叉树加入F 中;⑤重复③④,直到森林F中仅留下一棵树时,得到最终的哈夫曼树HF如图所示:⑥对上述哈夫曼树,将其树中的每个左分支赋0、右分支赋1,则从根结点开始到叶子结点,各分支路径分别得到对应的二进制串,即为给定的每个字符的哈夫曼编码。
二、代码实现源代码如下:#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>#include <string.h>#define N 6 //指定的编码字符数#define M (2 * N - 1) //HT结点数#define MAXWEIGHT 100typedef struct { //哈夫曼树的存储表示int weight;int parent, lchild, rchild;}HTNode;typedef HTNode HuffmanTree[M + 1];typedef char* HuffmanCode[N + 1]; //哈夫曼编码表void Select(HuffmanTree HT, int n, int& s1, int& s2);void CreateHuffmanTree(HuffmanTree& HT, int* w, int n); void CreateHuffmanCode(HuffmanTree HT, HuffmanCode& HC); void PrintHC(HuffmanCode HC, char ch[]);int main() {HuffmanTree HT;HuffmanCode HC;int w[N + 1];char ch[N + 1];printf("Please input %d characters & its weight(e.g. A 25):\n", N);for (int i = 1; i <= N; i++) {scanf("%c %d", &ch[i], &w[i]);getchar();}CreateHuffmanTree(HT, w, N);CreateHuffmanCode(HT, HC);PrintHC(HC, ch);return 0;}void Select(HuffmanTree HT, int n, int& s1, int& s2) { int i, min = 0, temp = MAXWEIGHT;for (i = 1; i <= n; i++) {if (!HT[i].parent) {if (temp > HT[i].weight) {temp = HT[i].weight;min = i; //最小值作为新树左子树}}}s1 = min;for (i = 1, min = 0, temp = MAXWEIGHT; i <= n; i++) { if ((!HT[i].parent) && i != s1) {if (temp > HT[i].weight) {temp = HT[i].weight;min = i; //次小值作为新树右子树}}}s2 = min;}void CreateHuffmanTree(HuffmanTree& HT, int* w, int n) { //创建哈夫曼树HTint i, s1, s2;if (n <= 1) return; //树为空或仅有根节点for (i = 1; i <= M; ++i) { //初始化HT[i].weight = w[i];HT[i].parent = 0;HT[i].lchild = 0;HT[i].rchild = 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].weight = HT[s1].weight + HT[s2].weight;}}void CreateHuffmanCode(HuffmanTree HT, HuffmanCode& HC) {int i, start, c, f;char cd[N];cd[N - 1] = '\0'; //编码结束符for (i = 1; i <= N; i++) { //对于第i个待编码字符即第i个带权值的叶子节点start = N - 1; //开始start指向结束符位置c = i;f = HT[i].parent; //f指向当前结点的双亲while (f) { //从叶上溯,到根节点跳出if (HT[f].lchild == c)cd[--start] = '0'; //左孩子elsecd[--start] = '1'; //右孩子c = f;f = HT[f].parent;}HC[i] = new char[N - start];strcpy(HC[i], &cd[start]); //复制结果到编码表,用于输出}}void PrintHC(HuffmanCode HC, char ch[]) { //打印哈夫曼编码表for (int i = 1; i <= N; i++)printf("\n%c: %s\n", ch[i], HC[i]);}三,输出各个字母的哈夫曼编码:四、算法分析1、哈夫曼编码是最优前缀编码:对包括N个字符的数据文件,分别以它们的出现概率构造哈夫曼树,利用该树对应的哈夫曼编码对报文进行编码,得到压缩后的最短二进制编码;2、算法自底而上地构造出对应最优编码的二叉树HT,它从n个叶子结点开始,识别出最低权重的两个对象,并将其合并;当合并时,新对象的权重设置为原两个对象权值之和,一共执行了|n| - 1次合并操作;3、是贪心算法:每次选择均为当下的最优选择,通过合并来构造最优树得到对应的哈夫曼编码;4、复杂度:①时间复杂度:有n个终端节点,构成的哈夫曼树总共有2n-1个节点,Select函数的时间复杂度为O(n),嵌套for循环,因此建立哈夫曼树的时间复杂度为O(n^2),创建哈弗曼编码表的时间复杂度为O(n^2);②空间复杂度:算法中临时占用存储空间大小为数组第0号空间,其耗费的空间复杂度为O(1)。
数据结构哈夫曼编码实验报告

数据结构哈夫曼编码实验报告数据结构哈夫曼编码实验报告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 构建哈夫曼树根据字符频率构建哈夫曼树是哈夫曼编码的核心步骤。
我们可以使用最小堆(优先队列)来高效地构建哈夫曼树。
首先,将每个字符频率作为节点存储到最小堆中。
然后,从最小堆中取出频率最小的两个节点,将它们作为子树构建成一个新的节点,新节点的频率等于两个子节点频率的和。
将新节点重新插入最小堆,并重复该过程,直到最小堆中只剩下一个节点,即哈夫曼树的根节点。
哈夫曼树编码实验报告

哈夫曼树编码实验报告哈夫曼树编码实验报告引言:哈夫曼树编码是一种常用的数据压缩算法,通过对数据进行编码和解码,可以有效地减小数据的存储空间。
本次实验旨在探究哈夫曼树编码的原理和应用,并通过实际案例验证其有效性。
一、哈夫曼树编码原理哈夫曼树编码是一种变长编码方式,根据字符出现的频率来确定不同字符的编码长度。
频率较高的字符编码较短,频率较低的字符编码较长,以达到最佳的数据压缩效果。
1.1 字符频率统计首先,需要对待编码的数据进行字符频率统计。
通过扫描数据,记录每个字符出现的次数,得到字符频率。
1.2 构建哈夫曼树根据字符频率构建哈夫曼树,频率较低的字符作为叶子节点,频率较高的字符作为父节点。
构建哈夫曼树的过程中,需要使用最小堆来维护节点的顺序。
1.3 生成编码表通过遍历哈夫曼树,从根节点到每个叶子节点的路径上的左右分支分别赋予0和1,生成对应的编码表。
1.4 数据编码根据生成的编码表,将待编码的数据进行替换,将每个字符替换为对应的编码。
编码后的数据长度通常会减小,实现了数据的压缩。
1.5 数据解码利用生成的编码表,将编码后的数据进行解码,恢复原始数据。
二、实验过程与结果为了验证哈夫曼树编码的有效性,我们选择了一段文本作为实验数据,并进行了以下步骤:2.1 字符频率统计通过扫描文本,统计每个字符出现的频率。
我们得到了一个字符频率表,其中包含了文本中出现的字符及其对应的频率。
2.2 构建哈夫曼树根据字符频率表,我们使用最小堆构建了哈夫曼树。
频率较低的字符作为叶子节点,频率较高的字符作为父节点。
最终得到了一棵哈夫曼树。
2.3 生成编码表通过遍历哈夫曼树,我们生成了对应的编码表。
编码表中包含了每个字符的编码,用0和1表示。
2.4 数据编码将待编码的文本数据进行替换,将每个字符替换为对应的编码。
编码后的数据长度明显减小,实现了数据的压缩。
2.5 数据解码利用生成的编码表,将编码后的数据进行解码,恢复原始文本数据。
数据结构哈夫曼树编码译码实验报告.doc

数据结构哈夫曼树编码译码实验报告.【详细设计】具体代码实现如下://HaffmanTree.h#include#include#includestruct HuffmanNode //哈夫曼树的一个结点{ int weight; int parent; int lchild,rchild; };class HuffmanTree //哈夫曼树{private: HuffmanNode *Node; //Node[]存放哈夫曼树char *Info; //Info[]存放源文用到的字符——源码,如'a','b','c','d','e',此内容可以放入结点中,不单独设数组存放int LeafNum; //哈夫曼树的叶子个数,也是源码个数public: HuffmanTree(); ~HuffmanTree(); void CreateHuffmanTree(); /*在内存中建立哈夫曼树,存放在Node[]中。
让用户从两种建立哈夫曼树的方法中选择:1.从键盘读入源码字符集个数,每个字符,和每个字符的权重,建立哈夫曼树,并将哈夫曼树写入文件hfmTree中。
2.从文件hfmTree中读入哈夫曼树信息,建立哈夫曼树*/ void CreateHuffmanTreeFromKeyboard(); void CreateHuffmanTreeFromFile(); void Encoder(); /*使用建立好的哈夫曼树(如果不在内存,则从文件hfmTree中读入并建立内存里的哈夫曼树),对文件ToBeTran中的正文进行编码,并将码文写入文件CodeFile中。
ToBeTran的内容可以用记事本等程序编辑产生。
*/ void Decoder(); /*待译码的码文存放在文件CodeFile中,使用建立好的哈夫曼树(如果不在内存,则从文件hfmTree中读入并建立内存里的哈夫曼树)将码文译码,得到的源文写入文件TextFile中,并同时输出到屏幕上。
数据结构哈夫曼编码实验报告

数据结构哈夫曼编码实验报告【正文】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.结论通过本次实验,我们深入了解了哈夫曼编码的原理和实现方法,实践了哈夫曼编码的过程,并对其在数据压缩中的有效性进行了验证。
实验结果表明,哈夫曼编码能够实现较高的压缩率和较高的编解码效率。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验报告
图1.2 启动界面
(2)编码操作。
图1.3在D盘中建立一个文本文档,并命名为123.txt
图1.4文件压缩,输出哈弗曼编码界面
图1.5在D盘中生成一个.COD的文档,并且名为12.COD:
(3)解码操作。
根据实验要求输出实验结果。
如图1.4所示。
图1.4 数据结果输出界面
(4) 显示数据内容
若用户想知道文本输入的内容,可输入“L”,然后界面提示输入文本文件的路径和文件名,完成输入后按回车键,界面会出现文本的内容。
六、实验收获与思考
在完成实验的过程中,使我明白了面向对象与面向对象的差别。
在面向对象过程中,类的设计是至关重要的,类设计好了等于程序就成功了一半,所以这次的课程帮助我复习了这一学期面向对象课程的学习,刚好可以弥补这一学期面向对象学习的不足。
同时,也使我对数据结构与算法的知识有了一定的了解,帮我
.
.。