1、信息论霍夫曼编码译码实验报告实验一 一、实验背景 *哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般叫作Huffman编码。 二、实验要求 *利用程序实现哈夫曼编码,以加深对哈夫曼编码的理解,并锻炼编程能力。 三、代码分析 #include #define n 3 /叶子数目 #define m (2*n-1) /结点总数 #define maxval 10000.0 /maxval是float类型的最大值 #def
2、ine maxsize 100 /哈夫曼编码的最大位数 typedef struct /定义霍夫曼树结构体 char ch; /消息 float weight; /所占权重 int lchild,rchild,parent; /定义左孩子、右孩子 hufmtree; typedef struct /定义霍夫曼编码结构体 char bitsn; /位串 int start; /编码在位串中的起始位置 char ch; /字符 codetype; void huffman(hufmtree tree); /建立哈夫曼树 void huffmancode(codetype code,hufmtree
3、 tree); /根据哈夫曼树求出哈夫曼编码 void decode(hufmtree tree); /依次读入电文,根据哈夫曼树译码 void main() printf( 哈夫曼编码n); printf(信源共有%d个符号n,n); hufmtree treem; /m个结点,即有m个树形结构 codetype coden; /信源有n个消息,则需要n个编码 int i,j; /循环变量 huffman(tree); /建立哈夫曼树 huffmancode(code,tree); /根据哈夫曼树求出哈夫曼编码 printf(【输出每个字符的哈夫曼编码】n); for(i=0;in;i+)
4、printf(%c: ,codei.ch); for(j=codei.start;jn;j+) printf(%c ,codei.bitsj); /“消息:该消息的编码” printf(n); printf(【读入电文,并进行译码】n); decode(tree); /依次读入电文,根据哈夫曼树译码 void huffman(hufmtree tree) /建立哈夫曼树 int i,j,p1,p2; /p1,p2分别记住每次合并时权值最小和次小的两个根结点的下标 float small1,small2,f; char c; for(i=0;im;i+) /初始化 treei.parent=0;
5、 treei.lchild=-1; treei.rchild=-1; treei.weight=0.0; printf(【依次读入前%d个结点的字符及权值(中间用空格隔开)】n,n); for(i=0;in;i+) /读入前n个结点的字符及权值 printf(输入第%d个字符为和权值,i+1); scanf(%c %f,&c,&f); getchar(); /吸收回车符 treei.ch=c; treei.weight=f; /将接收到的结点的字符及权值存入它对应的结构体数据中 for(i=n;im;i+) /进行n-1次合并,产生n-1个新结点 p1=0;p2=0; small1=maxva
6、l;small2=maxval; /maxval是float类型的最大值 for(j=0;ji;j+) /选出两个权值最小的根结点 if(treej.parent=0) /还未找到父结点的 if(treej.weightsmall1) /如果有比最小的还小的 small2=small1; /改变最小权、次小权及对应的位置 small1=treej.weight; p2=p1; p1=j; else if(treej.weightsmall2) /如果有比最小的大,但比第二小的小的 small2=treej.weight; /改变次小权及位置 p2=j; /找出的两个结点是新节点i的两个孩子 t
7、reep1.parent=i; treep2.parent=i; treei.lchild=p1; /最小权根结点是新结点的左孩子 treei.rchild=p2; /次小权根结点是新结点的右孩子 treei.weight=treep1.weight+treep2.weight; /huffman /codetype code为求出的哈夫曼编码 /hufmtree tree为已知的哈夫曼树 void huffmancode(codetype code,hufmtree tree) /根据哈夫曼树求出哈夫曼编码 int i,c,p; codetype cd; /缓冲变量 for(i=0;in;i
8、+) cd.start=n; /编码在位串中的起始位置 cd.ch=treei.ch; c=i; /从叶结点出发向上回溯,第i个叶结点 p=treei.parent; /treep是treei的父结点 while(p!=0) cd.start-; if(treep.lchild=c) cd.bitscd.start=0; /treei是左子树,生成代码0 else cd.bitscd.start=1; /treei是右子树,生成代码1 c=p; /c记录此时的父结点 p=treep.parent; /p记录新的父结点,即原来的父结点的父结点,向上溯回 codei=cd; /第i+1个字符的编码
9、存入codei /huffmancode void decode(hufmtree tree)/依次读入电文,根据哈夫曼树译码 int i,j=0; char bmaxsize; i=m-1; /从根结点开始往下搜索 printf(输入发送的编码:); gets(b); printf(译码后的字符为); while(bj!=0) if(bj=0) i=treei.lchild; /走向左子树 else i=treei.rchild; /走向右子树 if(treei.lchild=-1) /如果回到叶结点,则把该结点的消息符号输出 printf(%c,treei.ch); i=m-1; /回到根结点 j+; printf(n); if(treei.lchild!=-1&bj=0) /电文读完,但尚未到叶子结点printf(nERRORn); /输入电文有错 /decode 四、实验补充说明 解码时,以回车键结束输入电文。 已修复“电文读完,但尚未到叶子结点”这种情况下不能显示”ERROR”的错误。 构建父结点时,使用的序号i是在n,m-1的,最初的消息在结点的序号在0,n-1,每次寻找新的父结点,都是从0到i寻找,所以就是会优先叶子结点进行合并,所以这是一种方差最小的最优霍夫曼编码。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1