北邮 大数据结构 哈夫曼树报告材料

合集下载

北邮数据结构上机实验-哈夫曼树

北邮数据结构上机实验-哈夫曼树
hn=2*k-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;

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

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

数据结构哈夫曼编码实验报告一、实验目的:通过哈夫曼编、译码算法的实现,巩固二叉树及哈夫曼树相关知识的理解掌握,训练学生运用所学知识,解决实际问题的能力。

二、实验内容:已知每一个字符出现的频率,构造哈夫曼树,并设计哈夫曼编码。

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。

北邮数据结构实验报告

北邮数据结构实验报告

北邮数据结构实验报告北京邮电大学信息与通信工程学院2009级数据结构实验报告实验名称:实验三哈夫曼编/解码器的实现学生姓名:陈聪捷日期:2010年11月28日1.实验要求一、实验目的:了解哈夫曼树的思想和相关概念;二、实验内容:利用二叉树结构实现哈夫曼编/解码器1.初始化:能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立哈夫曼树。

2.建立编码表:利用已经建好的哈夫曼树进行编码,并将每个字符的编码输出。

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

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

5.打印:以直观的方式打印哈夫曼树。

6.计算输入的字符串编码前和编码后的长度,并进行分析,讨论哈夫曼编码的压缩效果。

7.用户界面可以设计成“菜单”方式,能进行交互,根据输入的字符串中每个字符出现的次数统计频度,对没有出现的字符一律不用编码。

2.程序分析2.1存储结构二叉树templateclassBiTree{public:BiTree();//构造函数,其前序序列由键盘输入~BiTree(void);//析构函数BiNode*Getroot();//获得指向根结点的指针protected:BiNode*root;//指向根结点的头指针};//声明类BiTree及定义结构BiNodeData:二叉树是由一个根结点和两棵互不相交的左右子树构成data:HCode*HCodeTable;//编码表inttSize;//编码表中的总字符数二叉树的节点结构templatestructBiNode//二叉树的结点结构{Tdata;//记录数据Tlchild;//左孩子Trchild;//右孩子Tparent;//双亲};编码表的节点结构structHCode{chardata;//编码表中的字符charcode[100];//该字符对应的编码};待编码字符串由键盘输入,输入时用链表存储,链表节点为structNode{charcharacter;//输入的字符unsignedintcount;//该字符的权值boolused;//建立树的时候该字符是否使用过Node*next;//保存下一个节点的地址};示意图:2.2关键算法分析1.初始化函数(voidHuffmanTree::Init(stringInput))算法伪代码:1.初始化链表的头结点2.获得输入字符串的第一个字符,并将其插入到链表尾部,n=1(n 记录的是链表中字符的个数)3.从字符串第2个字符开始,逐个取出字符串中的字符3.1将当前取出的字符与链表中已经存在的字符逐个比较,如果当前取出的字符与链表中已经存在的某个字符相同,则链表中该字符的权值加1。

北邮-数据结构-哈夫曼树报告

北邮-数据结构-哈夫曼树报告

数据结构欧阳学文实验报告实验名称:哈夫曼树学生姓名:袁普班级:211125班班内序号:14号学号:210681日期:12月1.实验目的和内容利用二叉树结构实现哈夫曼编/解码器。

基本要求: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 study data 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·实验目的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版

北邮-数据结构-哈夫曼树报告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] 算法基本思想:根据哈夫曼树构建要求,选取权值最小的两个结点结合,新结点加入数组,再继续选取最小的两个结点继续构建。

北邮数据结构实验报告三题目2-哈夫曼树

北邮数据结构实验报告三题目2-哈夫曼树

11.实验要求利用二叉树结构实现哈夫曼编/ 解码器(1). 初始化:能够对输入的任意长度的字符串s 进行统计,统计每个字符的频度,并建立哈夫曼树。

(2). 建立编码表:利用已经建好的哈夫曼树进行编码,并将每个字符的编码输出。

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

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

(5). 打印:以直观的方式打印哈夫曼树。

(6). 计算输入的字符串编码前和编码后的长度,并进行分析,讨论哈夫曼编码的压缩效果。

(7). 用户界面可以设计成“菜单”方式,能进行交互,根据输入的字符串中每个字符出现的次数统计频度,对没有出现的字符一律不用编码。

