数据结构课程设计-赫夫曼编码的应用_第1页
数据结构课程设计-赫夫曼编码的应用_第2页
数据结构课程设计-赫夫曼编码的应用_第3页
数据结构课程设计-赫夫曼编码的应用_第4页
数据结构课程设计-赫夫曼编码的应用_第5页
已阅读5页,还剩30页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、西南大学计算机与信息科学学院课程设计报告课程:数据结构课程设计题目:赫夫曼编码的应用级、专业:2014级计算机专业2 班学生姓名:提交日期: 2016年 06月 23日内容提要:这次的数据结构课程设计分为两个部分:基础部分和综合部分。基础的部分只是为了巩固基础知识,综合设计是主要部分。基础部分:基础部分是为了巩固加强基础知识,为综合的实验报告奠定基础。其中的内容包括一元多项式的相加,图的基本操作,树的基本操作。从基础部分着手,简单的两个多项式的相加的实现,图的基本操作的实现,树的基本操作的实现。综合部分:综合部分针对综合的设计能力的锻炼,在基础的部分上增强。综合部分就是做赫夫曼编码译码系统。输

2、入一些字符串或者是英文句子,根据字符出现的比重进行权值的计算,从而建立赫夫曼树,赫夫曼树是赫夫曼编码的基础,在赫夫曼树建立之上对其进行编码和译码。首先实现的是编码,其次是译码。根据每个字符的编码,译码的时候,输入密文,会自动的去编码表中寻找匹配的字符,从而进行译码,并打印出译码的明文。关键词:赫夫曼树编码电文译码链表图数据结构指针参考书目:数据结构(C语言版)清华大学出版社严蔚敏吴伟民编著数据结构课程设计第2版机械工业出版社苏仕华魏韦巍王敬生刘燕君编著成绩评定:指导教师(签字):年月日目录一、 基础设计部分011. 问题描述012. 功能需求分析013. 总体设计014. 详细设计025. 源

3、代码036. 测试177. 总结18二、 综合设计部分201. 问题描述202. 功能需求分析203. 总体设计214. 详细设计225. 源代码256. 测试307. 总结31三、 参考文献3131一、基础部分课程设计1 问题描述基础部分有三个基础的简单的程序。在这三个简单的课程设计之中要实现一元多项式的相加、图的基本操作以及树的基本操作。针对一元多项式相加的问题,如何实现在屏幕上把输入的两个要相加的一元多项式分别的显示出来以及相加以后的结果以多项式的形式显示出来?针对图的基本操作,如何实现用领接矩阵建立一个图?如何在建立好一个图的基础上实现广度优先和深度优先遍历等等问题?针对树的综合,如何

4、运用二叉链表建立树?以及二叉链表的遍历(包括先序、中序、后序、递归、非递归等)的实现等问题的解决?2 功能需求分析 一元多项式的相加:一元多项式的相加运算主要完成的是分别输入两个多项式,实现两个多项式指数对应的项的系数相加,并把相加的结果在屏幕上打印出来。在开始的时候输入每个多项式的项数之后再以成对的形式输入系数和指数,然后对应指数相等的项系数相加合并。 图的综合:图的综合实现了以邻接矩阵的方式构造一个图,而且在此基础上面广度优先和深度优先实现图的遍历。输入一个图的节点个数,再输入每个节点的符号,依次输入两个节点之间的路径长度构造邻接矩阵,并以广度优先和深度优先实现图的遍历过程。 树的基本操作

5、:树的基本操作实现的功能包括输入字符建立二叉链表构造树,先序、中序以及后序遍历用递归算法实现,求二叉树的叶子个数以及借助队列实现二叉树的层次遍历。3 总体设计基础部分的总体结构:基础部分一元多项式的相加树的综合图的综合二叉树的叶子结数以及层次遍历遍历二叉树建立二叉链表实现两个多项式的相加邻接矩阵构造图在屏幕上打印出计算结果分别输入两个多项式图的遍历:广度优先和深度优先4 详细设计1. 一元多项式的相加结构体:typedef int ElemType; typedef struct PolynNode /*单项链表的声明*/ int coef; / 系数 int expn; / 指数struct

