赫夫曼树的应用.docx
- 文档编号:11270821
- 上传时间:2023-02-26
- 格式:DOCX
- 页数:18
- 大小:130.61KB
赫夫曼树的应用.docx
《赫夫曼树的应用.docx》由会员分享,可在线阅读,更多相关《赫夫曼树的应用.docx(18页珍藏版)》请在冰豆网上搜索。
赫夫曼树的应用
题目:
赫夫曼树的应用
课程名称:
《数据结构》课程设计
指导教师:
专业:
班级:
学号:
姓名:
学号:
姓名:
学号:
姓名:
学号:
姓名:
完成时间:
目录
一、前言2
二、程序设计目的3
三、需求分析3
四、概要设计3
1、主要需要用到的主要数据结构3
2、算法流程分析4
五、源程序和运行结果5
1.源程序如下5
2、运行结果11
六、调试分析14
1.测试的结果14
2.时间复杂度分析14
3.各模块在设计和调试时存在问题14
4.算法的改进设想14
七、设计心得和总结15
八、参考书籍15
一、前言
赫夫曼编码(HuffmanCoding)是一种编码方式,赫夫曼编码是可变字长编码(VLC)的一种。
赫夫曼压缩是个无损的压缩算法,一般用来压缩文本和程序文件。
赫夫曼压缩属于可变代码长度算法一族。
意思是个体符号(例如,文本文件中的字符)用一个特定长度的位序列替代。
因此,在文件中出现频率高的符号,使用短的位序列,而那些很少出现的符号,则用较长的位序列。
赫夫曼编码的应用很广泛,利用赫夫曼树求地的二进制编码称为赫夫曼编码。
赫夫曼树中从根到每个叶子都有一条路径,对路径上的各分支约定:
指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为对应的编码,这就是赫夫曼编码。
我们在对一些问题进行求解时,会发现有些问题很难找到规律,或者根本无规律可寻。
对于这样的问题,可以利用计算机运算速度快的特点,先搜索查找所有可能出现的情况,再根据题目条件从所有可能的情况中,删除那些不符合条件的解。
由赫夫曼算法的定义可知,初始森林中共有n棵只含有根结点的二叉树。
算法的的第二步是:
算法的的第二步是:
将当前森林中的两棵根结点权值最小的二叉树,合并成一棵新的二叉树,每合并一次,森林中就减少一棵树,产生一个新结点。
则要进行n-1次合并,所以共产生n-1个新结点。
由此可知,最终求得的赫夫曼树中一共有2n-1个结点。
其中,n个结点是初始森林中的n个孤立结点。
并且赫夫曼树中没有度数为1的分支的结点。
采用赫夫曼编码方案,即应用赫夫曼树构造使电文的编码总长最短的编码方案。
二、程序设计目的
1.熟悉掌握C语言的基础知识和技能;
2.学习利用计算机语言实现赫夫曼树构造的算法;
3.了解利用赫夫曼树对给定权值的字符的赫夫曼编码的算法思想。
三、需求分析
1、打开一个文本文件,用一个指针指向它,指针变量为*pf
2、对其进行字母频率统计,把字母和字母的频率放到结构体syrs1[]中
3、用Huffman算法建立Huffman树以及每个字母的Huffman码(Huffman数以及Huffman码两张表,均要求输出,最好能在文本中输出)
4、把该文本文件的英文文章利用Huffman树编码生成二进制文件(该文件要求输出)
5、打开该二进制文本文件,对其解码,仍然利用刚才的Huffman树进行解码
6、输入,输出要求都是读取文件。
四、概要设计
1、主要需要用到的主要数据结构
a、赫夫曼树的数据结构
typedefstruct
{
chardata;
intweight;
intparent;
intlchild;
intrchild;
}HuffmanTree[M];
b、赫夫曼编码的数据结构
typedefstruct
{
chardata;
charbits[N];
}HuffmanCode[N];
c、字符串存储单元的数据结构
typedefstructstr
{
chardata;
charnum;
//intnum;
}str;
2、算法流程分析
a、建立赫夫曼树的数据结构、赫夫曼编码的数据结构和字符串存储单元的数据结构,字符串存储单元的数据结构是用来存储字母和对应的权值。
b、调用intread(strs2[])函数,取读文本ywq1.txt并统计这里出现字符的个数(字母区分大小写、空格键和各种标点符号),再统计该字符在文本中出现的频率(也就是所谓的权值)存放在结构体strs2[]中,返回字母个数k,打印字母的和对应的权值。
c、调用CrtHuffmanTree(ht,s2,k)函数来创建赫夫曼数,首先初始化节点并给其赋值0,利用for的循环语句并调用SelectMin函数,查找哈夫曼链表中两个权值最小的来建立赫夫曼树,打印赫夫曼树各节点的权值和它的左右孩子。
d、调用CrtHuffmanCode(ht,hc,k)利用建立好的哈夫曼树对文本文本ywq1.txt进行编码,并把编译的赫夫曼编码储存在文本ywq2.txt中,并且打印出来文本的赫夫曼编码。
e、通过调用DecodHuffmanCode(ht,k)将文本ywq2.txt字符的赫夫曼码翻译为字符,这就是所谓的反译码,把翻译的英语文章存储在文本ywq3.txt并且存储,并且在对话执行框中打印出来。
五、源程序和运行结果
1.源程序如下
#include
#include
#include
#defineN100
#defineM2*N-1
typedefstruct//定义哈夫曼树存储节点结构体类型
{
chardata;
intweight;
intparent;
intlchild;
intrchild;
}HuffmanTree[M];
typedefstruct//定义哈夫曼编码结构体类型
{
chardata;
charbits[N];
}HuffmanCode[N];
typedefstructstr//定义字符串存储单元结构体类型
{
chardata;
charnum;
//intnum;
}str;
intread(strs2[])
{
FILE*fp;
charch;
inti,k;
strs1[128];
for(i=0;i<=128;i++)
{
s1[i].num=0;s1[i].data=0;
s2[i].num=0;s2[i].data=0;
}
if((fp=fopen("ywq1.txt","r"))==NULL)
{
printf("\n库文件不存在!
");
exit
(1);
}
printf("\n读取字符串为:
\n");
ch=fgetc(fp);
while(!
feof(fp))//统计字符频率
{
printf("%c",ch);
s1[ch].num++;
s1[ch].data=ch;
ch=fgetc(fp);
}
fclose(fp);
for(i=1,k=1;i<=128;i++)
{
if(s1[i].num!
=0)
{
s2[k].num=s1[i].num;
s2[k].data=s1[i].data;
k++;
}
}
printf("\n\n统计结果为(字符频率):
\n");
for(i=1;i { printf("<%c%d>",s2[i].data,s2[i].num); } printf("(共%d种字符)\n",k-1); returnk; } voidSelectMin(HuffmanTreeht,inti,int*p1,int*p2)//查找哈夫曼链表中两个权值最小的节点 { intj,min1,min2; min1=min2=-1; for(j=1;j<=i;j++) { if(ht[j].parent==0) { if(ht[j].weight { if(min1! =-1) {min2=min1;*p2=*p1;} min1=ht[j].weight;*p1=j; } elseif(ht[j].weight { min2=ht[j].weight; *p2=j; } } } } voidCrtHuffmanTree(HuffmanTreeht,strs[],intn)//创建哈夫曼树 { inti,m,p1,p2; for(i=1;i { ht[i].data=s[i].data; ht[i].weight=s[i].num; ht[i].parent=0; ht[i].lchild=0; ht[i].rchild=0; } m=2*n-3; for(i=n;i<=m;i++) { ht[i].data=0; ht[i].weight=0; ht[i].parent=0; ht[i].lchild=0; ht[i].rchild=0; } for(i=n;i<=m;i++) { SelectMin(ht,i-1,&p1,&p2);//调用SelectMin函数 ht[i].weight=ht[p1].weight+ht[p2].weight; ht[p1].parent=i;ht[p2].parent=i; ht[i].lchild=p1;ht[i].rchild=p2; } } voidCrtHuffmanCode(HuffmanTreeht,HuffmanCodehc,intk)//利用建立好的哈夫曼树对字符串进行编码 { intc,p,i; charcd[N+1]; intstart; for(i=1;i { hc[i].data=ht[i].data; start=k-1; cd[start]='\0'; c=i; while((p=ht[c].parent)! =NULL) { cd[--start]=(ht[p].lchild==c)? '0': '1';//左分支为0,右分支为1 c=p; } strcpy(hc[i].bits,&cd[start]); } printf("\n\n每个字符对应的编码为: \n"); for(i=1;i printf("<%d%c%s>\n",i,hc[i].data,hc[i].bits); } voidWriteToFile(HuffmanCodehc,intn)//将编码结果存储在文件文件ywq2.txt中 { FILE*fp1,*fp2; charch; inti; if((fp1=fopen("ywq1.txt","r"))==NULL) { printf("\n文件不存在! "); exit (1); } if((fp2=fopen("ywq2.txt","w"))==NULL) { printf("\n文件不存在! "); exit (1); } ch=fgetc(fp1); printf("\n编码结果为: "); while(ch! =EOF) { for(i=1;i if(ch==hc[i].data) { fputs(hc[i].bits,fp2); printf("%s",hc[i].bits); } ch=fgetc(fp1); } fclose(fp1); fclose(fp2); printf("\n"); } voidDecodHuffmanCode(HuffmanTreeht,intn)//码结果进行译码,并将结果存储在文件ywq3中 { FILE*fp1,*fp2; charch; intp,k; if((fp1=fopen("ywq2.txt","r"))==NULL) { printf("\n文件不存在! "); exit (1); } if((fp2=fopen("ywq3.txt","w"))==NULL) { printf("\n文件未能创建! "); exit (1); } p=k=2*n-3; ch=fgetc(fp1); printf("译码为: "); while(ch! =EOF) { if(ch=='0')p=ht[p].lchild; elseif(ch=='1')p=ht[p].rchild; if(ht[p].data! =0) { printf("%c",ht[p].data); fputc(ht[p].data,fp2); p=k; } ch=fgetc(fp1); } printf("\n"); fclose(fp1);fclose(fp2); } voidcompare(intk) { FILE*fp1,*fp2; chars1[N],s2[N]; inti=1,j=1; printf("\n\n编译前后结果的比较: "); if((fp1=fopen("ywq1.txt","rt"))==NULL) { printf("\n打开文件失败! \n"); exit (1); } printf("\n\n原文件ywq1中的字符为: "); for(i=1;(s1[i]=fgetc(fp1))! =EOF;i++) printf("%c",s1[i]); fclose(fp1); if((fp2=fopen("ywq3.txt","rt"))==NULL) { printf("\n打开文件失败! \n"); exit (1); } printf("\n文件ywq3中的字符为: "); for(i=1;(s2[i]=fgetc(fp2))! =EOF;i++) printf("%c",s2[i]); fclose(fp2); while(j { if(s1[j]==s2[j]) j++; else { printf("\n编码失败! \n"); break; } } if(j==k) printf("\n前后数据一致,编码成功! \n"); } voidmain() { inti,k; intj=1; HuffmanTreeht; HuffmanCodehc; strs2[128]; printf("\n-------------------------------哈夫曼编码译码器---------------------------------"); k=read(s2); getchar(); CrtHuffmanTree(ht,s2,k); CrtHuffmanCode(ht,hc,k); WriteToFile(hc,k); getchar(); printf("\n\n"); printf("建立的哈夫曼树为: "); printf("\nnumber\tdata\tweight\tlchild\trchild\tparent"); for(i=1;i { printf("\n%d: %c%d%d%d} printf("\n\n"); DecodHuffmanCode(ht,k); getchar(); compare(k); //printf("\n\n按任意键退出...\n"); } 2、运行结果 注意: 在运行的时候,一直按【Enter】键执行 六、调试分析 1.测试的结果 请参考上面的运行结果。 2.时间复杂度分析 构造赫夫曼树: T(n)=O(n) 建立赫夫曼表: T(n)=O(n2) 进行译码: T(n)=O(n) 赫夫曼编码T(n)=O(n³) 3.各模块在设计和调试时存在问题 a、怎样把一篇文章英语文章的字符个数统计出来,并且把权值给统计出来,最后是用什么来存储。 b、建立赫夫曼树,先找到权值最小的两个字符建立成赫夫曼树,并且写出赫夫曼码。 c、最大的难题是怎么把文本用赫夫曼码代替,就是把英语文章翻译成赫夫曼码,就是所谓的译码过程。 d、将译码后的文章打印出来 4.算法的改进设想 在这个算法中我觉得有个地方要改进,就是在编译和反编译的过程中,存储的那些赫夫曼码和英语文章在每次执行之后没有自己清除,我觉得这个地方要改进,还有一点这个算法在时间复杂度上面有点复杂,但是我没有找到好的方法,这是我觉得这个算法要改进的地方 七、设计心得和总结 八、参考书籍 《数据结构理论与实践》杨永斌.主编天津科学技术出版社
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 赫夫曼树 应用
![提示](https://static.bdocx.com/images/bang_tan.gif)