1、赫夫曼编码的应用实验课程名称 赫夫曼编码的应用 专 业 班 级 10级计科(1)班 学 生 姓 名 学 号 指 导 教 师 2012至2013学年第 一 学期第 1 至 18 周目 录第1章 概述 2第2章 系统分析 22.1 分析思想 22.2 需求分析及要求 32.3 研究意义 3第3章 概要设计 43.1 设计总图 4第4章详细设计 54.1 程序中用到的所有抽象数据类型的定义 54.2 主程序模块 54.3 赫夫曼树的建立 54.4 赫夫曼编码 54.5 赫夫曼编码的生成 64.6 赫夫曼树的存储结构描述 6第5章 运行与测试 7第6章 总结和心得 7参考文献 7伪代码 7第1章 概述
2、 在当今信息爆炸时代,如何采用有效的数据压缩技术节省数据文件的存储和计算机网络的传送时间已越来越引起人们的重视,赫夫曼编码正是一种应用广泛且非常有效的数据压缩技术。第2章 系统分析2.1 分析思想1) 巩固赫夫曼树的算法;2) 实现赫夫曼树的建立;3) 赫夫曼编码的生成;4) 赫夫曼文件的译码;5) 运行测试实例。2.2 需求分析及要求本设计要求对输入的一串电文字符实现赫夫曼编码,再对赫夫曼编码生成的代码串进行译码,输出电文字符串。 通常我们把数据的压缩过程称为编码,解压缩的过程称为解码。电文编码总长的二进制码形式的字符串。但在信息传递时,总希望总长度尽可能最短,即采用最短短码。而设计电文总长
3、最短的二进制前缀编码,就是以n种字符出现的频率作权,构造一颗赫夫曼树,此造构过程称为赫夫曼编码。2.3 研究意义赫夫曼编码了解:哈夫曼编码是一种编码方式,以哈夫曼树即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。称为赫夫曼编码。假设每种字符在电文中出现的次数为Wi,编码长度为Li,电文中有n种字符,则电文编码总长度为WiLi。若将此对应到二叉树上,Wi为叶结点的权,Li为根结点到叶结点的路径长度。那么,WiLi恰好为二叉树上带权路径长度。因此 ,设计电文总长最短的二进制前缀编码,就是以n种字符出现的频率作权,构造一棵赫夫曼树。哈弗曼编码使用一张特殊的编码表将源字符进行编码。这张编码
4、表的特殊之处在于,它是根据每一个源字符出现的估算概率而建立起来的(出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的)。赫夫曼编码的应用很广泛,利用赫夫曼树求得的用于通信的二进制编码称为赫夫曼编码。树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为和各个叶子对应的字符的编码,这就是赫夫曼编码。第3章 概要设计3.1 设计总图第4章详细设计4.1 程序中用到的所有抽象数据类型的定义预定义常量#define N 5
5、0 #define M 2*N-1 #define MAXSIZE 100输入输出语句输入语句 scanf (格式串,变量1,变量2,。变量n);输出语句 printf(格式串,变量1,变量2,。变量n);赋值语句 变量名=表达式;循环语句 for(赋初值表达式序列;条件;修改表达式序列)结束语句 return表达式;类型定义Typedef int status4.2 主程序模块其中主函数为: main() 定义以及初始化 从文件中读取数据,输出矩阵调用转置和加法函数,输出转置矩阵以及加法矩阵 4.3 赫夫曼树的建立1. 选择parent为0且权值最小的两个根结点的算法2统计字符串中字符的种类
6、以及各类字符的个数3构造赫夫曼树 4. 赫夫曼树的存储5. 赫夫曼编码的算法6. 建立正文的编码文件4.4 赫夫曼编码 要求电文的赫夫曼编码,必须先定义赫夫曼编码类型,根据设计要求和实际需要定义的类型如下: typedef struct char aN; int start; HCode; 进行赫夫曼编码译码之前建立赫夫曼二叉树,新建立赫夫曼树,建立赫夫曼编码,进行主函数时,输入A到F所有的字符,并输入其权值,将其进行编码;将data的权值赋给ht,判断结点是否大于1,输出根结点及权值。比较i2*N-1;若是调用调用SELECT函数算出算出父亲结点然后输出两子结点及父亲结点。4.5 赫夫曼编码
7、的生成1. 建立赫夫曼树的三个函数void select(HuffmanTree T , int k, int &s1, int &s2) 2. 生成赫夫曼编码文件的两个函数void HuffmanEncoding(HuffmanTree HT, HuffmanCode HC) 3. 电文的译码char *decode(HuffmanCode HC) 4.6 赫夫曼树的存储结构描述 #define N 100 / 叶子结点数 #define M 2*N-1 / 赫夫曼树中结点总数 typedef struct int weight; / 叶子结点的权值 int lchild, rchild,
8、parent; / 左右孩子及双亲指针 HTNode; / 树中结点类型 第5章 运行与测试第6章 总结和心得在做本次试验之前我阅读了数据结构课程设计中关于赫夫曼的应用这一章节知识,在编写这个程序之前,我复习之前学习的基本知识,赫夫曼最小路径的求法,赫夫曼编码及译码的范围,程序结构等相关问题。还上网查阅了相关知识,了解到什么是赫夫曼树,什么是赫夫曼编码等问题,还去了解电文的编码、译码问题等来加深对它们的理解,还查阅了关于“树”的内容。通过这次的课程设计,让我在程序编写上有了很大的,提高感觉到了程序设计真的很锻炼人,自己要学会慢慢的摸索路径,这样形成自己编程时的特色。一个成功的程序,要经过之前对
9、课题的反复思考。这次我运用的是数组存储类型,结构简单而且方便。通过运用for的多重循环,提高运行的效率。参考文献1 数据结构:严蔚敏,吴伟民编著.北京:清华大学出版社,2007 2 数据结构与算法分析:苏仕华编著.合肥:中国科学技术大学出版社,20043 数据结构课程设计:苏仕华编著.北京:清华大学出版社,20024 徐孝凯.数据结构简明教程M. 清华大学出版社,1995年伪代码#include #include #include #include typedef struct unsigned int weight; unsigned int parent,lchild,rchild;HTN
10、ode,*HuffmanTree;/动态分配赫夫曼树typedef char * *HuffmanCode;/动态分配数组存储赫夫曼编码表int x27,y9,count;void SelectDifferentChar(int w,int &n);/将输入的字符串中相同的字符删去 void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int w,int n);void Select(HuffmanTree HT,int n,int &s1,int &s2);void ScanfCrunode(int w,char z,int &n);/读入结点
11、,并将权值存到*w数组中void PrintHuffmanCode(HuffmanCode HC,int w,int n ,float eve);void Everage(float &eve,int w,int n,HuffmanCode HC);void main() HuffmanTree HT; HuffmanCode HC; int w254,n; char z27; float eve=0; printf(请输入字符串:n); ScanfCrunode(w,z,n); SelectDifferentChar(w,n); HuffmanCoding(HT,HC,w,n); Evera
12、ge(eve,w,n,HC); PrintHuffmanCode(HC,w,n,eve);void ScanfCrunode(int w,char z,int &n)/读入结点,并将权值存到*w数组中 int i; gets(z); count=n=strlen(z); if(n=1) printf(wrong datan);exit(0);for(i=0;in;i+) wi=zi;void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int w,int n)/赫夫曼编码int m,i,s1,s2,start,f,c; char *cd; m=2
13、*n-1; HT=(HuffmanTree)malloc(m+1)*sizeof(HTNode);/0号单元没用 for(i=1;i=n;i+) HTi.weight=wi-1; HTi.parent=0; HTi.rchild=0; HTi.lchild=0; for(;i=m;i+) HTi.weight=0; HTi.parent=0; HTi.rchild=0; HTi.lchild=0; for(i=n+1;i=m;i+) Select(HT,i-1,s1,s2); HTs1.parent=i; HTs2.parent=i; HTi.lchild=s1; HTi.rchild=s2;
14、 HTi.weight=HTs1.weight+HTs2.weight; HC=(HuffmanCode)malloc(n+1)*sizeof(char *); cd=(char *)malloc(n*sizeof(char); cdn-1=0; for(i=1;i=n;i+) start=n-1; for(c=i,f=HTi.parent;f!=0;c=f,f=HTf.parent) if(HTf.lchild=c) cd-start=0; else cd-start=1; HCi=(char *)malloc(n-start)*sizeof(char); strcpy(HCi,&cdsta
15、rt); free(cd);void Select(HuffmanTree HT,int n,int &s1,int &s2)int i,j,k; k=32767;/无符号整数最大值 for(i=1;i=n;i+) if(HTi.weightk&HTi.parent=0) j=i; k=HTi.weight; s1=j; k=32767; for(i=1;i=n;i+) if(HTi.weightk&HTi.parent=0&i!=s1) j=i; k=HTi.weight; s2=j;void SelectDifferentChar(int w,int &n)int i,j,d=0,k; f
16、or(i=0;in;i+) yi=wi; for(i=0;in;i+) for(j=i+1;jn;j+) if(wi=wj) wj=-1; for(i=0;in;i+) if(wi!=-1) xd=wi;d+; k=n; n=d; for(i=0;in;i+) d=0; for(j=0;jk;j+) if(xi=yj) d+;wi=d; if(n=1) printf(wrong datan);exit(0);void Everage(float &eve,int w,int n,HuffmanCode HC)int sum=0,i; for(i=0;in;i+) sum+=wi; for(i=
17、0;in;i+) eve+=(float)wi/sum)*strlen(HCi+1);void PrintHuffmanCode(HuffmanCode HC,int w,int n ,float eve)int i,j,k;for(i=0;in;i+) printf(%c编码为:,xi); puts(HCi+1); printf( 出现次数为%d,wi); printf(n); printf(平均编码长度为:%.2fn,eve); printf(译文如下n); for(i=0;icount;i+) for(j=0;jn;j+) if(yi=xj) for(k=0;kstrlen(HCj+1);k+) printf(%c,HCj+1k); printf(n);
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1