6、 PolynNode *next; PolynNode,*PolynList; /*正位序(插在表尾)输入n个元素的值,建立带表头结构的单链线性表*/ /*指数系数一对一对输入*/2. 图的基本操作的结构体:struct stuchar name3;struct sttstruct stu ding10;int jz1010;int dd;struct shustruct stu * p;struct shu * l;struct shu * r;3. 树的基本操作的结构体:int dep, count= 0;typedef int Status;typedef char TElemType;

7、typedef struct BiTNode TElemType data; struct BiTNode *lchild, *rchild; /*右孩子,左孩子*/BiTNode, *BiTree;5 源代码 一元多项式的相加的源程序代码:#include#include#includetypedef int ElemType; typedef struct PolynNode /*单项链表的声明*/ int coef; / 系数 int expn; / 指数struct PolynNode *next; PolynNode,*PolynList; /*正位序(插在表尾)输入n个元素的值,建

8、立带表头结构的单链线性表*/ /*指数系数一对一对输入*/ void CreatePolyn(PolynList &L,int n) int i; PolynList p,q; L=(PolynList)malloc(sizeof(PolynNode); / 生成头结点 L-next=NULL; q=L; printf(n 成对输入多项式ha的%d个数据:,n); for(i=1;icoef,&p-expn); /指数和系数成对输入 q-next=p; q=q-next; p-next=NULL; / 初始条件:单链表L已存在/ 操作结果: 依次对L的每个数据元素调用函数vi()。一旦vi()

9、失败,则操作失败void PolynTraverse(PolynList L,void(*vi)(ElemType, ElemType) PolynList p=L-next; while(p) vi(p-coef, p-expn); if(p-next) printf( + ); /+号的输出,最后一项后面没有+ p=p-next; printf(n); /*ListTraverse()调用的函数(类型要一致)*/ void visit(ElemType c, ElemType e) if(c != 0) printf(%dX%d,c,e); /格式化输出多项式每一项 /* 多项式相加,原理

10、:归并 */ /* 参数:两个已经存在的多项式 */ /* 返回值:归并后新的多项式的头结点 */ PolynList MergeList(PolynList La, PolynList Lb) PolynList pa, pb, pc, Lc; pa = La-next; pb = Lb-next; Lc = pc = La; / 用La的头结点作为Lc的头结点while(pa&pb) if(pa-expn expn) pc-next = pa; /如果指数不相等,pc指针连上指数小的结点,pc = pa; pa = pa-next; /指向该结点的指针后移 else if (pa -exp

11、n pb-expn ) pc-next = pb; /pc指针连上指数小的结点,pc = pb; pb = pb-next; /指向该结点的指针后移 else /(pa -expn = pb-expn ) pa-coef = pa-coef + pb-coef; /指数相等时,系数相加pc-next = pa; pc = pa; pa = pa-next; /两指针都往后移pb = pb-next; pc-next = pa ? pa:pb; / 插入剩余段return Lc; int main() int m,n; PolynList ha,hb,hc;printf(1.输入第一个多项式的项

12、数:);scanf(%d,&m); printf( 非递减输入多项式ha ); CreatePolyn(ha,m); / 正位序输入n个元素的值printf(n); printf(2.输入第二个多项式的项数:);scanf(%d,&n); printf( 非递减输入多项式hb ); CreatePolyn(hb,n); / 正位序输入n个元素的值printf(n); printf(3.多项式ha :); PolynTraverse(ha, visit); printf(n); printf(4.多项式hb :); PolynTraverse(hb, visit); printf(n); pri

13、ntf(5.一元多项式的相加结果为:); hc = MergeList(ha,hb); PolynTraverse(hc, visit); 图的基本操作的源程序代码:#include #include#includestruct stuchar name3;struct sttstruct stu ding10;int jz1010;int dd;struct shustruct stu * p;struct shu * l;struct shu * r;struct stt * jltu()int i=0,j=0;struct stt * p;p=(struct stt *)malloc(s

14、izeof(struct stt);p-dd=0;for(;i10;i+)for(j=0;jjzij=100;return p;void txtu(struct stt * p)void scjd(struct stt * p);int i,j=0;printf(输入节点数:(dd=i;while(i-)printf(输入第%d个结点名字:n,p-dd-i);gets(p-dingj+.name);printf(构造邻接矩阵:(各节点间的距离,无联系为:100)n);for(i=0;idd;i+)for(j=i+1;jdd;j+)printf(输入点%s与点%s的距离:n,p-dingi.na

15、me,);scanf(%d,&p-jzij);p-jzji=p-jzij;scjd(p);void scjd(struct stt * p)int i=p-dd,j=0;printf(顶点数:%dn,i);while(i-)printf(姓名:%sn,);j+;printf(邻接矩阵为:n);for(i=0;i10;i+)for(j=0;jjzij);printf(n);void bianli(struct stt * p)void gdbl(struct stt * p,int i,int b10);void sdbl(struct stt *

16、 p,int i,int b10);int i,j,b10=1,1,1,1,1,1,1,1,1,1;i=p-dd;while(i-)bi=0;printf(从第几个结点开始遍历?n);scanf(%d,&i);j=i;printf( 深度遍历:n);sdbl(p,i,b);i=p-dd;while(i-)bi=0;printf(n);printf( 广度遍历:n);gdbl(p,j,b);void gdbl(struct stt * p,int i,int b10)int pd(int b10);int j=0,m,k=0,a10=11,11,11,11,11,11,11,11,11,11;a

17、j+=i;bi=1;while(!pd(b)i=ak;m=0;while(mjzim!=100&!bm) aj+=m;bm=1;m+;k+;k=0;while(ak!=11)printf(-%s-,p-dingak+.name);int pd(int b10)int i=0;while();bi=1;while(jdd)if(pd(b) break;if(p-jzij!=100&!bj) sdbl(p,j,b);j+;void scs(struct stt * p)int i,j,k=0,m,n;int a10,b10;struct shu * gen,* p1;prin

18、tf(选择根结点:n);scanf(%d,&j);n=j;for(i=0;i10;i+)ai=j;for(i=0;ijzji;while(k+dd)for(i=1,j=0;ibi) j=i;bj=bj+100;for(m=0;mjzjmbm&bmjzjm;am=j;i=0;while(i10)printf( %d ,ai+);printf(这个数组每个位置是其值的孩子,不一定是二叉树所以出现下一个相同值时其位置为该值左孩子的右孩子,依次类推。n);int main()struct stt * p;p=jltu();txtu(p);bianli(p);printf(n);scs(p);retur

19、n 0; 树的基本操作的源程序代码:#include #include#include#define OK 1#define ERROR 0#define OVERFLOW -1#define LIST_INT_SIZE 100#define LISTINCREMENT 10int dep, count= 0;typedef int Status;typedef char TElemType;typedef struct BiTNode TElemType data;struct BiTNode *lchild, *rchild;BiTNode, *BiTree;/建立二叉树Status Cr

20、eateBiTree(BiTree &T)char ch;getchar();scanf(%c, &ch);if(ch = | ch = n) T = NULL;return ERROR; else T = (BiTree)malloc(sizeof(BiTNode); T-data = ch;printf(请输入%c的左孩子:, T-data);CreateBiTree(T-lchild); printf(请输入%c的右孩子:, T-data);CreateBiTree(T-rchild);return OK; /主菜单void print()printf(n菜单:n);printf(1 .

21、 输入字符序列,建立二叉链表n);printf(2 . 先序、中序、后序遍历二叉树:递归算法n);printf(3 . 中序遍历二叉树:非递归算法n);printf(4 . 求二叉树的叶子个数n);printf(5 . 借助队列实现二叉树的层次遍历n);printf(0 . EXITn请选择操作序号:);/先序、中序、后序遍历二叉树:递归算法void print2() printf(n递归算法遍历二叉树,菜单如下:n);printf(1.先根遍历n); printf(2.中序遍历n);printf(3.后续遍历n); printf(0.退出n); printf(请输入二级菜单选择:);Stat

22、us Visit(BiTree T)if(T) printf(%c , T-data);return OK; Status PrintElement(TElemType e)printf( %c , e);return OK;/先序Status PreOrderTraverse(BiTree T, Status (*Visit)(TElemType e)if(T) if(Visit(T-data)if(PreOrderTraverse(T-lchild, Visit)if(PreOrderTraverse(T-rchild, Visit)return OK;return ERROR; else

23、return OK; /中序Status MidOrderTraverse(BiTree T, Status (*Visit)(TElemType e)if(T) if(MidOrderTraverse(T-lchild, Visit)if(Visit(T-data)if(MidOrderTraverse(T-rchild, Visit)return OK;return ERROR;elsereturn OK;/后序Status LastOrderTraverse(BiTree T, Status (*Visit)(TElemType e)if(T) if(LastOrderTraverse(

24、T-lchild, Visit)if(LastOrderTraverse(T-rchild, Visit)if(Visit(T-data)return OK;return ERROR; elsereturn OK;/求树的叶子的个数,和打印出叶子Status LeafNumTree(BiTree T)int lnum,rnum;if(T!=NULL) if(T-lchild=NULL & T-rchild=NULL)return 1;else lnum=LeafNumTree(T-lchild);rnum=LeafNumTree(T-rchild);return lnum+rnum; retu

25、rn 0;/求二叉树的高度Status BiTreeDepth(BiTree T)int l,r;if(T) l=BiTreeDepth(T-lchild); r=BiTreeDepth(T-rchild);if(l=r)dep += l;else dep += r; elsereturn 1;/先序、中序、后序遍历二叉树:非递归算法void print3() printf(n非递归算法遍历二叉树,菜单如下:n); printf(1.中根遍历n); printf(0.退出n); printf(请输入二级菜单选择:);typedef struct QueueNode BiTree e;struc

26、t QueueNode *next;QueueNode,*QueuePtr; /定义队列结点结构typedef struct QueuePtr front; QueuePtr rear;LinkQueue; /栈的顺序存储表示typedef struct BiTNode *base; /栈底指针 BiTNode *top; /栈顶指针 int stacksize; /当前已分配的存储空间SqStack;/初始化一个带头结点的队列void InitQueue(LinkQueue &q)q.front=q.rear=(QueuePtr)malloc(sizeof(QueueNode);q.fron

27、t-next=NULL;/入队列void enqueue(LinkQueue &q,BiTree p) QueuePtr s;int first=1; s=(QueuePtr)malloc(sizeof(QueueNode);s-e =p;s-next=NULL; q.rear-next=s; q.rear=s;/出队列void dequeue(LinkQueue &q,BiTree &p)char data; QueuePtr s;s=q.front-next; p=s-e ;data=p-data;q.front-next=s-next;if(q.rear=s)q.rear=q.front

28、;free(s);printf(%ct,data);/判断队列是否为空Status queueempty(LinkQueue q)if(q.front-next=NULL)return 1;return 0;/按层次遍历树中结点void Traverse(BiTree T)LinkQueue q;BiTree p;InitQueue(q); p=T;enqueue(q,p);while(queueempty(q)!=1) dequeue(q,p);if(p-lchild!=NULL)enqueue(q,p-lchild);if(p-rchild!=NULL)enqueue(q,p-rchild

29、); printf(n); /建立一个空栈void InitStack(SqStack &S) S.base=(BiTree)malloc(LIST_INT_SIZE * sizeof(BiTNode);if(!S.base)exit(OVERFLOW );/存储分配失败 S.top=S.base; S.stacksize=LIST_INT_SIZE; /压入栈void Push(SqStack & S,BiTree p) if(S.top-S.base=S.stacksize)/满栈,追加存储结构S.base=(BiTree)realloc(S.base,(S.stacksize+LISTI

30、NCREMENT)*sizeof(BiTNode);if(!S.base) exit(OVERFLOW );/存储分配失败 S.top=S.base+S.stacksize; S.stacksize+=LISTINCREMENT; *(+S.top)=*p; /退出栈bool Pop(SqStack &S,BiTree &p)if( S.top=S.base) printf(空栈n);return false; p=(BiTree)malloc( sizeof(BiTNode); *p=*S.top; -S.top;return true; /判断是否是空栈bool StackEmpty(Sq

31、Stack &S) if( S.top=S.base) return true;elsereturn false ; Status InOrderTraverAndCountLeaf(BiTree &T,Status(* Vist)(TElemType e)int j=0,count=0;BiTree p;p=(BiTNode *)malloc( sizeof(BiTNode);/关键一步p=T; SqStack s;InitStack(s);while(p|!StackEmpty(s)if(p) Push(s,p);/如果p为非空,将p压入栈if(!(p-lchild)&!(p-rchild

32、) +count;/记录叶子节点数 p=p-lchild; /ifelse Pop(s,p);/如果p为空,则p退栈Vist(p-data); p=p-rchild; /else /whilereturn count;int main()int n, ncase;int count;bool f, f1, f2, f3; BiTree T; TElemType e;print();while(scanf(%d, &n)!=EOF) f = true;switch(n)case 1: printf(输入空格或回车表示此结点为空结束n请输入头结点:);if(CreateBiTree(T) prin

33、tf(二叉树建立成功!n);else printf(二叉树建立失败!n);break;case 2:print2();while(scanf(%d, &ncase)!= EOF) f1 = true;switch(ncase) case 1: printf(先序遍历顺序为:);if(PreOrderTraverse(T, PrintElement)printf(先序遍历成功!n);else printf(先序遍历失败!n);break;case 2:printf(中序遍历顺序为:);if(MidOrderTraverse(T, PrintElement) printf(中序遍历成功!n);el

34、seprintf(中序遍历失败!n);break;case 3: printf(后序遍历顺序为:);if(LastOrderTraverse(T, PrintElement) printf(后序遍历成功!n);elseprintf(后序遍历失败!n);break;case 0: f1 = false;break;default :printf(输入错误,请重新输入!n);if(!f1)break;print2(); break;case 3:print3();while(scanf(%d, &ncase)!= EOF) f2 = true;switch(ncase) case 1:InOrde

35、rTraverAndCountLeaf(T,PrintElement);break;case 0: f2 = false;break;default :printf(输入错误,请重新输入!n); if(!f2)break;print3();break;case 4:dep = 0;BiTreeDepth(T); printf(二叉树的高度为:%dn, dep-1);break;case 5:count = LeafNumTree(T);printf(二叉树的叶子个数为:%dn, count);break;case 6: printf(按层次遍历的顺序为:n);Traverse(T);print

36、f(n);break;case 0: f = false;break;default: printf(输入错误,请重新输入!n);break; if(!f)printf(退出程序.n);break;print(); return 0;6 测试图1如图1所示为一元多项式的相加的测试图,多项式ha:2x2+34x3+56x4与多项式hb:12x1+23x2+334+2x5相加,结果为12x1+25x2+34x2+343+89x4+2x5。图2图3图4如图所示,图2、3、4则为图的综合的试验测试。图5图6如上所示,图5、6为树的综合的试验测试截图。7 总结以上是综合设计基础部分的所有内容,做基础部分

37、只是为了给后面的综合设计打下基础,巩固和扎实基础部分的知识,重点还是综合设计的部分。在基础部分,做了三个基本的实验程序,包括一元多项式的相加、图的基本操作和树的基本操作。应用到了指针、链表等基础知识,进一步对基础知识进行了了解和掌握。其中在树的基本操作之中。因为我选的综合应用设计题也是赫夫曼编码,所以在基础部分就没有实现赫夫曼编码的操作,只是简单把树的基本操作实现了。在一元多项式的相加中,实现了两个多项式的相加,项数相同的系数合并,然后打印出相加的结果;在图的综合之中,以邻接矩阵的方式建立图,并实现了图的广度优先和深度优先的遍历,在树的综合之中建立二叉链表,递归实现先序、中序、后序遍历二叉树等

38、的功能。虽然基础的实验也许做的不够完美,但是经过这几个基础的实验,最后的收获也不少,不仅温习了旧的知识,也学到了新的知识,给综合课程设计打下了坚实的基础。二、综合部分课程设计1 问题描述在当今的信息爆炸时代,如何采用有效的数据压缩技术来节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视。赫夫曼编码正是一种应用广泛非常有效的数据压缩技术。赫夫曼编码的应用很广泛,利用赫夫曼树求得的用于通信的二进制编码称为赫夫曼编码。哈夫曼编码的应用很广泛,利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0”码,指向右

39、子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为和各个对应的字符的编码,这就是哈夫曼编码。通常我们把数据压缩的过程称为编码,解压缩的过程称为解码。电报通信是传递文字的二进制码形式的字符串。但在信息传递时,总希望总长度尽可能最短,即采用最短码。我们需要解决的就是对电文的编码和译码问题。2 功能需求分析建立赫夫曼树:根据输入的字符串建立赫夫曼树。从键盘输入字符串,根据输入的字符串中每个字符出现的频率计算比重,实现赫夫曼树的建立。赫夫曼编码:根据所建立的赫夫曼树进行赫夫曼编码。指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,对每个字符进行编码,并在屏幕上打印出每个字母所对应

40、的编码结果。赫夫曼译码:根据给出的每个数值的编码进行相应的译码。从键盘输入密文(只能由“1”和“0”组成),根据输入的密文,对应的去扫描编码表,找出与之对应的字母,进行译码,并将译码的结果在屏幕上面打印出来。3 总体设计1. 总体结构赫夫曼编码译码系统译码编码建立赫夫曼树将译码结果打印出来从键盘上输入密文进行译码根据建立的赫夫曼树进行编码将编码结果打印出来从键盘上输入字符串根据输入的字符串算出每个字母出现的频率算出比重2. 设计流程程序总体执行的流程图如下:开始输入需要编码的字符串对输入的字符串根据出现的频率算出其比重根据每个字符所占的比重建立huffmantree编码输入密文进行译码输入的字

41、符是否只含0和1?否是打印译码明文是否继续译码?是否结束程序4 详细设计1. 赫夫曼编码的结构体typedef struct haha int weight;/*权值*/ int parent,lchild,rchild,flag;/*父结点、左孩子结点、右孩子结点,flag表示状态,用来记录是否被选中,初始为0*/ char data;/*存放字符*/ haha,*HuffmanTree;/*树中结点类型*/ typedef struct hehechar m;int n;struct hehe *next;hehe,*zhouwu;typedef char * *HuffmanCode;/

42、*动态分配数组存储赫夫曼编码表*/2. 函数功能的描述以及结构Begin():函数原型为void begin(zhouwu &l);函数实现的功能是对输入的字符串中的字母进行比重统计,算出其的比重权值。开始Begin()函数结构:为L动态分配内存输入字符串计算比重结束返回LSelect():函数原型为void select(HuffmanTree &ht,int k,int &x,int &y);/*选择权值最小的两个根节点的算法 */函数实现的功能是在所有的值中选择两个权值最小的数的结点。Huffmancoding():函数原型为void huffmancoding(HuffmanTree &ht,zhouwu &l);/*编码*/ 函数实现的功能是对字符进行编码。Huffmancoding()函数结构:结束循环结构打印出编码,释放指针是是否in是否成立?生成编码1生成编码0否否是选择的两个节点的权值是否为最小?是否为左孩子?赫夫曼树建立完毕,开始编码是Select()函数全部设置为0初始化数组的每个分量为h

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论