实验六 哈夫曼树及哈夫曼编码

合集下载

数据结构实验实验报告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域。

哈夫曼树的建立与编码实验报告

哈夫曼树的建立与编码实验报告
{
cjs=0;
for(i=0;i<num && cjs==0 && !feof(fp);i++)
{
cd[i]=' ';cd[i+1]='\0';
cd[i]=fgetc(fp);
for(j=1;j<=num;j++)
if(strcmp(HC[j].bits,cd)==0)
{
str[k]=HC[j].ch;k++;
k=*p-64;
temp[k]++;
}
}
j=0;
for(i=1,j=0;i<26;i++)
if(temp[i]!=0){
j++;
str[j]=i+64;
cnt[j]=temp[i];
}
return j;
}
1.3构造哈夫曼树
void ChuffmanTree(HuffmanTree HT,HuffmanCode HC,int cnt[],char str[])
{
int i,s1,s2;
for(i=1;i<=2*num-1;i++)
{
HT[i].lchild=0;HT[i].rchild=0;
HT[i].parent=0;HT[i].weight=0;
}
for(i=1;i<num;i++) //输入num个叶子结点的权值
HT[i].weight=cnt[i];
}HTNode,*HuffmanTree;
typedef char **HuffmanCode;

赫夫曼树及其编码

赫夫曼树及其编码
2011年10月 计算机科学与工程学院 TCS.CQ 第 4 页
哈夫曼树构造算法
1、给定一个具有n个权值{ w1,w2,………wn }的结点的集合
F = { T1,T2,………Tn }
2、 初始时,设集合 A = F。 3、 执行 i = 1 至 n -1 的循环,在每次循环时执行以下操作
从当前集合中选取权值最小、次最小的两个结点,以这两个 结点作为内部结点 bi 的左右儿子,bi 的权值为其左右儿子 权值之和。 在集合中去除这两个权值最小、次最小的结点,并将内部结 点bI 加入其中。这样,在集合A中结点个数便减少了一个。
第 9 页
2011年10月
计算机科学与工程学院 TCS.CQ
a(10), e(15), i(12), s(3), t(4), 空格(13), 换行(1)。
a 10 a 10 e 15 e 15 i 12 i 12 S 3 t 4 t 4 空格 13 S 3 8 a 10 e 15 i 12 空格 13 S 3
计算机科学与工程学院 TCS.CQ
2 5 i 12 空格 13 5 8 4
3 3 1 8 8 t 4 换行 1 a 10 e 15
3 3
1 8 8 4 S 3 t 4 换行 1
2 5 e 15 i 12 空格 13
3
S
a 10
《数据结构》课件
计算机科学与工程学院 TCS.CQ
第 12 页
哈夫曼编码 A 001
2011年10月 计算机科学与工程学院 TCS.CQ 第 7 页
前缀编码
字符只放在叶结点中,所以任何一个字符的编码 都不是同一字符集中另一个字符的编码的前缀。 利用赫夫曼树可以构造一种不等长的二进制编码, 并且构造所得的赫夫曼编码是一种最优前缀编码, 即使所传电文的总长度最短。 字符编码可以有不同的长度

c语言哈夫曼树的构造及编码

c语言哈夫曼树的构造及编码

c语言哈夫曼树的构造及编码一、哈夫曼树概述哈夫曼树是一种特殊的二叉树,它的构建基于贪心算法。

它的主要应用是在数据压缩和编码中,可以将频率高的字符用较短的编码表示,从而减小数据存储和传输时所需的空间和时间。

二、哈夫曼树的构造1. 哈夫曼树的定义哈夫曼树是一棵带权路径长度最短的二叉树。

带权路径长度是指所有叶子节点到根节点之间路径长度与其权值乘积之和。

2. 构造步骤(1) 将待编码字符按照出现频率从小到大排序。

(2) 取出两个权值最小的节点作为左右子节点,构建一棵新的二叉树。

(3) 将新构建的二叉树加入到原来排序后队列中。

(4) 重复上述步骤,直到队列只剩下一个节点,该节点即为哈夫曼树的根节点。

3. C语言代码实现以下代码实现了一个简单版哈夫曼树构造函数:```ctypedef struct TreeNode {int weight; // 权重值struct TreeNode *leftChild; // 左子节点指针struct TreeNode *rightChild; // 右子节点指针} TreeNode;// 构造哈夫曼树函数TreeNode* createHuffmanTree(int* weights, int n) {// 根据权值数组构建节点队列,每个节点都是一棵单独的二叉树TreeNode** nodes = (TreeNode**)malloc(sizeof(TreeNode*) * n);for (int i = 0; i < n; i++) {nodes[i] = (TreeNode*)malloc(sizeof(TreeNode));nodes[i]->weight = weights[i];nodes[i]->leftChild = NULL;nodes[i]->rightChild = NULL;}// 构建哈夫曼树while (n > 1) {int minIndex1 = -1, minIndex2 = -1;for (int i = 0; i < n; i++) {if (nodes[i] != NULL) {if (minIndex1 == -1 || nodes[i]->weight < nodes[minIndex1]->weight) {minIndex2 = minIndex1;minIndex1 = i;} else if (minIndex2 == -1 || nodes[i]->weight < nodes[minIndex2]->weight) {minIndex2 = i;}}}TreeNode* newNode =(TreeNode*)malloc(sizeof(TreeNode));newNode->weight = nodes[minIndex1]->weight + nodes[minIndex2]->weight;newNode->leftChild = nodes[minIndex1];newNode->rightChild = nodes[minIndex2];// 将新构建的二叉树加入到原来排序后队列中nodes[minIndex1] = newNode;nodes[minIndex2] = NULL;n--;}return nodes[minIndex1];}```三、哈夫曼编码1. 哈夫曼编码的定义哈夫曼编码是一种前缀编码方式,它将每个字符的编码表示为二进制串。

