1、软 件 学 院课程设计报告书课程名称 数据结构 设计题目 赫夫曼编码系统 专业班级 学 号 姓 名 指导教师 2012 年 1 月2目录1 设计时间 32 设计目的 33 设计任务 .34 设计内容 34.1 需求分析 .34.2 总体设计 .44.3 详细设 计 .64.4 测试与分析 104.4.1 测试 104.4.2 分析 114.5 附录 .115 总结与展望 .16参考文献.1831 设计时间 2012 年 1 月 2 日到 2012 年 1 月 6 日2 设计目的1) 巩固赫夫曼树的算法;2) 实现赫夫曼树的建立;3) 赫夫曼编码的生成;4) 赫夫曼文件的译码;3设计任务设计时间
2、一周,对输入的一串电文字符实现赫夫曼编码,再对赫夫曼编码生成的代码串进行译码,输出电文字符串。电报通信是传递文字的二进制码形式的字符串。但在信息传递时,总希望总长度能尽可能短,即采用最短码。设计实现的功能: (1) 赫夫曼树的建立; (2) 赫夫曼编码的生成; (3) 编码文件的译码。 4 设计内容 4.1需求分析 哈夫曼编码是一种编码方式,以哈夫曼树即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。称为赫夫曼编码。假设每种字符在电文中出现的次数为 Wi,编码长度为Li,电文中有 n 种字符,则电文编码总长度为WiLi。若将此对应到二叉树上,Wi 为叶结点的权,Li 为根结点到叶结点
3、的路径长度。那么,WiLi 恰好为二叉树上带权路径长度。因此 ,设计电文总长最短的二进制前缀编码,就是以 n 种字符出现的频率作权,构造一棵赫夫曼树。哈弗曼编码使用一张特殊的编码表将源字符进行编码。这张编码表的特殊之处在于,它是根据每一个源字符出现的估算概率而建立起来的(出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的) 。赫夫曼编码的应用很广泛,利用赫夫曼树求得的用于通信的二进制编码称为赫夫曼编码。树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0”码,指向右子树的分支表示“1”
4、 码,取每条路径上的 “0”或“1”的序列作为和各个叶子对应的字符的编码,这就是赫夫曼编码。哈弗曼译码输入字符串可以把它编译成二进制代码,输入二进制代码时可以编译成字符串。假设输入字符 BCD 编码成二进制代码应与特殊的编码表上的二进制编码相同输出应为40010100000,若出现其他情况的结果,错误;假设输入二进制代码 0010100000,则编译成字符串正确应为 BCD , 若出先其他情况的结果,错误。4.2总体设计(1) 、程序中用到的所有抽象数据类型的定义预定义常量#define N 50 #define M 2*N-1 #define MAXSIZE 100输入输出语句输入语句 sc
5、anf (格式串,变量 1,变量 2, 。 。 。 。 。变量 n);输出语句 printf(格式串,变量 1,变量 2, 。 。 。 。 。变量 n);赋值语句 变量名=表达式;循环语句 for(赋初值表达式序列;条件;修改表达式序列)结束语句 return 表达式;类型定义 Typedef int status(2) 、赫夫曼编码 要求电文的赫夫曼编码,必须先定义赫夫曼编码类型,根据设计要求和实际需要定义的类型如下: typedef structchar aN; int start; HCode;进行赫夫曼编码译码之前建立赫夫曼二叉树,新建立赫夫曼树,建立赫夫曼编码,进行主函数时,输入 A
6、 到 F 所有的字符,并输入其权值,将其进行编码;将 data 的权值赋给 ht,判断结点是否大于 1,输出根结点及权值。比较 i1将 data 和 weigth 赋给 HT输出根结点和权值调用 SELECT 函数 计算根结点函数双亲为两结点之和输出两子结点和双亲结点是否为根结点?左子树为空此时编码为 0I#include #include #include typedef structunsigned int weight;unsigned int parent,lchild,rchild;HTNode,*HuffmanTree;/动态分配赫夫曼树typedef char * *Huffma
7、nCode;/动态分配数组存储赫夫曼编码表int x1024,y1024,count;void SelectDifferentChar(int w,int /将输入的字符串中相同的字符删去 void HuffmanCoding(HuffmanTree void Select(HuffmanTree HT,int n,int void ScanfCrunode(int w,char z,int /读入结点,并将权值存到*w 数组中void PrintHuffmanCode(HuffmanCode HC,int w,int n ,float eve);void Everage(float 18vo
8、id main() HuffmanTree HT;HuffmanCode HC;int w1024,n;char z1024;float eve=0;ScanfCrunode(w,z,n);SelectDifferentChar(w,n);HuffmanCoding(HT,HC,w,n);Everage(eve,w,n,HC);PrintHuffmanCode(HC,w,n,eve);void ScanfCrunode(int w,char z,int gets(z);count=n=strlen(z);if(n #include #define MAXLEN 100 typedef stru
9、ct Huffmantree char ch; /*键值*/ int weight,mark; /*weight 为权值,mark 为标志域*/ struct Huffmantree *parent,*lchild,*rchild,*next; Hftree,*linktree; /*整理输入的字符串,合并相同的项,并求出每个字符在数组中出现的次数 */ linktree tidycharacter(char character) int i=0; linktree tree,ptr,beforeptr,node; /*链式 ,tree 为头结点,beforeptr 为 ptr 的前一结点,n
10、ode 为新申请的结点*/ tree=(linktree)malloc(sizeof(Hftree);/*创建单链表的头结点*/ if(!tree)return NULL; tree-next=NULL; /* 头结点为空,且后续结点为空*/ for(i=0;characteri!=0i+) /*遍历直到字符串结束为止*/ ptr=tree; beforeptr=tree; node=(linktree)malloc(sizeof(Hftree); /*新申请结点 node*/ if(!node)return NULL; node-next=NULL; node-parent=NULL; no
11、de-lchild=NULL; node-rchild=NULL; /*置空*/ node-mark=0; node-ch=characteri; node-weight=1; if(tree-next=NULL) tree-next=node; /*头结点的下一结点为空,连接 node*/ else ptr=tree-next; 22while(ptr beforeptr=beforeptr-next; /*后移*/ if(ptr /*将该结点的权加一*/ free(node); /*释放 node 结点的存储空间 */ else /*新结点与表中结点不相同, 将新结点插入链表后*/ nod
12、e-next=beforeptr-next; beforeptr-next=node; /*node 连接在 beforeptr 之后*/ return tree; /*将整理完的字符串按出现次数从小到大的顺序排列 */ linktree taxisnode(linktree tree) linktree head,ph,pt,beforeph; /*head 为新链表的表头结点 */ head=(linktree)malloc(sizeof(Hftree);/*创建新链表的头结点 */ if(!head)return NULL; head-next=NULL; /*新结点的头结点为空,后续结
13、点也为空*/ ph=head; beforeph=head; while(tree-next) pt=tree-next;/*取被操作链表的首元结点 */ tree-next=pt-next; pt-next=NULL; /*取出 pt 所指向的结点 */ ph=head-next; beforeph=head; if(head-next=NULL) head-next=pt;/*创建当前操作链表首元结点 */ else while(ph beforeph=beforeph-next; pt-next=beforeph-next; beforeph-next=pt; free(tree); 2
14、3return head; /*用排完序的字符串建立霍夫曼树 */ linktree createHftree(linktree tree) linktree p,q,newnode,beforep; for(p=tree-next,q=p-next;p!=NULLp=tree-next,q=p-next) tree-next=q-next; q-next=NULL; p-next=NULL; newnode=(linktree)malloc(sizeof(Hftree);/*申请新结点作为霍夫曼树的中间结点 */ if(!newnode)return NULL; newnode-next=N
15、ULL; newnode-mark=0; newnode-lchild=p;/*取链表头结点后的两个结点作为新结点的左、右儿子*/ newnode-rchild=q; p-parent=newnode; q-parent=newnode; newnode-weight=p-weight+q-weight; p=tree-next; beforep=tree; if(p!=NULL beforep-next=newnode; else while(p!=NULL beforep=beforep-next; newnode-next=beforep-next; beforep-next=newno
16、de; return (tree-next); /*对霍夫曼树进行编码 */ void Huffmancoding(linktree tree) int index=0; char *code; linktree ptr=tree; 24code=(char *)malloc(10*sizeof(char);/*此数组用于统计霍夫曼编码*/ printf(“字符以及它的相应权数-霍夫曼编码nn“); if(ptr=NULL) printf(“霍夫曼树是空的!n“); exit(0); else while(ptr-lchild ptr=ptr-lchild; if(!ptr-lchild co
17、deindex=0; printf(“tw%c=%dttt“,ptr-ch,ptr-weight); for(index=0;codeindex!=0;index+) printf(“%c“,codeindex); printf(“n“); ptr=tree; index=0; if(ptr-rchild codeindex+=1; if(!ptr-lchild codeindex+=0; printf(“tw%c=%dttt“,ptr-ch,ptr-weight); for(index=0;codeindex!=0;index+) printf(“%c“,codeindex); printf
18、(“n“); ptr=tree; index=0; if(ptr-lchild-mark=1 ptr=tree; index=0; 25printf(“n“); free(code); /*解码 */ void decode(linktree tree,char code) int i=0,j=0; char *char0_1; linktree ptr=tree; char0_1=(char *)malloc(10*sizeof(char);/*此数组用于统计输入的 0、1 序列*/ printf(“霍夫曼编码-相应字符nn“); for(j=0,ptr=tree;codei!=0j=0,p
19、tr=tree) for(j=0;codei!=0j+,i+) if(codei=0) ptr=ptr-lchild; char0_1j=0; if(codei=1) ptr=ptr-rchild; char0_1j=1; if(!ptr-lchild for(j=0;char0_1j!=0;j+) printf(“%c“,char0_1j); printf(“tt%cn“,ptr-ch); if(codei=0 printf(“没有与最后的几个 0、 1 序列:%s 相匹配的字符!n“,char0_1); return; free(char0_1); /*文件*/ void inchange
20、() FILE *fp; char ch; if(fp=fopen(“e10_1.c“,“rt“)=NULL) 26 printf(“Cannot open file strike any key exit!“); /getch(); exit(1); ch=fgetc(fp); while (ch!=EOF) putchar(ch); ch=fgetc(fp); fclose(fp); /*释放霍夫曼树所占用的空间*/ void deletenode(linktree tree) linktree ptr=tree; if(ptr) deletenode(ptr-lchild); delet
21、enode(ptr-rchild); free(ptr); void main() int n; char characterMAXLEN,codeMAXLEN; FILE *fp; linktree temp,ht,htree,ptr=NULL; printf(“一、编码:n 请输入要测试的字符串:n“); scanf(“%s“,character); printf(“n“); temp=tidycharacter(character); ht=taxisnode(temp); htree=createHftree(ht); Huffmancoding(htree); printf(“二、解码:n 请输入用于解码的 0、1 序列:n“); scanf(“%s“,code); printf(“n“); decode(htree,code); deletenode(htree); 27成绩评定成绩 教师签字