实验六 哈夫曼树及哈夫曼编码
数据结构实验实验报告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;
赫夫曼树及其编码

哈夫曼树构造算法
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语言哈夫曼树的构造及编码一、哈夫曼树概述哈夫曼树是一种特殊的二叉树,它的构建基于贪心算法。
它的主要应用是在数据压缩和编码中,可以将频率高的字符用较短的编码表示,从而减小数据存储和传输时所需的空间和时间。
二、哈夫曼树的构造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版)哈夫曼树实验报告

实验报告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_哈夫曼编码

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)树和哈夫曼编码讨论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最小的二叉树称为赫夫曼树或最优二叉树。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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");
}。