2.程序分析2.1存储结构二叉树:示意图:root2.21{2.3 关键算法分析1. 定义哈夫曼树的模板类#include <iostream>#include <string.h> using namespace std; structLNode {char ch;int weight;char code[20];LNode* next; };struct TNode{int weight; //int Lchild; //int Rchild; //int Parent; // };class Huffman 结点权值左孩子指针右孩子指针双亲指针// 链表的节点, 用来统计字符频率,并编码// 字符// 权值// 字符编码// 指向下一个节点// 哈弗曼树结点的结构体1 public:Huffman(); ~Huffman(); void CreateTable(); void PrintTable(); void Encoding(); void Decoding(); void Comrate();// 构造函数,输入、统计字符,创建哈弗曼树、码表// 释放链表空间、哈弗曼树的节点// 建立编码表,并将信息存入链表// 输出码表// 哈弗曼编码// 译码void SelectMin(int &x,int &y,int begin,int end);void reverse(char ch[]); voidcontrol();private: // 选取权值最小的两个数,创建哈弗曼树// 将码值倒置,用来编码// 对菜单交互等提示操作TNode* troot;LNode* lroot; void List(char a[]); void HTree(); int Letter; char astr[1000]; char bstr[1000]; // 在统计字符频率是构建链表的根节点// 统计字符的权值建立的单链表// 哈弗曼树建立// 共有不同字符总数// 用户输入的一串字符// 将字符串的码值保存Huffman::Huffman(){lroot=new LNode;bstr[0]='\0';lroot->next=NULL;Letter=0; // 初始化字符总数为1 cout<<" 请输入一串字符,以回车键结束"<<endl;cin.getline(astr,1000,'\n');if(strlen(astr)==0) throw 1;else{List(astr); // 用链表存储每个字符HTree();CreateTable();Encoding();}};Huffman::~Huffman(){delete troot;LNode* p=lroot;while(p=lroot->next)1{{ lroot=p->next; delete p; p=lroot;}delete p; };2. 建立哈夫曼树void Huffman::HTree(){LNode* p=lroot; int a=0;troot=new TNode[2*Letter-1]; //2n-1 while (p=p->next){troot[a].weight=p->weight; troot[a].Parent=-1; troot[a].Lchild=-1; troot[a].Rchild=-1; a++;};for (int i=Letter;i<2*Letter-1;i++)troot[i].Parent=-1; int x,y,begin=0;for (int j=Letter;j<2*Letter-1;j++) while (troot[begin].Parent!=-1)begin++;个结点// 建立叶子节点// 是两个最小值的角标SelectMin(x,y,begin,j);troot[j].weight=troot[x].weight+troot[y].weight;troot[j].Lchild=x;troot[j].Rchild=y;troot[j].Parent=-1;troot[x].Parent=j;troot[y].Parent=j;}};3.统计字符的频率void Huffman::List(char a[]){LNode *p=lroot;int i=0;while(a[i]!='\0'){{while (p&&p->ch!=a[i]) // 查找链表中没有该字符或者找到该字符p=p->next;if (!p) // 如果没有该字符,创建节点。

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

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

软件学院设计性实验报告理解哈夫曼树的特征及其应用;在对哈夫曼树进行理解的基础上,构造哈夫曼树,并用构造的哈夫曼树进行编码和译码;通过该实验,使学生对数据结构的应用有更深层次的理解。

二、实验仪器或设备学院提供公共机房,1台/学生微型计算机。

三、总体设计(设计原理、设计方案及流程等)1.问题描述:利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。

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

对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。

试为这样的信息收发站设计一个哈夫曼编/译码系统。

2.一个完整的系统应具有以下功能:1)初始化(Initialzation)。

从数据文件DataFile.dat中读入字符及每个字符的权值,建立哈夫曼树HuffTree;2)编码(EnCoding)。

用已建好的哈夫曼树,对文件ToBeTran.dat中的文本进行编码形成报文,将报文写在文件Code.txt中;3)译码(Decoding)。

利用已建好的哈夫曼树,对文件CodeFile.dat中的代码进行解码形成原文,结果存入文件Textfile.txt中;4)输出(Output): 输出DataFile.dat中出现的字符以及各字符出现的频度(或概率);输出ToBeTran.dat及其报文Code.txt;输出CodeFile.dat及其原文Textfile.txt;要求:所设计的系统应能在程序执行的过程中,根据实际情况(不同的输入)建立DataFile.dat、ToBeTran.dat和CodeFile.dat三个文件,以保证系统的通用性。

四、实验步骤(包括主要步骤、代码分析等)1)编写C语言程序#include<string.h>#include<malloc.h>#include<stdio.h>#include<iostream.h>#include<math.h>#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1typedef struct{char data;int weight;int parent,lchild,rchild;}HTNode,*HuffmanTree;typedef char **HuffmanCode;void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,char *d,int *w,int n) //构造哈弗曼函数HT,构造编码HC{void select(HuffmanTree HT,int n,int &s1,int &s2);int m,c,f,j;HuffmanTree p;int i,s1,s2,start;char *cd;m=2*n-1; //m为结点数,n为叶子数HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));p=HT;p++;for(i=1;i<=n;i++,p++) //将叶子的值输入HT中{p->data=d[i]; //={*d,*w,0,0,0};p->weight=w[i];p->parent=0;p->lchild=0;p->rchild=0;}for (i=n+1;i<=m;i++,p++) //={'#',0,0,0,0} {p->data='#';p->weight=0;p->parent=0;p->lchild=0;p->rchild=0;}s1=1;s2=2;for(i=n+1;i<=m;i++) //构建哈夫曼树{select(HT,i-1,s1,s2);HT[i].lchild=s1;HT[i].rchild=s2;HT[i].weight=HT[s1].weight+HT[s2].weight;HT[s1].parent=i;HT[s2].parent=i;}HC=(HuffmanCode)malloc((n+1)*sizeof(HuffmanTree)); //开辟空间,编码cd=(char *)malloc(n*sizeof(char));cd[n-1]='\0';for (i=1;i<=n;++i){start=n-1;for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent){if(HT[f].lchild==c)cd[--start]='0';elsecd[--start]='1';}HC[i]=(char*)malloc((n-start)*sizeof(char));strcpy(HC[i],&cd[start]);printf("%c的编码是:",HT[i]);puts(HC[i]);}free(cd);}void select(HuffmanTree HT,int n,int &s1,int &s2) //求最小两数{int i,t;s1=1;s2=2;while(HT[s1].parent!=0)s1++;while((HT[s2].parent!=0)||(s1==s2))s2++;/*for(i=1;i<=n;i++){if(HT[s1].weight>HT[i].weight&&HT[i].parent==0&&s2!=i)s1=i;}if(HT[s1].weight>HT[s2].weight){t=s1;s1=s2;s2=t;}for(i=1;i<=n;i++){if(s1!=i){if(HT[s2].weight>HT[i].weight&&HT[i].parent==0)s2=i;}}*/for(i=1;i<=n;i++){if(s1!=i&&i!=s2){if(HT[i].weight<HT[s1].weight&&HT[i].parent==0&&i!=s2) {if(HT[s1].weight<HT[s2].weight) s2=s1;s1=i;}elseif(HT[i].weight<HT[s2].weight&&HT[i].parent==0&&s1!=i) s2=i;}}}void translation(HuffmanTree HT,int num){char str[20];int i,t=num;printf("请输入由0或1组成的编码:");cin>>str;//t=HT; //t为树的指向各节点的指针for(i=0;i<(strlen(str));i++){if(str[i]=='0')t=HT[t].lchild;elseif(str[i]=='1')t=HT[t].rchild;else{printf("编码输入错误");break;}if(!(HT[t].lchild&&HT[t].rchild)){printf("%c",HT[t].data);t=num;}}printf("\n");}void main(){void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,char d[],int w[],int n);void translation(HuffmanTree HT,int num);HuffmanTree HT=NULL;HuffmanCode HC=NULL;char data,n,*p,*d;int *w,wei,i,num;printf("please intput character number:");scanf("%d",&n);d=(char*)malloc((n+1)*sizeof(char));w=(int *)malloc((n+1)*sizeof(int));printf("请输入Huffman树中的字符:\n");for(i=1;i<=n;i++){cin>>data;d[i]=data;}printf("请输入%d次位权\n:",n);for (i=1;i<=n;i++){cin>>wei;w[i]=wei;}num=2*n-1;HuffmanCoding(HT,HC,d,w,n);translation(HT,num);}2)程序分析此实验是构造哈夫曼树,求出哈夫曼编码然后输出构造哈夫曼树的算法操作时选出两棵根节点的权值最小的一颗树的左右子树,且置新树的根节点的权值为其左右子树上根节点的权值之和,根据哈夫曼树求出带权路径的算法操作是用递归调用的方法。