哈夫曼树和哈夫曼编码(数据结构程序设计)

哈夫曼树和哈夫曼编码(数据结构程序设计)

课程设计(数据结构)哈夫曼树和哈夫曼编码二○○九年六月二十六日课程设计任务书及成绩评定课题名称表达式求值哈夫曼树和哈夫曼编码Ⅰ、题目的目的和要求:巩固和加深对数据结构的理解,通过上机实验、调试程序,加深对课本知识的理解,最终使学生能够熟练应用数据结构的知识写程序。

(1)通过本课程的学习,能熟练掌握几种基本数据结构的基本操作。

(2)能针对给定题目,选择相应的数据结构,分析并设计算法,进而给出问题的正确求解过程并编写代码实现。

Ⅱ、设计进度及完成情况Ⅲ、主要参考文献及资料[1] 严蔚敏数据结构(C语言版)清华大学出版社 1999[2] 严蔚敏数据结构题集(C语言版)清华大学出版社 1999[3] 谭浩强 C语言程序设计清华大学出版社[4] 与所用编程环境相配套的C语言或C++相关的资料Ⅳ、成绩评定:设计成绩:(教师填写)指导老师:(签字)二○○九年六月二十六日目录第一章概述 (1)第二章系统分析 (2)第三章概要设计 (3)第四章详细设计及实现代码 (8)第五章调试过程中的问题及系统测试情况 (12)第六章结束语 (13)参考文献 (13)第一章概述课程设计是实践性教学中的一个重要环节,它以某一课程为基础,可以涉及和课程相关的各个方面,是一门独立于课程之外的特殊课程。

课程设计是让同学们对所学的课程更全面的学习和应用,理解和掌握课程的相关知识。

《数据结构》是一门重要的专业基础课,是计算机理论和应用的核心基础课程。

数据结构课程设计,要求学生在数据结构的逻辑特性和物理表示、数据结构的选择和应用、算法的设计及其实现等方面,加深对课程基本内容的理解。

同时,在程序设计方法以及上机操作等基本技能和科学作风方面受到比较系统和严格的训练。

在这次的课程设计中我选择的题目是表达式求值和哈夫曼树及哈夫曼编码。

这里我们介绍一种简单直观、广为使用的算法,通常称为“算符优先法”。

哈夫曼树又称最优树,是一类带权路径长度最短的树,有着广泛的应用。

(完整word版)哈夫曼树实验报告

(完整word版)哈夫曼树实验报告

实验报告1、实验目的:(1)理解哈夫曼树的含义和性质。

(2)掌握哈夫曼树的存储结构以及描述方法。

(3)掌握哈夫曼树的生成方法。

(4)掌握哈夫曼编码的一般方法,并理解其在数据通讯中的应用.2、实验内容:哈夫曼树与哈弗曼编码、译码a。

问题描述:哈夫曼问题的提出可以参考教材P。

145。

利用哈弗曼编码进行通信可以大大提高通信利用率,缩短信息传输时间,降低传输成本。

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

算法提示:参见教材P.147—148算法6.12、6。

13的描述.3、实验要求:建立哈夫曼树,实现编码,译码。

错误!.初始化(Initialization)。

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

○2。

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

○3.译码(Decoding ).利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件T extFile 中。

错误!.输出代码文件(Print).将文件CodeFile以紧凑格式显示在终端上,每行50个代码。

同时将此字符形式的编码文件写入文件CodePrint中。

错误!。

输出哈夫曼树(TreePrinting).将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。

测试数据:设权值c= (a,b, c, d , e, f,g,h)w=(5,29,7,8,14,23,3,11),n=8。

按照字符‘0’或‘1’确定找左孩子或右孩子,则权值对应的编码为:5:0001,29:11,7:1110,8:111114:110,23:01,3:0000,11:001。

实习报告6_哈夫曼编码

实习报告6_哈夫曼编码

1.初始化:从文件(程序运行时,由用户输入)读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,将它存于文件中。

2.编码:利用已建好的哈夫曼树(如不在内存,则从文件中读入)对文件字符集中的每一个进行编码,将结果放在中。

3.译码:利用已建好的哈夫曼树将中的代码进行译码,结果保存在中。

4.印代码文件。

将文件以紧凑的格式显示在终端上,每行50个代码。

同时将结果保存在中。

