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

合集下载

数据结构实验实验报告Huffman赫夫曼编码及应用

数据结构实验实验报告Huffman赫夫曼编码及应用

实验报告课程名称:数据结构实验名称:赫夫曼编码及应用院(系):计算机与通信工程学院专业班级:计算机科学与技术姓名:学号:指导教师:2020 年 5 月12 日一、实验目的掌握赫夫曼树和赫夫曼编码的基本思想和算法的程序实现。

二、实验内容及要求1、任务描述a.提取原始文件中的数据(包括中文、英文或其他字符),根据数据出现的频率为权重,b.构建Huffman编码表;c.根据Huffman编码表对原始文件进行加密,得到加密文件并保存到硬盘上;d.将加密文件进行解密,得到解码文件并保存点硬盘上;e.比对原始文件和解码文件的一致性,得出是否一致的结论。

2、主要数据类型与变量a.对Huffman树采用双亲孩子表示法,便于在加密与解密时的操作。

typedef struct Huffman* HuffmanTree;struct Huffman{unsigned int weight; //权值unsigned int p, l, r;//双亲,左右孩子};b.对文本中出现的所有字符用链表进行存储。

typedef struct statistics* List;struct statistics {char str; //存储此字符int Frequency; //出现的频率(次数)string FinalNum; //Huffman编码struct statistics* Next;};3、算法或程序模块对读取到的文本进行逐字符遍历,统计每个字符出现的次数,并记录在创建的链表中。

借助Huffman树结构,生成结构数组,先存储在文本中出现的所有字符以及它们出现的频率(即权值),当作树的叶子节点。

再根据叶子节点生成它们的双亲节点,同样存入Huffman树中。

在完成对Huffman树的创建与存储之后,根据树节点的双亲节点域以及孩子节点域,生成每个字符的Huffman编码,并存入该字符所在链表节点的FinalNum域。

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

北邮信通院数据结构实验报告三哈夫曼编码器.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、计算输入的字符串编码前和编码后的长度,并进行分析,讨论赫夫

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

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

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

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

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。

北邮数据结构实验3哈夫曼编码

北邮数据结构实验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. 实验目的本实验旨在通过实践理解哈夫曼编码的原理和实现方法,加深对数据结构中树的理解,并掌握使用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 构建哈夫曼树根据字符频率构建哈夫曼树是哈夫曼编码的核心步骤。

我们可以使用最小堆(优先队列)来高效地构建哈夫曼树。

首先,将每个字符频率作为节点存储到最小堆中。

然后,从最小堆中取出频率最小的两个节点,将它们作为子树构建成一个新的节点,新节点的频率等于两个子节点频率的和。

将新节点重新插入最小堆,并重复该过程,直到最小堆中只剩下一个节点,即哈夫曼树的根节点。

北邮数据结构实验哈夫曼编码解码

北邮数据结构实验哈夫曼编码解码
//Huffman.h
#include<iostream>
#include<string>
using namespace std;
const int NUM=128;
const int M=1000;
int frequency[NUM]={0}; //统计各输入字符频率
void Huffman::CteatCodeTable(char letters[],int frequency[]) //生成编码表
{
Hcodetable=new Hcode[leaf];
for(int i=0,m=0;i<128;i++)
{
if(frequency[i]!=0)
temp[i]=HTree[i].weight;
HTree[i].Lchild=Min1;
HTree[i].Rchild=Min2;
HTree[i].parent=-1;
}
delete temp;
}
///////////////////////////////////////////////////////////////////////////////////////////
void Encode(char *s,char*d); //编码函数
void Decode(char *s,char*d); //解码函数
void Reverse(char a[]); //编码倒置函数
void Huffman::Reverse(char a[])
{
int m=0;
while(a[m]!='\0')

北邮数据结构实验报告三题目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.实验目的本实验旨在研究哈夫曼编码的原理和实现方法,通过实验验证哈夫曼编码在数据压缩中的有效性,并分析其应用场景和优缺点。

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.结论通过本次实验,我们深入了解了哈夫曼编码的原理和实现方法,实践了哈夫曼编码的过程,并对其在数据压缩中的有效性进行了验证。

实验结果表明,哈夫曼编码能够实现较高的压缩率和较高的编解码效率。

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

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

数据结构实验报告实验名称:实验三树——哈夫曼编/解码器学生姓名:班级:班内序号:学号:日期: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树构成规则进行。

数据结构课程设计报告(HuffMan编码器)

数据结构课程设计报告(HuffMan编码器)

《数据结构》课程设计报告题目:HuffMan编码器目录一.问题描述二.基本要求(需求分析)三.•概要设计(设计思想、实现方法、模块设计)四.•详细设计(数据结构设计、算法设计、算法分析)五.测试数据及测试结果六.课程设计小结(心得体会、存在问题、改进措施)一.问题描述利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。

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

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

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

二.基本要求(需求分析)一个完整的系统应具有以下功能:(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中。

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

字符空格 A B C D E F G H I J K L M频度186 64 13 22 32 103 21 15 47 57 1 5 32 20字符N O P Q R S T U V W X Y Z频度57 63 15 1 48 51 80 23 8 18 1 16 1[实现提示](1)编码结果以文本方式存储在文件CodeFile中。

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

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

数据结构实验报告实验名称:实验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、重复输出,递归调用,直到叶子。

数据结构 哈夫曼编码实验报告(2023版)

数据结构 哈夫曼编码实验报告(2023版)

数据结构哈夫曼编码实验报告实验目的:本实验旨在了解和实现哈夫曼编码算法,通过将字符转换为对应的哈夫曼编码来实现数据的压缩和解压缩。

一、引言1.1 背景介绍哈夫曼编码是一种基于字符出现频率的编码方法,通过使用不等长编码来表示不同字符,从而实现数据的高效压缩。

该编码方法在通信、存储等领域有着广泛的应用。

1.2 目标本实验的目标是实现哈夫曼编码算法,通过对给定文本进行编码和解码,验证哈夫曼编码的有效性和可靠性。

二、实验过程2.1 数据结构设计在实现哈夫曼编码算法时,我们需要设计合适的数据结构来存储字符和对应的编码。

常用的数据结构包括树和哈希表。

我们将使用二叉树作为数据结构来表示字符的编码。

2.2 构建哈夫曼树哈夫曼树是由给定字符集合构建而成的最优二叉树。

构建哈夫曼树的过程分为两步:首先根据字符出现频率构建叶子节点,然后通过合并叶子节点和父节点构造哈夫曼树。

2.3 哈夫曼编码表根据构建好的哈夫曼树,我们可以对应的哈夫曼编码表。

哈夫曼编码表由字符和对应的编码组成,可以用于字符的编码和解码。

2.4 文本压缩利用的哈夫曼编码表,我们可以对给定的文本进行压缩。

将文本中的字符逐个替换为对应的哈夫曼编码,从而实现数据的压缩。

2.5 文本解压缩对压缩后的数据进行解压缩时,我们需要利用的哈夫曼编码表,将哈夫曼编码逐个替换为对应的字符,从而还原出原始的文本数据。

三、实验结果我们使用不同长度、不同频率的文本进行了实验。

实验结果表明,哈夫曼编码在数据压缩方面有着显著的效果,可以大大减小数据存储和传输的开销。

四、实验总结通过本实验,我们深入理解了哈夫曼编码算法的原理和实现过程,掌握了数据的压缩和解压缩技术。

哈夫曼编码作为一种经典的数据压缩算法,具有重要的理论意义和实际应用价值。

附件:本文档附带哈夫曼编码实验的源代码和实验数据。

法律名词及注释:在本文档中,涉及的法律名词和注释如下:1.哈夫曼编码:一种数据压缩算法,用于将字符转换为可变长度的编码。

实验三哈夫曼编码

实验三哈夫曼编码

数据结构实验报告1.实验要求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.2. 程序分析2.1 存储结构用二叉树的结构建立哈夫曼树,每个节点的结构是struct HNode{int weight;int parent;int lch;int rch;string code;char data;哈夫曼树的特点:只有度为2的结点和叶子结点,所以具有n个叶子结点的哈夫曼树的结点总数为2n-1顺序存储结构:设置一个的HTree[2*n-1]数组2.2 关键算法分析关键算法一:初始化伪代码:1.将存字符串权值的数组a赋0值,字符种类n赋0值2.获取输入字符串3.遍历输入的字符串,若某个字符出现一次,则在a[i]++,i为该字符ascii码4.遍历a数组,在a[i]有值的地方给HTree[i].weight赋值为a[i],HTree[i].data赋值为ascii码为i的字符源代码:void Huffman::Init() //初始化{for(int m=0;m<256;++m)a[m]=0;cout<<"请输入想要编码的字符"<<endl;getline(cin,str);n=0;cout<<"各字符权值为:"<<endl;for(int i = 0;i!=str.size();++i)++a[str[i]];for(int i=0;i<256;++i)if(a[i]!=0){cout<<char(i)<<" "<<a[i]<<endl;n++;}HTree=new HNode[2*n-1];int j = 0;//j!=n;++j)for(int k=0;k<256;++k){if(a[k]!=0){HTree[j].weight=a[k];HTree[j].data=char(k);j++;}}}时间复杂度:若输入的字符串长度为n,则时间复杂度为O(n)关键算法二:编码:思想(不等长编码)使用频率高的字符,编码长度短;使用频率低的字符,编码长度长;利用不等长编码,可以使报文总长度较短,这也是文件压缩技术的核心。

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

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

数据构造试验汇报――试验五简朴哈夫曼编/译码旳设计与实现本试验旳目旳是通过对简朴哈夫曼编/译码系统旳设计与实现来纯熟掌握树型构造在实际问题中旳应用。

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

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

不过,这规定在发送端通过一种编码系统看待传数据预先编码,在接受端将传来旳数据进行译码,此试验即设计这样旳一种简朴编/码系统。

系统应当具有如下旳几种功能: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。

北邮数据结构实验报告

北邮数据结构实验报告

二、试验内容:
用编码。
利用二叉树结构实现哈夫曼编/解码器
2. 程序分析
1.初始化:能够对输入的任意长度的字符串 s 进行统计,统计每
2.1 存储结构
个字符的频度,并建立哈夫曼树。
二叉树
2.建立编码表:利用已经建好的哈夫曼树进行编码,并将每个字

第1页共3页
本文格式为 Word 版,下载可任意编辑
template class BiTree { public: BiTree(); //构造函数,其前序序列由键盘输入 ~BiTree(void); //析构函数 BiNode* Getroot(); //获得指向根结点的指针 protected: BiNode *root; //指向根结点的头指针 }; //声明类 BiTree 及定义结构 BiNode Data: 二叉树是由一个根结点和两棵互不相交的左右子树构成

第2页共3页
本文格式为 Word 版,下载可任意编辑
{ char data; //编码表中的字符 char code[100]; //该字符对应的编码 }; 待编码字符串由键盘输入,输入时用链表存储,链表节点为 struct Node { char character; //输入的字符 unsigned int count;//该字符的权值 bool used; //建立树的时候该字符是否使用过 Node* next; //保存下一个节点的地址 }; 示意图:
本文格式为 Word 版,下载可任意编辑
北邮数据结构实验报告
符的编码输出。 3.编码:依据编码表对输入的字符串进行编码,并将编码后的
字符串输出。
2021 级数据结构试验报告
4.译码:利用已经建好的哈夫曼树对编码后的字符串进行译码,

数据结构试验报告-哈弗曼编码

数据结构试验报告-哈弗曼编码

实验报告:哈弗曼编码班级:姓名:学号:一、需求分析:1.利用哈弗曼编码进行通信时可以大大提高信息利用率,缩短信息传输时间,降低传输成本;2.哈夫曼编码对终端“明文”文件中的正文进行编码,然后将结果存入“密文”中。

同时也可以将“密文”进行译码,提高了信息的安全性;3.输入输出的要求:要求在输入和输出端都有一个完整的编/译码系统,用户按照提示内容从键盘输入命令,系统根据用户输入的命令在保证界面友好的前提下输出用户所需要的信息,并按要求保存文件,以便保存备份信息;4.测试数据;1)令叶子节点的个数为4,权值集合为:w[]={5,7,11,6};2)令叶子节点的个数为8,权值集合为:w[]={7, 5, 2, 4, 14, 23, 3, 11};二、概要设计:1.定义哈弗曼编码数据结构类型:ADT Huffman{数据对象:D={ ai |ai 属于字符数集,i=1,2,3,4……n n>=0}数据关系:R1={<ai-1, ai >| ai-1, ai ∈D,ai-1< ai ,i=2……n}基本操作:void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n)初始条件:HT,HC,w,n等都存在操作结果:将w数组内的数都转化到HT内的哈夫曼树内,然后将哈夫曼树内的数据转化到HC这个代码中,全部转化成只有0和1这两个二进制数的一串译码。

void Select(HuffmanTree &HT, int s, int &s1, int &s2)初始条件:HT这个哈夫曼树存在操作结果:通过该个函数,将原来的哈夫曼树扩展成为有权值,双亲,左孩子,右孩子等四个值得哈夫曼树。

并用s1,s2两个字将双亲为0中权值最小的两个的下标返回到HuffmanCoding函数中,改变哈夫曼树。

实验三哈夫曼树实验报告

实验三哈夫曼树实验报告

数据结构实验报告实验名称:实验三树学生姓名:班级:班内序号:学号:日期: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。

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

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

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

构造哈夫曼树时,权值小的放左子树,权值大的放右子树,编码时右子树编码为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;arent =-1;HuffNode[i].lchild =-1;HuffNode[i].rchild =-1;scanf("%c",&x);scanf("%c",&HuffNode[i].value); eight);}for (i=n; i<2*n-1; i++){HuffNode[i].weight = 0;arent =-1;HuffNode[i].lchild =-1;HuffNode[i].rchild =-1;HuffNode[i].value=i;}/* 循环构造 Huffman 树 */for (i=0; i<n-1; i++){m1=m2=MAXQZ; eight < m1 && HuffNode[j].parent==-1){m2=m1;eight;x1=j;}else if (HuffNode[j].weight < m2 && HuffNode[j].parent==-1) {m2=HuffNode[j].weight;x2=j;}} /* end for *//* 设置找到的两个子结点 x1、x2 的父结点信息 */HuffNode[x1].parent = n+i;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=+1; j<n; j++)HuffCode[i].bit[j] = [j];HuffCode[i].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++){= n-1;c = i;p = HuffNode[c].parent;while (p != -1) /* 父结点存在 */{if (HuffNode[p].lchild == c)[] = 0;else[] = 1;; /* 求编码的低一位 */c=p;p=HuffNode[c].parent; /* 设置下一循环条件 */ } /* end while */for (j=+1; j<n; j++)HuffCode[i].bit[j] = [j];HuffCode[i].start = ;} /* 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;}四、调试分析与心得体会:虽然哈夫曼树的建立有书上的参考,但是实际写整个代码的时候还是问题重重。

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

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

数据结构实验报告实验名称:实验三树——哈夫曼编/解码器学生:班级:班序号:学号:日期: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 rchild parent 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树构成规则进行。

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

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

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

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

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

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 树,也叫做最优二叉树哈夫虽树示意图root孩子双亲表示法_____________________ JL________________weight Ichild rchild pare nt数存储在数组a[]中。

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

关键点:选择最小和次小结点合成。

void Huffma n::CreateHTree(){HTree = new HNode [2*n-1]; // 根据权重数组a[0..n-1] 初始化Huffman 树for (i nt j = 0; j < n; j++)HTree[j].weight = a[j];HTree[j].LChild = HTree[j].RChild = HTree[j].pare nt = -1;}int x,y;for (int i = n; i < 2*n-1; i++) // 开始建Huffman 树{SelectMin( HTree, i, x, y); //从1~i中选出两个权值最小的结点HTree[x].pare nt = HTree[y].pare nt = i;HTree[i].weight = HTree[x].weight+ HTree[y].weight;HTree[i].LChild = x;HTree[i].RChild = y;HTree[i].pare nt = -1;}}2时间复杂度为0(n )void Huffman::SelectMin( HNode *hTree,int n, int & 1, int &i2 ) {int i;// 找一个比较值的起始值for(i=0; i<n; i++) // 找i1{ if(hTree[i].pare nt==_1 ){ i1=i; break;}i++;for( ; i<n; i++) // 找i2{ if(hTree[i].pare nt==_1 ){ i2=i; break; }}指向最小的if(hTree[i1].weight>hTree[i2].weight) 〃i1{ int j=i2; i2=i1; i1 = j; }// 开始找最小的两个i++;for( ; i<n; i++){ if(hTree[i].pare nt==-1&& hTree[i].weight < hTree[i1].weight ) { i2=i1; i1 = i; } else if( hTree[i].pare nt==-1&& hTree[i].weight < hTree[i2].weight){ i2=i; }}}时间复杂度为0(n)(3)创建编码表child = pare nt; //迭代首先定义码表存储空间;循环对n 个叶子结点自底向上回溯到根,记下途径的左右关系, 将各个叶子结点对应的逆序串反序即可。

void Huffma n::CreateCodeTable() {HCodeTable = new HCode[ n]; // 生成编码表for (int i=0;i< n;i++)HCodeTable[i].data = l[i];int child = i;int pare nt = HTree[i].pare nt; ////孩子结点编号当前结点的父结点编号int k=0;while(pare nt!=-1)if (child==HTree[pare nt]. LChild) HCodeTable[i].code[k] = 'O'; elseHCodeTable[i].code[k] = '1 k++;算法过程:从叶子到根 自底向上形成编码的逆序串;//左孩子标//右孩子标‘ 1'pare nt = HTree[child].pare nt;child = pare nt; //迭代HCodeTable[i].code[k] = '\0:Reverse(HCodeTable[i].code);//将编码字符逆置}}时间复杂度为0(n)(4)生成编码串将输入的字符串的每一个字符与编码表比较void Huffman::Encode(char *d)〃编码,d为编码后的字符串{char *s = str;while(*s!='\0'){for (in t i=0;i< n;i++)if (*s == HCodeTable[i].data ){strcat(d, HCodeTable[i].code);break;}s++;}*d = HCodeTable[pare nt].data;时间复杂度为0(n)(5) 解码:算法过程: 从根到叶子---自顶向下基于huffman 树存储数组,从根结点开始,依据输入待解码串 s 中码字0或1,分别向左或只要s 串为结束,重复上述过程{while(*s!='\0') {{if (*s=='0')pare nt = HTree[pare nt].LChild; elsepare nt = HTree[pare nt].RChild; s++; } d++;右跟踪至叶子结点,叶子结点对应的字符(见码表),即为解码得到的字符;void Huffma n::Decode(char* s, char *d)//解码,s 为编码串,d 为解码后的字符串int pare nt = 2*n-2;while (HTree[pare nt]. LChild!=-1) II //根结点在HTree 中的下标如果不是叶子结点}时间复杂度为0(n)2.3其他(1)哈夫曼树的输出是以凹入表示法来实现的,具体算法如下:void Huffma n::Pri nt( in t i, i nt m){if (HTree[i].LChild == -1)cout<<setfill(' ')<<setw(m+1)<<l[i]<<setfill('-')<<setw(10-m)<<'\n:else{cout<<setfill(' ')<<setw(m+1)<<HTree[i].weight<<setfill('-')<<setw(10-m)<<'\n:Prin t(HTree[i].LChild,m+1);Prin t(HTree[i].RChild,m+1);}}(2)统计字符頻数时,利用字符的ASCII码进行计数统计,调用了cin.get()函数3.程序运行程序框图:开始输入要编码的字符串*d = HCodeTable[pare nt].data;结束#in elude <iostream> #i nclude <ioma nip> using n amespace std; struct HNode {int weight; 〃结点权值int parent; //双亲指针int LChild; //左孩子指针 int RChild ; //右孩子指针};struct HCode {char data; char code[100]; };class Huffma n {private:HNode* HTree; HCode* HCodeTable; char str[1024]; char l[256]; int a[256]; public:int n;程序源代码://Huffman 树 //Huffman 编码表 //输入的原始字符串〃叶子节点对应的字符//记录每个出现的字符的个数〃叶子节点数void Ini t();void CreateHTree();void CreateCodeTable(); void Prin tTable();void En code(char *d); void Decode(char *s, char *d); void Prin t( int i,i nt m);//初始化//创建huffman树//创建编码表//编码//解码//打印Huffman树void SelectMi n( HNode *hTree, int n, int & 1, i nt & 2);// 找出最小的两个权值void Reverse(char* s); void Compare(char*d);~ Huffma n(); }; //逆序//比较压缩大小〃析构void Huffma n::l nit() {int nNum[256]= {0};int ch = cin .get();int i=0;while((ch!='\r') && (ch!='\n')) {nNu m[ch]++;str[i++] = ch;ch = cin .get(); }str[i]='\0'; //记录每一个字符出现的次数//统计字符出现的次数//记录原始字符串//读取下一个字符n = 0;for ( i=0;i<256;i++) {if (nN um[i]>0){l[n] = (char)i;a[n] = nNu m[i];n++;}}}void Huffman::CreateHTree(){HTree = new HNode [2* n-1]; 树〃若nNum[i]==0,字符未出现//根据权重数组a[0..n-1]初始化Huffmanfor (i nt j = 0; j < n; j++){HTree[j].weight = a[j];HTree[j].LChild = HTree[j].RChild = HTree[j].pare nt = -1;}int x,y;for (int i = n; i < 2*n-1; i++) 〃开始建Huffman 树{SelectMin( HTree, i, x, y); //从1~i中选出两个权值最小的结点HTree[x].pare nt = HTree[y].pare nt = i;HTree[i].weight = HTree[x].weight+ HTree[y].weight;HTree[i].LChild = x;HTree[i].RChild = y;HTree[i].pare nt = -1;}void Huffman::SelectMin( HNode *hTree,int n, {int & 1, int &i2 ) int i;//找一个比较值的起始值for(i=0; i<n; i++) // 找i1{ if(hTree[i].pare nt==_1 ){ i1=i; break; }}i++;for( ; i<n; i++) // 找i2{ if(hTree[i].pare nt==_1 ){ i2=i; break; }}if(hTree[i1].weight>hTree[i2].weight) 〃i1 指向最小的{ int j=i2; i2=i1; i1 = j; }〃开始找最小的两个i++;for( ; i<n; i++){ if(hTree[i].pare nt==_1&& hTree[i].weight < hTree[i1].weight ){ i2=i1; i1 = i; }else if( hTree[i].pare nt==-1&& hTree[i].weight < hTree[i2].weight){ i2=i; }}}void Huffma n::Pri nt( in t i, i nt m){if (HTree[i].LChild == -1)cout<<setfill(' ')<<setw(m+1)<<l[i]<<setfill('-')<<setw(10-m)<<'\n: else{cout<<setfill(' ')<<setw(m+1)<<HTree[i].weight<<setfill('-')<<setw(10-m)<<'\n:Prin t(HTree[i].LChild,m+1);Prin t(HTree[i].RChild,m+1);}}void Huffma n::CreateCodeTable(){HCodeTable = new HCode[n]; // 生成编码表for (i nt i=0;i <n ;i++){HCodeTable[i].data = l[i];int child = i; //孩子结点编号in t pare nt = HTree[i].pare nt; //当前结点的父结点编号int k=0;while(pare nt!=-1){if (child==HTree[parent].LChild) //左孩子标’O'HCodeTable[i].code[k] = '0';elseHCodeTable[i].code[k] = '1' ; // 右孩子标’1k++;child = pare nt; // 迭代pare nt = HTree[child].pare nt;}HCodeTable[i].code[k] = '\0';Reverse(HCodeTable[i].code); // 将编码字符逆置}}void Huffma n::Pri ntTable(){for (i nt i=0;i <n ;i++) cout<<HCodeTable[i].data<<'\t'<<HCodeTable[i].code<<e ndl;}void Huffman::Encode(char *d)〃编码,d为编码后的字符串{char *s = str;while(*s!='\0'){for (int i=0;i< n;i++)if (*s ==HCodeTable[i].data ){strcat(d, HCodeTable[i].code);break;}s++;}}void Huffman::Decode(char* s, char *d) 〃解码,s 为编码串,d 为解码后的字符串{while(*s!='\0'){in t pare nt = 2*n-2; 〃根结点在HTree中的下标while (HTree[pare nt]. LChild!=-1) 〃如果不是叶子结点{if (*s=='0')pare nt = HTree[pare nt].LChild;elsepare nt = HTree[pare nt].RChild;s++;}*d = HCodeTable[pare nt].data;d++;}}void Huffman::Reverse(char* s)// 换序{char ch;int len = strle n( s);for (int i=0;i<len/2;i++) {ch = s[i];s[i] = s[le n-i-1];s[le n-i-1] = ch;}}void Huffman::Compare(char*d)〃比较压缩大小{cout<<"编码前:"<<strle n(str)*8<<"bit"<<e ndl;cout<<"编码后:"<<strle n(d)<<"bit"<<e ndl;}Huffman::~ Huffman()// 析构函数{delete []HTree;delete []HCodeTable;}void mai n(){Huffma n HFCode;char d[1024]={0};char s[1024]={0};cout<<"请输入要编码的字符串:";HFCode.I nit();HFCode.CreateHTree();HFCode.CreateCodeTable();HFCode.E ncode(d);HFCode.Decode(d,s);int m;cout<<"欢迎使用\n"<<"1.打印哈夫曼树\n"<<"2.打印哈夫曼编码表打印编码\n"<<"3. \n"<<"4.打印解码\n"<<"5.压缩比"<<endl;while(1){cin»m;switch(m){case 1:{HFCode.Pri nt(2*HFCode. n-2,1);break;}case 2:{HFCode.Pri ntTable();break;}case 3:{cout<<"编码结果:"<<d<<e ndl; break;} case 4:{cout<<"解码结果:"<<s<<endl; break; } case 5:{pare(d); } } } }运行结果:*E :\vc-b - \Microsoft Visual Stu□ i o\F/lyPrcy ects x h af u m\Debug\nafnj.e>:eI uiLl ti'y my best tLoue cl 且 I :丑 S true cure I loue Computer^:叱* ?■片3 的st 黏 码t a 員> 编站翁筮 要y 用吟匸毎M 比」瓦LnJn r D r DI D I 5H 丿欢迎下载 214.总结在编程时,最开始在字符统计时出现了空格无法统计的问题,后来用ci n.get()函数进 行统计。

相关文档
最新文档