北邮信通院数据结构实验报告三哈夫曼编码器之欧阳引擎创编

北邮信通院数据结构实验报告三哈夫曼编码器之欧阳引擎创编

数据结构实验报告欧阳引擎(2021.01.01)实验名称:实验三树——哈夫曼编/解码器学生姓名:班级:班内序号:学号:日期: 2014年12月11日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、根据输入的字符串中每个字符出现的次数统计频度,对没有出现的字符一律不用编码。

2. 程序分析2.1 存储结构Huffman树给定一组具有确定权值的叶子结点,可以构造出不同的二叉树,其中带权路径长度最小的二叉树称为Huffman树,也叫做最优二叉树。

weight lchild rchildparent 2-1-1-15-1-1-1 6-1-1-1 7-1-1-1 9-1-1-1weight lchild rchild parent2-1-155-1-156-1-167-1-169-1-17701713238165482967-12.2关键算法分析(1)计算出现字符的权值利用ASCII码统计出现字符的次数,再将未出现的字符进行筛选,将出现的字符及頻数存储在数组a[]中。

北邮 数据结构实验报告2

北邮 数据结构实验报告2

数据结构实验报告实验名称:__ 哈夫曼树________学生姓名:______ 蔡宇豪_________________班级:________ 2 5____________________ 班内序号:__________15__________________学号:_________2012210673___________________ 日期:________2013.11.24____________________2. 程序分析2.1 存储结构哈夫曼树结点的存储结构包括双亲域parent,左子树lchild,右子树rchild,还有字符word,权重weight,编码code对用户输入的信息进行统计,将每个字符作为哈夫曼树的叶子结点。

统计每个字符出现的次数作为叶子的权重,统计次数可以根据每个字符不同的ASCII码,根据叶子结点的权重建立一个哈夫曼树2.2 关键算法分析要实现哈夫曼解/编码器,就必须用二叉树结构建立起哈夫曼树,其中有4个关键算法,首先是初始化函数,统计每个字符的频度,并建立起哈夫曼树;然后是建立编码表,将每个字符的编码输出;再次就是编码算法,根据编码表对输入的字符串进行编码,并将编码后的字符串输出;最后是译码算法,利用已经建好的赫夫曼树对编码后的字符串进行译码,并输出译码结果。