二.概要设计:1.哈夫曼树的抽象数据类型定义:ADT haffman{ 数据对象:D={ai|ai为charnode型的结点,i=1,2,3,……n,n>0}数据关系:R={<ai,><ai,>|ai是D上的元素}} ADT haffman2.编码集结构体的抽象数据类型的定义:ADT code{ 数据对象:D1={ai| ai是charlink型的结点,i=1,2,……n,n>0}D2={bi|bi是codelink型的结点,i=1,2,……n,n>0}数据关系: R1={<ai,>|ai是D1上的元素}R2={<bi,>|bi是D2上的元素}} ADT code3.程序分为四个部分:1)读入字符集以及相应频度,建立哈夫曼树。

2)根据哈夫曼树得到每一个字符的哈夫曼编码。

3)读入要编码的字符串,根据哈夫曼树和编码集求出字符串的哈夫曼编码。

4)根据哈夫曼编码和哈夫曼树得到字符串。

三.详细设计:h >> hufW[ ii ].wt;}(); .eight<< setw( 8 ) << hufT[ tOut ].parent<< setw( 8 ) << hufT[ tOut ].lChild<< setw( 8 ) << hufT[ tOut ].rChild << endl;}hufTreeOutPut << "-- end HT --------------------------- " << endl << endl << "-- HC ------------------------------- " << endl;for( int cOut = 1 ; cOut <= hufNum ; cOut++ ){hufTreeOutPut << " " << hufC[ cOut ].ch << " ---->> " << hufC[ cOut ].hufCh << endl;}hufTreeOutPut << "-- convert -- ok -------------------- " << endl;(); t;p->parent = p->lChild = p->rChild = 0; i-1 ]选择parent 为 0 且weight 最小的两个结点,其序号分别为 s1 和 s2arent = i; arent = i; Child = s1; Child = s2; eight =HT[ s1 ].weight + HT[ s2 ].weight; arent ; f != 0 ; c = f , f =HT[ f ].parent ) Child == c ) { cd[ --start ] = '0'; }else { cd[ --start ] = '1'; }}HC[ i ].ch = w[ i-1 ].ch ; ufCh = ( char* ) malloc ( ( n - start ) * sizeof( char ) ); ufCh , &cd[ start ] ); arent != 0 ) continue;else{sm1 = HT[ m ].weight;s1=m;break;}}for( int j = m+1 ; j <= i ; j++ ) arent != 0 ) continue;else{if( sm1 > HT[ j ].weight ){sm1 = HT[ j ].weight;s1 = j;}}}for( m = 1 ; m <= i ; m++ ) arent != 0 ) continue;else{sm2 = HT[ m ].weight;s2=m;if( s2 == s1 ) continue;else break;}}for( int k = m+1 ; k <= i ; k++ ) arent != 0 ) continue;else{if( (HT[ k ].weight < sm2) && ( k != s1 ) ) eight;s2 = k;}}}} ufCh == ' 'fOut << HC[ sub ].hufCh;}else if( inBuf == '\n' ){continue;}else{ufCh == 'A'. 以下的字符雷同sub = inBuf - 63;fOut << HC[ sub ].hufCh;}}HT[p]就为 HT 的根.Child != 0 ) Child; ufCh , cd ) == 0 ){fOut << HC[ iHC ].ch;break; Child; Child != 0 ) Child; ufCh , cd ) == 0 ){fOut << HC[ iHC ].ch;break; Child; ufCh , cd ) == 0 ){fOut << HC[ iHC ].ch;break; ufCh , cd ) == 0 ){fOut << HC[ iHC ].ch;break; 试分析1.本次作业在打印树形结构的时候有点遗憾,其他的都应该做的完美的了。

哈夫曼(huffman)树和哈夫曼编码

哈夫曼(huffman)树和哈夫曼编码

哈夫曼(huffman)树和哈夫曼编码讨论QQ群:待定哈夫曼树哈夫曼树也叫最优二叉树(哈夫曼树)问题:什么是哈夫曼树?例:将学生的百分制成绩转换为五分制成绩:≥90 分: A,80~89分: B,70~79分: C,60~69分: D,<60分: E。

if (a < 60){b = 'E';}else if (a < 70) {b = ‘D’;}else if (a<80) {b = ‘C’;}else if (a<90){b = ‘B’;}else {b = ‘A’;}判别树:用于描述分类过程的二叉树。

如果每次输入量都很大,那么应该考虑程序运行的时间如果学生的总成绩数据有10000条,则5%的数据需1 次比较,15%的数据需 2 次比较,40%的数据需 3 次比较,40%的数据需 4 次比较,因此 10000 个数据比较的次数为: 10000 (5%+2×15%+3×40%+4×40%)=31500次此种形状的二叉树,需要的比较次数是:10000 (3×20%+2×80%)=22000次,显然:两种判别树的效率是不一样的。

问题:能不能找到一种效率最高的判别树呢?那就是哈夫曼树回忆树的基本概念和术语路径:若树中存在一个结点序列k1,k2,…,kj,使得ki是ki+1的双亲,则称该结点序列是从k1到kj的一条路径。

路径长度:等于路径上的结点数减1。

结点的权:在许多应用中,常常将树中的结点赋予一个有意义的数,称为该结点的权。

结点的带权路径长度:是指该结点到树根之间的路径长度与该结点上权的乘积。

树的带权路径长度:树中所有叶子结点的带权路径长度之和,通常记作:其中,n表示叶子结点的数目,wi和li分别表示叶子结点ki的权值和树根结点到叶子结点ki之间的路径长度。

赫夫曼树(哈夫曼树,huffman树)定义:在权为w1,w2,…,wn的n个叶子结点的所有二叉树中,带权路径长度WPL最小的二叉树称为赫夫曼树或最优二叉树。

哈夫曼树及哈夫曼编码的程序-附流程图(下)

哈夫曼树及哈夫曼编码的程序-附流程图(下)

哈夫曼树及哈夫曼编码的程序-附流程图(下)int m,s1,s2;typedef struct {unsigned int weight;unsigned int parent,lchild,rchild;}HTNode,*HuffmanTree;typedef char *HuffmanCode;void Select(HuffmanTree HT,int n) {int i,j;for(i = 1;i <= n;i++)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))s1=i;for(j = 1;j <= n;j++)if((HT[s2].weight>HT[j].weight)&&(!HT[j].parent)&&(s1!=j))s2=j;}void HuffmanCoding(HuffmanTree &HT, HuffmanCode HC[], int *w, int n) {int i, j;char *cd;int p;int cdlen;if (n<=1) return;m = 2 * n - 1;HT = (HuffmanTree)malloc((m+1) * sizeof(HTNode));for (i=1; i<=n; i++) {HT[i].weight=w[i-1];HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;}for (i=n+1; i<=m; i++) {HT[i].weight=0;HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;}puts("\n哈夫曼树的构造过程如下所⽰:");printf("HT初态:\n 结点 weight parent lchild rchild");for (i=1; i<=m; i++)printf("\n%4d%8d%8d%8d%8d",i,HT[i].weight,HT[i].parent,HT[i].lchild, HT[i].rchild);printf(" 按任意键,继续 ...");getchar();for (i=n+1; i<=m; i++) {Select(HT, i-1);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;printf("\nselect: s1=%d s2=%d\n", s1, s2);printf(" 结点 weight parent lchild rchild");for (j=1; j<=i; j++)printf("\n%4d%8d%8d%8d%8d",j,HT[j].weight,HT[j].parent,HT[j].lchild, HT[j].rchild);printf(" 按任意键,继续 ...");getchar(); }cd = (char *)malloc(n*sizeof(char));p = m; cdlen = 0;for (i=1; i<=m; ++i)HT[i].weight = 0;while (p) {if (HT[p].weight==0) {HT[p].weight = 1;if (HT[p].lchild != 0) { p = HT[p].lchild; cd[cdlen++] ='0'; } else if (HT[p].rchild == 0){ HC[p] = (char *)malloc((cdlen+1) * sizeof(char));cd[cdlen] ='\0'; strcpy(HC[p], cd); }}else if (HT[p].weight==1){ HT[p].weight = 2;if (HT[p].rchild != 0) { p = HT[p].rchild; cd[cdlen++] ='1'; }} else { // HT[p].weight==2,HT[p].weight = 0; p = HT[p].parent; --cdlen; } }}void main() {HuffmanTree HT;HuffmanCode *HC;int *w,n,i;puts("输⼊结点数:");scanf("%d",&n);HC = (HuffmanCode *)malloc(n*sizeof(HuffmanCode));w = (int *)malloc(n*sizeof(int));printf("输⼊%d个结点的权值\n",n);for(i = 0;i < n;i++)scanf("%d",&w[i]);HuffmanCoding(HT,HC,w,n);puts("\n各结点的哈夫曼编码:");for(i = 1;i <= n;i++)printf("%2d(%4d):%s\n",i,w[i-1],HC[i]);getchar(); }。

哈夫曼树编码实训报告

哈夫曼树编码实训报告

一、实训目的本次实训旨在通过实际操作,让学生掌握哈夫曼树的基本概念、构建方法以及编码解码过程,加深对数据结构中树型结构在实际应用中的理解。

通过本次实训,学生能够:1. 理解哈夫曼树的基本概念和构建原理;2. 掌握哈夫曼树的编码和解码方法;3. 熟悉Java编程语言在哈夫曼树编码中的应用;4. 提高数据压缩和传输效率的认识。

二、实训内容1. 哈夫曼树的构建(1)创建叶子节点:根据给定的字符及其权值,创建叶子节点,并设置节点信息。

(2)构建哈夫曼树:通过合并权值最小的两个节点,不断构建新的节点,直到所有节点合并为一棵树。

2. 哈夫曼编码(1)遍历哈夫曼树:从根节点开始,按照左子树为0、右子树为1的规则,记录每个叶子节点的路径。

(2)生成编码:将遍历过程中记录的路径转换为二进制编码,即为哈夫曼编码。

3. 哈夫曼解码(1)读取编码:将编码字符串按照二进制位读取。

(2)遍历哈夫曼树:从根节点开始,根据读取的二进制位,在哈夫曼树中寻找对应的节点。

(3)输出解码结果:当找到叶子节点时,输出对应的字符,并继续读取编码字符串。

三、实训过程1. 准备工作(1)创建一个Java项目,命名为“HuffmanCoding”。

(2)在项目中创建以下三个类:- HuffmanNode:用于存储哈夫曼树的节点信息;- HuffmanTree:用于构建哈夫曼树、生成编码和解码;- Main:用于实现主函数,接收用户输入并调用HuffmanTree类进行编码和解码。

2. 编写代码(1)HuffmanNode类:```javapublic class HuffmanNode {private char data;private int weight;private HuffmanNode left;private HuffmanNode right;public HuffmanNode(char data, int weight) {this.data = data;this.weight = weight;}}```(2)HuffmanTree类:```javaimport java.util.PriorityQueue;public class HuffmanTree {private HuffmanNode root;public HuffmanNode buildHuffmanTree(char[] data, int[] weight) {// 创建优先队列,用于存储叶子节点PriorityQueue<HuffmanNode> queue = new PriorityQueue<>();for (int i = 0; i < data.length; i++) {HuffmanNode node = new HuffmanNode(data[i], weight[i]);queue.offer(node);}// 构建哈夫曼树while (queue.size() > 1) {HuffmanNode left = queue.poll();HuffmanNode right = queue.poll();HuffmanNode parent = new HuffmanNode('\0', left.weight + right.weight);parent.left = left;parent.right = right;queue.offer(parent);}root = queue.poll();return root;}public String generateCode(HuffmanNode node, String code) {if (node == null) {return "";}if (node.left == null && node.right == null) {return code;}generateCode(node.left, code + "0");generateCode(node.right, code + "1");return code;}public String decode(String code) {StringBuilder result = new StringBuilder();HuffmanNode node = root;for (int i = 0; i < code.length(); i++) {if (code.charAt(i) == '0') {node = node.left;} else {node = node.right;}if (node.left == null && node.right == null) { result.append(node.data);node = root;}}return result.toString();}}```(3)Main类:```javaimport java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.println("请输入字符串:");String input = scanner.nextLine();System.out.println("请输入字符及其权值(例如:a 2 b 3 c 5):"); String[] dataWeight = scanner.nextLine().split(" ");char[] data = new char[dataWeight.length / 2];int[] weight = new int[dataWeight.length / 2];for (int i = 0; i < dataWeight.length; i += 2) {data[i / 2] = dataWeight[i].charAt(0);weight[i / 2] = Integer.parseInt(dataWeight[i + 1]);}HuffmanTree huffmanTree = new HuffmanTree();HuffmanNode root = huffmanTree.buildHuffmanTree(data, weight); String code = huffmanTree.generateCode(root, "");System.out.println("编码结果:" + code);String decoded = huffmanTree.decode(code);System.out.println("解码结果:" + decoded);scanner.close();}}```3. 运行程序(1)编译并运行Main类,输入字符串和字符及其权值。

哈夫曼实验报告(附代码)

哈夫曼实验报告(附代码)

哈夫曼实验报告(附代码)以下是为大家整理的哈夫曼实验报告(附代码)的相关范文,本文关键词为哈夫曼,实验,报告,代码,,您可以从右上方搜索框检索更多相关文章,如果您觉得有用,请继续关注我们并推荐给您的好友,您可以在综合文库中查看更多范文。

哈弗曼编码/译码器一、程序的功能分析1.构造哈夫曼树及哈夫曼编码:从终端读入字符集大小n、n 个字符以及n个对应的权值,建立哈夫曼树;利用已经建好的哈夫曼树求每个叶结点的哈夫曼编码,并保存。

2.编码:利用已构造的哈夫曼编码对“明文”文件中的正文进行编码,然后将结果存入“密文”文件中。

3.译码:将“密文”文件中的0、1代码序列进行译码。

(读文件) 4.打印“密文”文件:将文件以紧凑格式显示在终端上,每行30个代码;同时,将此字符形式的编码文件保存。

5.打印哈夫曼树及哈夫曼编码:将已在内存中的哈夫曼树以凹入表形式显示在终端上,同时将每个字符的哈夫曼编码显示出来;并保存到文件。

二、基本要求分析1、输入输出的要求按提示内容从键盘输入命令,系统根据用户输入的需求在保证界面友好的前提下输出用户所需信息,并按要求保存文件,以便保存备份信息。

2、测试数据(1).令叶子结点个数n为4,权值集合为{1,3,5,7},字符集合为{A,b,c,D},且字符集与权值集合一一对应。

(2).令叶子结点个数n为7,权值集合为{12,6,8,18,3,20,2},字符集合为{A,b,c,D,e,F,g},且字符集与权值集合一一对应。

(3).请自行选定一段英文文本,统计给出的字符集,实际统计字符的频度,建立哈夫曼树,构造哈夫曼编码,并实现其编码和译码。

三、概要设计1.主模块的流程及各子模块的主要功能主函数负责提供选项功能,循环调控整个系统。

创建模块实现接收字符、权值、构建哈夫曼树,并保存文件,此功能是后续功能的基础。

编码模块实现利用已编好的哈夫曼树对每个字符进行哈夫曼编码,即对每个字符译出其密文代码,并保存文件。

数据结构——哈夫曼(Huffman)树+哈夫曼编码

数据结构——哈夫曼(Huffman)树+哈夫曼编码

数据结构——哈夫曼(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}对应的哈夫曼树。

⾄此,应该堆哈夫曼树的概念有了⼀定的了解了,下⾯看看如何去构造⼀棵哈夫曼树。

哈夫曼树和哈夫曼编码——实验报告

哈夫曼树和哈夫曼编码——实验报告

实验报告学生姓名 学号专业 年级、班级课程名称 实验项目 排队系统的模拟 实验类型✓ 综合实验时间 年 月 日实验指导老师 实验评分1、实验项目名称哈夫曼树和哈夫曼编码2、实验目的及要求掌握哈夫曼树和哈夫曼编码的实现3、实验内容及步骤(1)新建一个工程——Win32 Console Application,为工程取名——创建一个简单的程序【S】(2)进入类视图,添加类——鼠标右键,点击New Class——输入类的名称,点击确定。

(3)将对应代码放入对应文件——5-13代码放入 hfTree.h文件;5-14、5.15代码放入hfTree.cpp文件;5-16代码放入幂函数文件ex 007.cpp。

(//后绿色的字是在分析代码)(4)组建、编译,运行结果4、实验结果及分析5-13 哈夫曼树类的定义代码分析template <class Type>//模板类class hfTree{private:struct Node//数组中的元素类型:一个结点{ Type data;//结点值int weight;//结点的权值int parent,left,right;//父结点以及左右儿子的下标地址};Node *elem;//定义一个数组,elem是数组的起始位置,哈夫曼树被保存在一个数组中int length;//数组的规模长度public:struct hfCode{//保存赫夫曼编码的类型Type data;//待编码的字符string code;//对应的哈夫曼编码};hfTree(const Type*x,const int*w,int size);//构造函数,构造函数接收一组待编码的字符以及对应的权值,构造一棵哈夫曼树void getCode(hfCode result[]);//返回哈夫曼编码的函数~hfTree(){delete []elem;}//析构函数,释放存储空间};5-14 哈夫曼树的构造函数代码分析template <class Type>hfTree<Type>::hfTree(const Type*v,const int *w,int size)//哈夫曼树的构造函数,有3个参数,一组待编码的符号,符号对应的权值,前面两个数组的数组规模{ const int MAX_INT=32767;int min1,min2;//最小树、次小树的权值int x,y;//最小树、次小树的下标length=2*size;//保存哈夫曼树的数组规模是符号数组、权值数组的两倍elem=new Node[length];//申请一个保存哈夫曼树的数组for(int i=size;i<length;++i)//for循环为数组赋初值{ elem[i].weight=w[i-size];//将待编码的符号对应的权值放到数组的后半部分elem[i].data=v[i-size];//将待编码的符号放到数组的后半部分 elem[i].parent=elem[i].left=elem[i].right=0;//将符号的父结点以及左右儿子都设为0,表明它们都是只有根结点的树}for(i=size-1;i>0;--i)//for循环完成size-1次的归并{ min1=min2=MAX_INT;x=y=0;// min1,min2分别保存两棵权值最小的数的权值,x、y分别表示这两棵树的树根在数组中的下标for(int j=i+1;j<length;++j)//找出父结点为0,且权值最小和次小的两棵树,等待归并的两棵树if(elem[j].parent==0)if(elem[j].weight<min1){min2=min1;min1=elem[j].weight;x=y;y=j;}else if(elem[j].weight<min2){min2=elem[j].weight;x=j;}elem[i].weight=min1+min2;//归并这两棵树,形成新树i,i这棵树的权值=min1+min2(分别保存挑选出的两棵权值最小的树的权值) elem[i].left=x;elem[i].right=y;elem[i].parent=0;//将挑选出来的两个结点作为左、右子树,构建一棵新树,i为根结点elem[x].parent=i;elem[y].parent=i;//i是挑选出来的两个结点的父结点}}5-15 哈夫曼的getCode函数代码分析template <class Type>void hfTree<Type>::getCode(hfCode result[])//哈夫曼树的getCode函数,返回的是一个数组,数组元素类型是hfCode,每一个元素包含待编码的符号和它对应的编码,编码是一个比特串,用字符串类型表示{ int size=length/2;//符号数组规模=哈夫曼数组规模/2int p,s;//s是追溯过程中正在处理结点的下标,p是s的父结点下标for(int i=size;i<length;++i)//读取每一个符号{result[i-size].data=elem[i].data; // result数组中第一个元素符号是哈夫曼数组elem中间的元素符号,因为哈夫曼数组elem包含了元素符号数组和元素符号权值数组,而符号数组规模=权值数组规模,所以哈夫曼数组elem数组是它们的两倍。

数据结构实验哈夫曼树及哈夫曼编码c语言

数据结构实验哈夫曼树及哈夫曼编码c语言

数据结构实验报告:哈夫曼树及哈夫曼编码一、实验目的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年。

哈夫曼树与哈夫曼树编码实验原理

哈夫曼树与哈夫曼树编码实验原理

哈夫曼树与哈夫曼树编码实验原理哈夫曼树(Huffman Tree)是一种用于数据压缩的树形数据结构。

它的主要原理是通过构建一个最优的二叉树来实现编码和解码的过程。

以下是哈夫曼树和哈夫曼编码的实验原理:1. 构建哈夫曼树:- 给定一组需要进行编码的字符及其出现频率。

通常,这个频率信息可以通过统计字符在原始数据中的出现次数来得到。

- 创建一个叶节点集合,每个叶节点包含一个字符及其对应的频率。

- 从叶节点集合中选择两个频率最低的节点作为左右子节点,创建一个新的父节点。

父节点的频率等于左右子节点频率的和。

- 将新创建的父节点插入到叶节点集合中,并将原来的两个子节点从集合中删除。

- 重复上述步骤,直到叶节点集合中只剩下一个节点,即根节点,这个节点就是哈夫曼树的根节点。

2. 构建哈夫曼编码:- 从哈夫曼树的根节点开始,沿着左子树走一步就表示编码的0,沿着右子树走一步表示编码的1。

- 遍历哈夫曼树的每个叶节点,记录从根节点到叶节点的路径,得到每个字符对应的编码。

由于哈夫曼树的构建过程中,频率较高的字符在树中路径较短,频率较低的字符在树中路径较长,因此哈夫曼编码是一种前缀编码,即没有任何一个字符的编码是其他字符编码的前缀。

3. 进行数据压缩:- 将原始数据中的每个字符替换为其对应的哈夫曼编码。

- 将替换后的编码串连接起来,形成压缩后的数据。

4. 进行数据解压缩:- 使用相同的哈夫曼树,从根节点开始,按照压缩数据中的每个0或1进行遍历。

- 当遇到叶节点时,就找到了一个字符,将其输出,并从根节点重新开始遍历。

- 继续按照压缩数据的编码进行遍历,直到所有的编码都解压为字符。

通过构建最优的哈夫曼树和对应的编码表,可以实现高效的数据压缩和解压缩。

频率较高的字符使用较短的编码,从而达到减小数据大小的目的。

而频率较低的字符使用较长的编码,由于其出现频率较低,整体数据大小的增加也相对较小。

实验6:哈夫曼树及哈夫曼编码的算法实现-副本

实验6:哈夫曼树及哈夫曼编码的算法实现-副本

实验6:哈夫曼树及哈夫曼编码的算法实现-副本实验6:哈夫曼树及哈夫曼编码的算法实现实验所需学时数2学时实验目的1)掌握哈夫曼树的基本概念及其存储结构;2)掌握哈夫曼树的建立算法;3)掌握哈夫曼树的应用(哈夫曼编码和译码)。

实验内容对输入的一串电文字符实现哈夫曼编码,再对哈夫曼编码生成的代码串进行译码,输出电文字符串。

实验所需器材计算机及VC++ 6.0软件内容要求:1、初始化(Init):能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立哈夫曼树2、建立编码表(CreateTable):利用已经建好的哈夫曼树进行编码,并将每个字符的编码输出。

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

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

测试数据:输入字符串“this*program*is*my*favourite”,完成这28个字符的编码和译码。

实验结果1、演示程序运行结果。

2、说明调试过程中出现的现象学生实验评价依据:优:实验认真、刻苦,有钻研精神,不无故缺席。

良:能认真对待实验,不无故缺席。

中:基本能认真对待实验,不无故缺席。

差:对待实验不够认真,有少量迟到、早退或无故缺席现象。

不及格:对待实验马虎、敷衍,经常迟到、早退或无故缺席。

#include#include#define maxvalue 10000 //定义最大权值常量#define maxnodenumber 100 //定义节点最大数#define maxbit 10 //定义哈弗曼编码最大长度typedef struct{ //定义新数据类型即节点结构int weight; //权重域int parent,lchild,rchild; //指针域}htnode; //节点类型标识符//typedef htnode * huffmanstree; //定义哈弗曼数类型htnode ht[maxnodenumber]; //定义三叉链表存储数组typedef struct {//定义保存一个叶子节点哈弗曼编码的结构int bit[maxbit]; //定义一维数组为编码域int start; //定义位置域}hcnodetype; //定义编码类型htnode * creatstree(int n) //huffmanstree creatstree(int n) //建立哈夫曼树算法实现函数{int i,j,m1,m2,k1,k2; //局部变量for(i=0;i<2*n-1;i++) //初始化各节点{ht[i].weight=0; //权重初始化为0ht[i].parent=-1; //根节点和给左右孩子初始化为-1ht[i].lchild=-1;ht[i].rchild=-1;}for(i=0;i<="">{scanf("%d",&ht[i].weight);}for(i=0;i<="">{m1=maxvalue; //预置最小权值变量为最大权值m2=maxvalue; //预置次小权值变量为最大权值k1=0; //预置最小权值节点位置为下标为0处k2=0; //预置次小权值节点位置为下标为0处for(j=0;j<="">if(ht[j].parent==-1&&ht[j].weight<m1)< p="">{m2=m1;k2=k1;m1=ht[j].weight;k1=j;}else //当小于当前次小m2则更新m2及其位置if(ht[j].parent==-1&&ht[j].weight<m2)< p="">{m2=ht[j].weight;k2=j;}ht[k1].parent=n+i; //修改最小权值节点的双亲为刚生成的新节点ht[k2].parent=n+i; //修改次小权值节点的双亲为刚生成的新节点ht[n+i].weight=ht[k1].weight+ht[k2].weight; //将新生成的权重值填入新的根节点ht[n+i].lchild=k1; //新生节点左孩子指向k1 ht[n+i].rchild=k2; //新生节点右孩子指向k2}return ht; //返回哈夫曼树指针}void getstree(htnode * ht,int n) //哈夫曼编码算法及打印函数的实现{int i,j,c,p; //局部变量的定义hcnodetype cd[maxnodenumber]; //定义存储哈夫曼编码的数组for(i=0;i<="">{c=i; //为编码各节点初始化c和jj=maxbit;do{j--; //j指向bit中存放编码为的正确位置p=ht[c].parent; //p指向c的双亲节点if(ht[p].lchild==c) //如果c是p的左孩子cd[i].bit[j]=0; //编码为赋值0else //否则即c是p的右孩子cd[i].bit[j]=1; //编码赋值1c=p;//更新当前指针,为下一节点编码做准备}while(ht[p].parent!=-1); //判断是否编码结束即循环至最终根节点cd[i].start=j; //编码完成,记下编码开始位置}for(i=0;i<="">{for(j=cd[i].start;j<="">printf("%d",cd[i].bit[j]);printf("\n"); //每输出一编码后换行}}int main() //主函数{int n;printf("请输入节点数:"); //用户输入节点数scanf("%d",&n);htnode * p; // huffmanstree p //定义哈夫曼树类型pp=(htnode * )malloc(sizeof(htnode *));//p=(huffmanstree)malloc(sizeof(huffmanstree))//分配内存空间p=creatstree(n);//调用建立哈夫曼树函数赋返回值给pgetstree(p,n); //调用编码函数读入建立的哈夫曼树p进行编码return 0;}</m2)<></m1)<>。

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

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define n 6 /* 叶子数目*/
#define m 2*n-1 /* 结点总数*/
#define Maxval 1 /* 最大权值*/
typedef char datatype;
typedef struct //定义为结构类型
{
float weight; //权值
datatype data;
int lchild, rchild, parent;
} hufmtree;
hufmtree tree[m];
typedef struct
{ char bits[n]; /* 编码数组位串,其中n为叶子结点数目*/ int start; /* 编码在位串的起始位置*/
datatype data;
} codetype;
codetype code[n];
HUFFMAN(hufmtree tree[ ])
{ int i, j, p1,p2;
char ch;
float small1,small2,f;
for( i=0; i<m; i++) /* 初始化*/
{ tree[i].parent=0;
tree[i].lchild=0;
tree[i].rchild=0;
tree[i].weight=0.0;
tree[i].data= '0';
}
for( i=0;i<n;i++) /* 输入n个结点的权值*/
{ scanf("%f ", &f);
tree[i].weight=f;
scanf("%c", &ch); //* 输入n个结点的值*/
tree[i].data=ch;
}
for(i=n;i<m;i++)
{ p1=p2=0;
small1=small2=Maxval;
for ( j=0; j<=i-1; j++ )
if ( tree[j].parent==0)
if ( tree[j].weight<small1 )
{ small2=small1;
small1=tree[j].weight;
p2=p1;
p1=j;
} else if( tree[j].weight<small2 )
{ small2=tree[j].weight;
p2=j; }
tree[p1].parent=i;
tree[p2].parent=i;
tree[i].lchild=p1;
tree[i].rchild=p2;
tree[i].weight = tree[p1].weight+tree[p2].weight;
}
}
HUFFMANCODE(codetype code[ ],hufmtree tree[ ] ) /* code 存放求出的哈夫曼编码的数组*/
{ int i, c, p;
codetype cd;
for ( i=0; i<n; i++ )
{ cd. start=n;
c=i;
p=tree[c].parent;
cd.data=tree[c].data;
while( p!=0 )
{ cd.start-- ;
if( tree[p]. lchild == c)
cd.bits[cd.start]= '0';
else cd.bits [cd.start]='1';
c=p;
p=tree[c].parent;
}
code[i]=cd; /* 一个字符的编码存入code[i] */ printf("%c:",cd.data );//输出cd的数据语句
for(int k=cd.start;k<n;k++)printf("%c",cd.bits[k]);
printf("\n");
}
}
HUFFMANDECODE(codetype code[ ],hufmtree tree[ ]) { int i, c, p, b;
int endflag=2;
i=m-1;
scanf ( "%1d", &b);
while ( b != endflag)
{ if( b==0) i=tree[i].lchild;
else i=tree[i].rchild;
if ( tree[i].lchild==0 )
{ putchar( code[i].data);
i=m-1;
}
scanf("%1d", &b);
}
if ((tree[i].lchild!=0)&&(i!=m-1) )
printf("\nERROR\n");
}
void main()
{
printf("输入结点的权值和结点字母,用空格隔开:(如:0.4 a)\n");
HUFFMAN( tree);
printf("\n编码结果\n");
HUFFMANCODE(code, tree );
printf("\n开始译码,请输入密码:\n");
HUFFMANDECODE(code, tree);
printf("\n");
}。

相关文档
最新文档