1.初始化函数int i,j;for(i=0;i<MAX;i++)a[i]=0; //先将a[]数组中每个值都赋为,不然程序会运行出错?for(i=0;s[i]!='\0';i++) //'\0'字符串结束标志{for(j=0;j<n;j++){if(s[i]==b[j]) //判断该字符是否已经出现过break;}if(j<n) //该字符出现过,对应计数器加一a[j]++;else//该字符为新字符,上面的循环全部运行完毕,j=n,记录到b[j]中,对应计数器加一{b[j]=s[i];a[j]++;n++; //出现的字符种类数加一}}//cout<<"共有"<<n<<"种字符,分别为:"<<endl;for(i=0;i<n;i++)cout<<b[i]<<"出现次数为:"<<a[i]<<endl;HTree=new HNode[2*n-1] ; //哈夫曼树初始化for(int i=0;i<2*n-1;i++){if(i<n){HTree[i].weight=a[i];}else{HTree[i].weight=0;}HTree[i].LChild=-1;HTree[i].RChild=-1;HTree[i].parent=-1;}int x,y,m1,m2; //x,y用于存放权值最小结点在数组中的下标for(int i=n;i<2*n-1;i++) //开始建哈夫曼树{//找出权值最小的结点m1=m2=MAX; //MAX=1000x=y=0;for(int j=0;j<i;j++){if(HTree[j].weight<m1&&HTree[j].parent==-1){m2=m1;m1=HTree[j].weight;x=j;}else if(HTree[j].weight < m2 && HTree[j].parent==-1){m2=HTree[j].weight;y=j;}}HTree[x].parent=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;2.生成编码表HCodeTable=new HCode[n];for(int i=0;i<n;i++){HCodeTable[i].data=b[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';elseHCodeTable[i].code[k]='1';k++;child=parent;parent=HTree[child].parent;}HCodeTable[i].code[k]='\0';cout<<b[i]<<"的编码:";for(int j=k-1;j>=0;j--)cout<<HCodeTable[i].code[j];cout<<endl;}3.编码cout<<"编码后的字符串为:";while(*d!='\0'){for(int i=0;i<n;i++){if(b[i]==*d) //判断,每当出现一种时,就找到对应编码并输出{int k=strlen(HCodeTable[i].code);for(int j=k-1;j>=0;j--){*s=HCodeTable[i].code[j];cout<<*s;s++;}}}d++;}*s='\0';cout<<endl;【计算关键算法的时间、空间复杂度】关键算法A的时间复杂度为O(n),关键算法B的时间复杂度为O(n),关键算法C的时间复杂度为O(n),关键算法D的时间复杂度为O(n).2.3 其他程序完整代码:#include<iostream>using namespace std;const int MAX=1000;struct HNode{int weight;int parent;int LChild;int RChild;};struct HCode{char data;char code[200];};class Huffman{private:HNode *HTree; //哈夫曼树HCode *HCodeTable; //哈夫曼编码表char b[MAX]; //记录出现的字符int a[MAX]; //记录每个字符出现的次数,即权值static int n; //字符的种类数(静态变量)public:void init(char s[]); //初始化void init1(char s[]);void CreateCodeTable(); //创建编码表void Encoding(char *s,char *d); //编码void Decoding(char *s,char *d); //解码int count1() //算编码前长度{int q1=0;for(int i=0;i<n;i++){q1+=8*a[i];}return q1;}int count2() //算编码后长度{int q2=0;for(int i=0;i<n;i++){q2+=strlen(HCodeTable[i].code)*a[i];}return q2;}};int Huffman::n=0;void Huffman::init(char s[]){int i,j;for(i=0;i<MAX;i++)a[i]=0; //先将a[]数组中每个值都赋为,不然程序会运行出错?for(i=0;s[i]!='\0';i++) //'\0'字符串结束标志{for(j=0;j<n;j++){if(s[i]==b[j]) //判断该字符是否已经出现过break;}if(j<n) //该字符出现过,对应计数器加一a[j]++;else//该字符为新字符,上面的循环全部运行完毕,j=n,记录到b[j]中,对应计数器加一{b[j]=s[i];a[j]++;n++; //出现的字符种类数加一}}//cout<<"共有"<<n<<"种字符,分别为:"<<endl;for(i=0;i<n;i++)cout<<b[i]<<"出现次数为:"<<a[i]<<endl;HTree=new HNode[2*n-1] ; //哈夫曼树初始化for(int q=0;q<2*n-1;q++){if(q<n){HTree[q].weight=a[q];}else{HTree[q].weight=0;}HTree[q].LChild=-1;HTree[q].RChild=-1;HTree[q].parent=-1;}int x,y,m1,m2; //x,y用于存放权值最小结点在数组中的下标for(int w=n;w<2*n-1;w++) //开始建哈夫曼树{//找出权值最小的结点m1=m2=MAX; //MAX=1000x=y=0;for(int j=0;j<i;j++){if(HTree[j].weight<m1&&HTree[j].parent==-1){m2=m1;m1=HTree[j].weight;x=j;}else if(HTree[j].weight < m2 && HTree[j].parent==-1){m2=HTree[j].weight;y=j;}}HTree[x].parent=HTree[y].parent=w;HTree[w].weight=HTree[x].weight+HTree[y].weight;HTree[w].LChild=x;HTree[w].RChild=y;HTree[w].parent=-1;}}void Huffman::init1(char s[]){int i,j;for(i=0;i<MAX;i++)a[i]=0; //先将a[]数组中每个值都赋为,不然程序会运行出错?for(i=0;s[i]!='\0';i++) //'\0'字符串结束标志{for(j=0;j<n;j++){if(s[i]==b[j]) //判断该字符是否已经出现过break;}if(j<n) //该字符出现过,对应计数器加一a[j]++;else//该字符为新字符,上面的循环全部运行完毕,j=n,记录到b[j]中,对应计数器加一{b[j]=s[i];a[j]++;n++; //出现的字符种类数加一}}HTree=new HNode[2*n-1] ; //哈夫曼树初始化for(int e=0;e<2*n-1;e++){if(e<n){HTree[e].weight=a[e];}else{HTree[e].weight=0;}HTree[e].LChild=-1;HTree[e].RChild=-1;HTree[e].parent=-1;}int x,y,m1,m2; //x,y用于存放权值最小结点在数组中的下标,m1,m2用于存放两个无父结点且结点权值最小的两个结点for(int r=n;r<2*n-1;r++) //开始建哈夫曼树{//找出权值最小的结点m1=m2=MAX; //MAX=1000x=y=0;for(int j=0;j<r;j++){if(HTree[j].weight<m1&&HTree[j].parent==-1){m2=m1;//y=x;m1=HTree[j].weight;x=j;}else if(HTree[j].weight < m2 && HTree[j].parent==-1){m2=HTree[j].weight;y=j;}}HTree[x].parent=HTree[y].parent=r;HTree[r].weight=HTree[x].weight+HTree[y].weight;HTree[r].LChild=x;HTree[r].RChild=y;HTree[r].parent=-1;}}void Huffman::CreateCodeTable() //生成编码表{HCodeTable=new HCode[n];for(int i=0;i<n;i++){HCodeTable[i].data=b[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';elseHCodeTable[i].code[k]='1';k++;child=parent;parent=HTree[child].parent;}HCodeTable[i].code[k]='\0';cout<<b[i]<<"的编码:";for(int j=k-1;j>=0;j--)cout<<HCodeTable[i].code[j];cout<<endl;}}void Huffman::Encoding(char *s,char *d) // 编码算法 //d为字符串{cout<<"编码后的字符串为:";while(*d!='\0'){for(int i=0;i<n;i++){if(b[i]==*d) //判断,每当出现一种时,就找到对应编码并输出{int k=strlen(HCodeTable[i].code);for(int j=k-1;j>=0;j--){*s=HCodeTable[i].code[j];cout<<*s;s++;}}}d++;}*s='\0';cout<<endl;}void Huffman::Decoding(char *s,char *d) //s为编码串{cout<<"解码后的字符串为:";while(*s!='\0'){int parent=2*n-1-1;while(HTree[parent].LChild!=-1){if(*s=='0')parent=HTree[parent].LChild;elseparent=HTree[parent].RChild;s++;}*d=HCodeTable[parent].data;cout<<*d;d++;}cout<<endl;void main(){int i=0;char d[MAX];char s[MAX];cout<<"请输入字符串:";while((d[i]=getchar())!='\n')i++;d[i]='\0';Huffman h;cout<<"哈夫曼功能:"<<endl;cout<<"1.统计字符种类及出现次数"<<endl;cout<<"2.数据的编码解码"<<endl;cout<<"3.分析压缩效果"<<endl;int q;for(;;){cout<<"请输入(1~3)"<<endl;cin>>q;bool x=0;switch (q){case 1:h.init(d);break;case 2:h.init1(d);h.CreateCodeTable();h.Encoding(s,d);h.Decoding(s,d);break;case 3:cout<<"编码前的长度为:"<<h.count1()<<endl;cout<<"编码后的长度为:"<<h.count2()<<endl;cout<<"压缩比为:"<<(h.count2()*1.0/h.count1())<<endl;break;default:cout<<"请输入选择!!!!!"<<endl;break;}}3.}程序运行结果分析输入:I love data Structure, I love Computer。

大数据的结构哈夫曼编码实验报告材料

大数据的结构哈夫曼编码实验报告材料

数据结构实验报告――实验五简单哈夫曼编/译码的设计与实现本实验的目的是通过对简单哈夫曼编/译码系统的设计与实现来熟练掌握树型结构在实际问题中的应用。

此实验可以作为综合实验,阶段性实验时可以选择其中的几个功能来设计和实现。

一、【问题描述】利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。

但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码,此实验即设计这样的一个简单编/码系统。

系统应该具有如下的几个功能:1、接收原始数据。

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

2、编码。

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

3、译码。

利用已建好的哈夫曼树将文件code.dat中的代码进行译码,结果存入文件textfile.dat中。

4、打印编码规则。

即字符与编码的一一对应关系。

二、【数据结构设计】1、构造哈夫曼树时使用静态链表作为哈夫曼树的存储。

在构造哈夫曼树时,设计一个结构体数组HuffNode保存哈夫曼树中各结点的信息,根据二叉树的性质可知,具有n个叶子结点的哈夫曼树共有2n-1个结点,所以数组HuffNode的大小设置为2n-1,描述结点的数据类型为:typedef struct{int weight;//结点权值int parent;int lchild;int rchild;char inf;}HNodeType;2、求哈夫曼编码时使用一维结构数组HuffCode作为哈夫曼编码信息的存储。

求哈夫曼编码,实质上就是在已建立的哈夫曼树中,从叶子结点开始,沿结点的双亲链域回退到根结点,没回退一步,就走过了哈夫曼树的一个分支,从而得到一位哈夫曼码值,由于一个字符的哈夫曼编码是从根结点到相应叶子结点所经过的路径上各分支所组成的0、1序列,因此先得到的分支代码为所求编码的低位码,后得到的分支代码位所求编码的高位码,所以设计如下数据类型:#define MAXBIT 10typedef struct{int bit[MAXBIT];int start;}HcodeType;3、文件nodedata.dat、code.dat和textfile.dat。

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

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

数据结构哈夫曼编码实验报告【正文】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. 进一步熟悉编程语言的使用。

实验过程1. 构建哈夫曼树首先,我们需要根据给定的字符频率表构建哈夫曼树。

哈夫曼树是一种特殊的二叉树,其叶子节点表示字符,而非叶子节点表示字符的编码。

构建哈夫曼树的过程如下:1. 根据给定的字符频率表,将每个字符视为一个节点,并按照频率从小到大的顺序排列。

2. 将频率最小的两个节点合并为一个新节点,并将其频率设置为两个节点的频率之和。

这个新节点成为新的子树的根节点。

3. 将新节点插入到原来的节点列表中,并继续按照频率从小到大的顺序排序。

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

2. 哈夫曼编码表在构建完哈夫曼树后,我们需要根据哈夫曼树每个字符的哈夫曼编码表。

哈夫曼编码表是一个字典,用于存储每个字符对应的编码。

哈夫曼编码表的过程如下:1. 从哈夫曼树的根节点出发,遍历整个树。

2. 在遍历的过程中,维护一个路径,用于记录到达每个字符节点的路径,0表示左子树,1表示右子树。

3. 当到达一个字符节点时,将路径上的编码存储到哈夫曼编码表中对应的字符键下。

3. 压缩数据有了哈夫曼编码表后,我们可以使用哈夫曼编码对数据进行压缩。

将原本以字符表示的数据,转换为使用哈夫曼编码表示的二进制数据。

压缩数据的过程如下:1. 将待压缩的数据转换为对应的哈夫曼编码,将所有的编码连接成一个字符串。

2. 将该字符串表示的二进制数据存储到文件中,同时需要保存哈夫曼编码表以便解压时使用。

实验结果通过实验,我们成功实现了哈夫曼编码的构建和使用。

北邮信通院数据结构实验报告三哈夫曼编码器

北邮信通院数据结构实验报告三哈夫曼编码器

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

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

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

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

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

测试数据:I lovedata Structure, I loveputer。

I willtrymy best tostudy data Structure、提示:1、用户界面可以设计为“菜单”方式:能够进行交互。

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

2、程序分析2、1存储结构Huffman树给定一组具有确定权值得叶子结点,可以构造出不同得二叉树,其中带权路径长度最小得二叉树称为Huffman树,也叫做最优二叉树。

weightlchildrchild parent2-1-1-15-1-1-16-1-1-17-1-1-19-1-1-1weight lchild rchildparent 2-1-155-1-156-1-167-1-169-1-17701713238165482967-12、2 关键算法分析(1)计算出现字符得权值利用ASCII码统计出现字符得次数,再将未出现得字符进行筛选,将出现得字符及頻数存储在数组a[]中。

void Huffman::Init(){ﻩintnNum[256]= {0};//记录每一个字符出现得次数int ch = cin、get();int i=0;ﻩwhile((ch!='\r') && (ch!='\n'))ﻩ{ﻩﻩnNum[ch]++; //统计字符出现得次数ﻩstr[i++] = ch; //记录原始字符串ﻩch = cin、get(); //读取下一个字符ﻩ}str[i]='\0';n = 0;for ( i=0;i<256;i++)ﻩ{ﻩﻩif(nNum[i]>0) //若nNum[i]==0,字符未出现ﻩ{l[n] = (char)i;ﻩa[n] = nNum[i];n++;ﻩ}}}时间复杂度为O(1);(2)创建哈夫曼树:算法过程:Huffman树采用顺序存储---数组;数组得前n个结点存储叶子结点,然后就是分支结点,最后就是根结点;首先初始化叶子结点元素—循环实现;以循环结构,实现分支结点得合成,合成规则按照huffman树构成规则进行。

北邮信通院数据结构实验报告三哈夫曼编码器之欧阳化创编

北邮信通院数据结构实验报告三哈夫曼编码器之欧阳化创编

数据结构实验报告实验名称:实验三树——哈夫曼编/解码器学生姓名:班级:班内序号:学号:日期: 2014年12月11日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、根据输入的字符串中每个字符出现的次数统计频度,对没有出现的字符一律不用编码。

2. 程序分析2.1 存储结构Huffman树给定一组具有确定权值的叶子结点,可以构造出不同的二叉树,其中带权路径长度最小的二叉树称为Huffman树,也叫做最优二叉树。

weight lchild rchildparent 2-1-1-15-1-1-16-1-1-17-1-1-19-1-1-1weight lchild rchild parent2-1-155-1-156-1-167-1-169-1-17701713238165482967-12.2关键算法分析(1)计算出现字符的权值利用ASCII码统计出现字符的次数,再将未出现的字符进行筛选,将出现的字符及頻数存储在数组a[]中。

void Huffman::Init(){int nNum[256]= {0}; //记录每一个字符出现的次数int ch = cin.get();int i=0;while((ch!='\r') && (ch!='\n')){nNum[ch]++; //统计字符出现的次数str[i++] = ch; //记录原始字符串ch = cin.get(); //读取下一个字符}str[i]='\0';n = 0;for ( i=0;i<256;i++){if (nNum[i]>0) //若nNum[i]==0,字符未出现{l[n] = (char)i;a[n] = nNum[i];n++;}}}时间复杂度为O(1);(2)创建哈夫曼树:算法过程:Huffman树采用顺序存储---数组;数组的前n个结点存储叶子结点,然后是分支结点,最后是根结点;首先初始化叶子结点元素—循环实现;以循环结构,实现分支结点的合成,合成规则按照huffman树构成规则进行。

北邮数据结构 实验报告四——哈夫曼树

北邮数据结构 实验报告四——哈夫曼树

数据结构实验报告实验名称:实验4——题目4——哈夫曼树学生姓名:班级:班内序号:学号:日期:2017年1月6日1.实验要求利用二叉树结构实现哈夫曼编/解码器。

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

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

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

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

2. 程序分析2.1 存储结构本实验的存储结构为哈夫曼树与哈夫曼编码表哈夫曼树:存储结构:struct HNode//哈夫曼树的结点结构{int weight;//结点权值int parent;//双亲指针int LChild;//左孩子指针int RChild;//右孩子指针};哈夫曼编码表:struct HCode//编码表的结点结构{char data;//字符char code[10];//编码int k;//码长};存储结构:2.2 关键算法分析一、初始化:步骤:1、设立数组,记录每一个字符出现的次数与字符对应的ASCII码2、以字符不是回车或换行遍历输入的字符数组3、将存储出现次数大于0的字符存储进叶子节点数组4、相对应的,存储叶子结点的数据域字符出现的次数。

时间复杂度:O(n)空间复杂度:O(n)二、创建哈夫曼树步骤:1、创建2n-1个数节点2、将权值数组依次赋值进0到n-1的权值节点中3、从0到i-1(最开始等于n-1)选择两个权值最小的节点x、y,将其连接为i节点的左右孩子,改变x、y的双亲指针为i节点4、I++,循环步骤4直到2n-1时间复杂度:O(n^2)空间复杂度 O(n)三、创建哈夫曼编码表步骤:1、创建n个编码表节点2、依次将叶子节点的字符放入编码表节点数据域中3、对每个编码表对应的树结点,向根节点开始回溯(为父节点的左孩子编码值为0,右孩子为1,不断上移,直到根节点)4、进行倒置时间复杂度O(n)空间复杂度 O(n)四、编码步骤:1、新建编码数组2、从源码第一个字符开始在编码表中寻找到相应字符后将编码复制进编码数组3、计算压缩比时间复杂度O(n+e) n为源码 e为编码数组长度空间复杂度O(n)五、解码步骤:1、从根节点开始,按照编码串寻找(0为左子树,1为右子树)2、直到该节点无子树,将该节点(也就是叶子节点)字符放入解码串中3、重复步骤1、2直到编码串结束时间复杂度O(n) n为编码串长度空间复杂度O(e) e为原串长度六、打印哈夫曼树步骤:1、从根节点开始第m层前方空m个格2、叶子结点先输出数据域再在下一行输出权值3、重复输出,递归调用,直到叶子。

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

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

数据结构实验报告实验题目:Huffman编码与解码姓名:学号:院系:实验名称:Huffman编码与解码实验问题描述:本实验需要以菜单形式完成以下功能:1.输入电文串2.统计电文串中各个字符及其出现的次数3.构造哈弗曼树4.进行哈弗曼编码5.将电文翻译成比特流并打印出来6.将比特流还原成电文数据结构的描述:逻辑结构:本实验可用二叉树实现,其逻辑结构为一对二的形式,即一个结点对应两个结点。

在实验过程中我们也应用到了栈的概念。

存储结构:使用结构体来对数据进行存储:typedef struct{int weight;int parent,lc,rc;}HTNode,*HuffmanTree;typedef struct LNode{char *elem;int stacksize;int top;}SqStack;在main函数里面定义一个哈弗曼树并实现上述各种功能。

程序结构的描述:本次实验一共构造了10个函数:1.void HuffTree(HuffmanTree &HT,int n[],int mun);此函数根据给定的mun个权值构建哈弗曼树,n[]用于存放num个权值。

2.void Select(HuffmanTree &HT,int n,int i,int &s1,int &s2);此函数用于在HT[1,i-1]中选择parent为0且weight为最小的两个结点,其下标分别为s1,s2.3.void HuffmanCoding(HuffmanTree HT,char **&HC,int n);此函数从哈弗曼树HT上求得n 个叶子结点的哈弗曼编码并存入数组HC中。

4.void Coding(HuffmanTree HT,char **HC,int root,SqStack &S);此函数用于哈弗曼编码,先序遍历哈弗曼树HT,求得每个叶子结点的编码字符串,存入数组HC,S为一个顺序栈,用来记录遍历路径,root是哈弗曼数组HT中根结点的位置下标。

Huffman树实验报告

Huffman树实验报告

Huffman编码及译码实验报告姜流PB12210218问题的描述:对传输的电文统计出现的字符及次数并进行Huffman编码,生成Huffman树,编码形式为1,0两种数字,打印出比特流,再将比特流译码成字符。

问题的输入输出:1.用户从键盘输入任意长度的任意字符,打印出出现的不同字符及次数;2.根据不同字符的权重生成Huffmam树并先序打印出来;3.根据Huffman树进行编码,打印出来比特流;4.将比特流转换成电文字符打印出来;算法的描述:1.统计字符功能的算法:用p指向输入的字符串,另开两个数组,一个是ch[],用来存放不同的字符,另一个是k[]用来存放各个不同字符的次数,对输入的字符串逐个字符依次比较,就可以完成字符统计功能。

2.生成Huffamn树算法:采用经典的生成算法,每次找两个权重最小的节点合并成一个节点,一直到最后没有节点,本次实验采用左孩子权重小于右孩子的规则进行生成。

3.Huffman编码算法:先序遍历生成的Huffman树,每次向左拐就将1压栈,向右拐就将0压栈,直到访问到叶子,将栈里的1,0字符copy到相应字符的编码,就然后进行出栈操作,直到访问完全部的节点。

4.Hufman译码算法:对输入的比特流进行逐个访问,若为1,在Huffman树上左拐,若为0,在Huffman树上右拐,一直到叶子,则叶子上的字符就是比特流对应的字符,然后再从根节点开始译码,直到比特流结束,即可译出所有的电文打印。

数据结构的描述:1.存放编码的栈:typedef struct{ char *base;char *top;int stacksize;}SqStack;2.Huffman树的节点:typedef struct{int weight,parent,lchild,rchild;}HTNode;3.Huffman树结构体:typedef struct{HTNode *Htree;int root;}HuffmanTree;5.双指针类型:存放每个字符对应编码#define HuffmanCode char **HuffmanCode HC=NULL;//初始时为空程序结构的描述:Status EmptyStack(SqStack s);Status Increment(SqStack &s);void InitStack(SqStack &s);void push(SqStack &s,char e);void pop(SqStack &s,char &e);Status Getop(SqStack &s,char &e);int StackLength(SqStack S);//以上关于栈的通用函数void select(HTNode *HT,int k,int &s);void CreateHuffman(HuffmanTree &T,int *w,int n);void Coding(HuffmanTree T,int i,SqStack &S,char **HC);void HuffmanCoding(HuffmanTree T,HuffmanCode &HC,int n);void Decoding(HuffmanTree T,char *s);void Print(HuffmanTree T);int compare(char ch[],char cha,int &n);void stat(char *s,char ch[],int k[],int &count);//完成各功能的函数main{ //主函数中对各个子函数调用顺序stat(s,ch,k,count);//以上为字符统计功能CreateHuffman(T,w,n);Print(T);//以上为构造HuffmanTree,并打印HuffmanCoding(T,HC,n);//以上为将每个字符翻译成比特文p=s;//puts(s);while(*p){i=compare(ch,*p,n);//printf("%d\n",n);printf("%s",HC[n+1]);p++;}printf("\n");//以上为将电文翻译为比特文printf("input the bits\n");gets(s1);Decoding(T,s1);//译码}调试分析:1.字符统计功能:结果是对的2.生成Huffman树并打印:结果是与输入相符合的3.将各个字符编码,成为比特流:结果很正确4.将比特流译码成为电文:结果输入的字符时相同的调试中遇到的问题:在创建Huffman树时,一开始是用scanf,但是调试的时候却总是不正确,查阅scanf函数原型后发现scanf在读字符时把空格也认为是有效字符,因此空格不能作为间隔符,建议用getchar(),gets()等函数。

哈夫曼树实验报告

哈夫曼树实验报告

一、实验目的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)对给定的文本进行了编码和译码,验证了编码的正确性。

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

数据结构实验报告实验名称:哈夫曼树学生:袁普班级:2013211125班班序号:14号学号:2013210681 日期:2014年12月1.实验目的和容利用二叉树结构实现哈夫曼编/解码器。

基本要求: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 study dataStructure.提示: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),要遍历一遍字符串,时间复[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] 算法基本思想:根据哈夫曼树构建要求,选取权值最小的两个结点结合,新结点加入数组,再继续选取最小的两个结点继续构建。

[3] 算法空间、时间复杂度分析:取决于叶子节点个数,时间复杂度O(n),空间[4] 代码逻辑HTree=new HNode[2*leaf-1]; n2=n0-1,一共需要2n-1个结点空间for(int i=0;i<leaf;i++){HTree[i].weight=weight[i]; 给每个结点附权值HTree[i].lchild=-1; 初始化左右孩子和父节点,都为-1HTree[i].rchild=-1;HTree[i].parent=-1;}int x,y; //用于记录两个最小权值for(int i=leaf;i<2*leaf-1;i++){Selectmin(HTree,i,x,y); 选出两个最小权值的结点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; 父节点的父节点设为-1}算法3:void Selectmin(HNode*hTree,int n,int&i1,int &i2);[1] 算法功能:从现有的结点中选择出两个最小的结点,返回其位置[2] 算法基本思想:先选出两个没有构建的结点,然后向后依次比较,筛选出最小的两个结点[3] 算法空间、时间复杂度分析:空间复杂度O(1),要遍历所有结点,时间复杂度O(N)[4] 代码逻辑int i;for(i=0;i<n;i++) //n为现在有的结点个数,是个变化值,会有相加后的新权值加入{if(hTree[i].parent==-1) //父节点不是-1意味着这个结点还没有被选择过{i1=i; 记录结点位置break;}}i++; //执行一遍for循环就加1,意为下次查找从当前位置开始查找for(;i<n;i++){if(hTree[i].parent==-1){i2=i; 记录第二个没选择过的结点编号break;}}if(hTree[i1].weight>hTree[i2].weight) 进行比较,使I1为最小的,I2为第二小的{int j=0;j=i2;i2=i1;i1=j;}i++;for(;i<n;i++) 将I1 I2 与后面的结点进行比较{if(hTree[i].parent==-1&&hTree[i].weight<hTree[i1].weight) 如果结点小于I1 {i2=i1; 使I2=I1 I1=新结点i1=i;}else if(hTree[i].parent==-1&&hTree[i].weight<hTree[i2].weight){ I1《新结点《I2,使I2为新节点i2=i;}}算法4:void CreateT able();[1] 算法功能:对出现的字符进行编码[2] 算法基本思想:根据字符在哈夫曼树中的位置,从下到上编码,是左孩子编0,右孩子编1[3] 算法空间、时间复杂度分析:空间复杂度O(1),要遍历data数组,时间复杂度0(N)[4] 代码逻辑HCodeTable=new HCode[leaf]; 新建编码结点,个数为叶子节点个数for(int i=0;i<leaf;i++){HCodeT able[i].data=data[i];int child=i; 初始化要编码的结点的位置int parent=HTree[i].parent; 初始化父结点int k=0; //统计编码个数while(parent!=-1){if(child==HTree[parent].lchild)HCodeT able[i].code[k]='0'; //左孩子标‘0’elseHCodeTable[i].code[k]='1'; //右孩子标‘1’k++;child=parent; 孩子结点上移parent=HTree[child].parent; 父节点也上移}HCodeT able[i].code[k]='\0'; //将编码反向char code[100];for(int u=0;u<k;u++)code[u]=HCodeTable[i].code[k-u-1];for(int u=0;u<k;u++)HCodeTable[i].code[u]=code[u];cout<<data[i]<<"的哈夫曼编码为:";cout<<HCodeT able[i].code<<endl;length3[i]=k; //每一个字符编码的长度,为求编码总长度做准备}算法5:void Encoding();[1] 算法功能:对输入的字符串进行编码[2] 算法基本思想:找到每个字符对应的编码,将编码按顺序输出[3] 算法空间、时间复杂度分析:空间复杂度O(1),时间复杂度0(n)[4] 代码逻辑cout<<endl<<"输入的字符串转化为哈夫曼编码为:"<<endl;for (int i=0;str[i]!='\0';i++) 遍历输入的每一个字符{for(int j=0;j<leaf;j++)if(str[i]==HCodeT able[j].data) 找到字符对应的编码{ s1=s1+HCodeTable[j].code; 将所有编码按顺序加起来cout<<HCodeT able[j].code; 输出编码}}cout<<endl;算法6:void Decoding();[1] 算法功能:对编码串进行解码[2] 算法基本思想:找到每段编码对应的字符,输出字符[3] 算法空间、时间复杂度分析:时间复杂度0(N),空间复杂度0(1)[4] 代码逻辑(可用伪代码描述)cout<<"解码后的字符串为: "<<endl;char *s = const_cast<char*>(s1.c_str()); 将编码字符串转化为char while(*s!='\0'){int parent=2*leaf-2; 父节点为最后一个节点while(HTree[parent].lchild!=-1) //还有左子树,不可能是叶子节点{if(*s=='0') 编码为0,为左孩子parent=HTree[parent].lchild;elseparent=HTree[parent].rchild; 编码为1,为右孩子s++;}cout<<HCodeTable[parent].data; 输出字符}cout<<endl;……注意分析程序的时间复杂度、存申请和释放,以及算法思想的体现。

2.4 其他在此次试验中使用了类和STL中的string,使用string可以方便的将单个字符的编码加起来成为总的编码后的数值,再利用STL中的转化函数可以直接将string转化为char,方便进行解码工作。

总而言之,使用STL使得编码大大的简洁了。

相关文档
最新文档