哈呼曼编译器设计说明书.docx

上传人:b****6 文档编号:8244739 上传时间:2023-01-30 格式:DOCX 页数:18 大小:159.84KB
下载 相关 举报
哈呼曼编译器设计说明书.docx_第1页
第1页 / 共18页
哈呼曼编译器设计说明书.docx_第2页
第2页 / 共18页
哈呼曼编译器设计说明书.docx_第3页
第3页 / 共18页
哈呼曼编译器设计说明书.docx_第4页
第4页 / 共18页
哈呼曼编译器设计说明书.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

哈呼曼编译器设计说明书.docx

《哈呼曼编译器设计说明书.docx》由会员分享,可在线阅读,更多相关《哈呼曼编译器设计说明书.docx(18页珍藏版)》请在冰豆网上搜索。

哈呼曼编译器设计说明书.docx

哈呼曼编译器设计说明书

*******************

实践教学

*******************

 

兰州理工大学

计算机与通信学院

2007年春季学期

 

算法与数据结构课程设计

 

题目:

哈夫曼编译码器设计

专业班级:

05计算机科学与技术3班

姓名:

徐玉霞

学号:

05240317

指导教师:

李睿

成绩:

_____________________

目录

摘要2

前言3

正文4

1.采用类c语言定义相关的数据类型4

2.各模块的伪码算法4

3.函数的调用关系图7

4.调试分析7

5.测试结果8

6.源程序(带注释)10

参考文献18

致谢19

附件Ⅰ部分源程序代码20

摘要

该设计是对输入的一串电文字符实现哈夫曼编码,再对哈夫曼编码生成的代码串进行译码,输出电文字符串。

在该设计中把数据压缩过程称为编码,解压缩的过程称为译码。

此程序中建立了哈夫曼树,并利用建好的哈夫曼树对文件中的正文进行编码,对文件中的代码进行译码,显示输出等功能。

关键词:

哈夫曼树,哈夫曼编码,哈夫曼译码。

前言

哈夫曼编码的应用很广泛,利用哈夫曼树求地的二进制编码称为哈夫曼编码。

哈夫曼树中从根到每个叶子都有一条路径,对路径上的各分支约定:

指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为对应的编码,这就是哈夫曼编码。

我们在对一些问题进行求解时,会发现有些问题很难找到规律,或者根本无规律可寻。

对于这样的问题,可以利用计算机运算速度快的特点,先搜索查找所有可能出现的情况,再根据题目条件从所有可能的情况中,删除那些不符合条件的解。

由哈夫曼算法的定义可知,初始森林中共有n棵只含有根结点的二叉树。

算法的的第二步是:

算法的的第二步是:

将当前森林中的两棵根结点权值最小的二叉树,合并成一棵新的二叉树,每合并一次,森林中就减少一棵树,产生一个新结点。

则要进行n-1次合并,所以共产生n-1个新结点。

由此可知,最终求得的哈夫曼树中一共有2n-1个结点。

其中,n个结点是初始森林中的n个孤立结点。

并且哈夫曼树中没有度数为1的分支的结点。

采用哈夫曼编码方案,即应用哈夫曼树构造使电文的编码总长最短的编码方案。

正文

1.采用类C语言定义相关的数据类型

(1)哈夫曼树的存储结构定义为:

typedefstruct/*字符集的元素结构*/

{chardata;

intweight;//权值

}elemtype;

typedefstruct/*哈夫曼树的元素结构*/

{chardata;

intflag;

intweight;//权值

intparent,lchild,rchild;//左右孩子及双亲指针

}htnode,*huffmantree;//动态分配数组存储哈夫曼树

typedefchar**HuffmanCode;//动态分配数组存储哈夫曼编码表

(2)哈夫曼树的存储结构描述:

#include

#include

#include

#definen27/*字符集的容量*/

#defineMAXVALUE1000/*权值的最大值*/

#defineMAXNODE35//哈夫曼树最多节点数

#defineMAXD100

2.各模块的伪码算法:

(1)构造哈夫曼树的算法

voidChuffmanTree(HuffmanTreeHT,HuffmancodeHc,intcnt[],charstr[])

{/*构造哈夫曼树HT,cnt中存放每类字符在电文中出项的频率,str中存放电文中不同类的字符*/

inti,s1,s2;

for(i=1;i<=2;*num-1;i++)

{

HT[i].lchild=0;HT[i].rchild=0;

HT[i].parent=0;HTweight=0;

}

for(i=1;i<=2*num;i++)/*输入num个结点的权值*/

HT[i].weight=cnt[i];

for(i=num+1;i<=2*num-1;i++)

{/*在HT[1..i-1]中选择parent为0且权值最小的两个结点*/

selext(Ht,i-1,s1,s2);

HT[s1].parent=i;HT[s2].parent=i;

Ht[i].lchild=s;HT[i].rchild=s2;

HT[i].weight=HT[s1].weight+HT[s2].weight;

}

for(i=0;i<=num;i++)/*输入字符集中字符*/

HC[i].ch=str[i];

i=1;while(i<=num)

printf("字符&c,次数为:

%d\n",HC[i].ch,cnt[i++]);

}

(2)求哈夫曼编码(huffmancode)算法:

HuffmanCodehuffmancode(huffmantreeht)

{char*cd;

intc,i,f,start;

HuffmanCodeHC;

HC=(HuffmanCode)malloc((n+1)*sizeof(char*));//分配n个字符编码的头指针向量

cd=(char*)malloc(n*sizeof(char));//分配求编码的工作区间

cd[n-1]='\0';//编码结束符标志

for(i=1;i<=n;i++)//逐个字符求哈夫曼编码

{start=n-1;//编码结束位置

for(c=i,f=ht[i].parent;f!

=0;c=f,f=ht[f].parent)//从叶子到根逆向求编码

if(ht[f].lchild==c)cd[--start]='0';

elsecd[--start]='1';

HC[i]=(char*)malloc((n-start)*sizeof(char));//为第i个字符编码分配空间

strcpy(HC[i],&cd[start]);//从cd复制编码(串)到HC

}

for(i=1;i<=n;i++)

puts(HC[i]);

free(cd);//释放工作空间

return(HC);

}

(3)求测试数据的编码(encoding)算法:

voidencoding(huffmantreeht,char**hc)//根据哈夫曼树HT求哈夫曼编码表HC

{inti,j,k;

charsstring[MAXNODE];

clrscr();

flushall();

printf("inputhuffmancode\neg.:

thisisprogrammaismyfavorite:

\n");

gets(sstring);

for(i=0;i

{for(j=1;j<=n;j++)

if(sstring[i]==ht[j].data)

{k=j;

break;

}

(4)哈夫曼译码算法:

voiddecoding(huffmantreeht)//代码文件的译码

{chara[MAXD];

intm,i;

clrscr();

scanf("%s",a);

m=2*n-1;

for(i=0;a[i]!

='\0';i++)

{if(a[i]=='0')m=ht[m].lchild;

elsem=ht[m].rchild;

if(m<=n)

{printf("%c",ht[m].data);

m=2*n-1;

}

}

}

3.函数调用关系图:

4.调试分析:

a.调试中遇到的问题及对问题的解决方法:

在对源程序进行调试时,当输入字符后,应正确判断所输入的字符是否满足程序的需求,且保正所输入字符后所输出语句功能唯一。

则在源程序中加入了一条while()判断语句,若while()判断语句中表达式成立,就重新获取一个字符,然后对while()语句进行重新判断,直到while()判断语句中表达式不成立,就执行switch()语句中于其输入字符相对应的case’’语句.其程序语句如下:

while(ch!

='r'&&ch!

='c'&&ch!

='e'&&ch!

='d'&&ch!

='q')

ch=getchar();/*选取功能*/

switch(ch)

{case'r':

readdata(w);break;/*初始化(readdata),读取数据*/

case'c':

ht=createhuff(w);break;/*建立哈夫曼树(createhuff)*/

case'e':

hc=huffmancode(ht);encoding(ht,hc);break;

/*求字符集的哈夫曼编码(huffmancode)和求测试数据的编码(encoding)*/

case'd':

decoding(ht);break;/*译码(decoding)*/

case'q':

return;/*程序结束,返回*/

}

b.算法的时间复杂度和空间复杂度

时间复杂度:

建立哈夫曼树:

O(n³)

对文件中正文进行编码:

O(n2)

对文件中的代码进行译码:

O(n)

5测试结果

对下列给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:

“THISPROGRAMISMYFAVORITE“。

字符空格ABCDEFGHIJKLM

频度1866413223210321154757153220

字符NOPQRSTUVWXYZ

频度5763151485180238181161

输入r后:

输入c后:

输入e后:

6.源程序(带注释)

#include

#include

#include

#definen27/*字符集的容量*/

#defineMAXVALUE1000/*权值的最大值*/

#defineMAXNODE35//哈夫曼树最多节点数

#defineMAXD100

typedefstruct/*字符集的元素结构*/

{chardata;

intweight;

}elemtype;

typedefstruct/*哈夫曼树的元素结构*/

{chardata;

intflag;

intweight;//权值

intparent,lchild,rchild;//左右孩子及双亲节点

}htnode,*huffmantree;//动态分配数组存储哈夫曼树

typedefchar**HuffmanCode;//动态分配数组存储哈夫曼编码表

 

voidreaddata(elemtype*w);

huffmantreecreatehuff(elemtype*w);

char**huffmancode(huffmantreeht);

voidencoding(huffmantreeht,char**hc);

voiddecoding(huffmantreeht);

//初始化readdata,读取数据

voidreaddata(elemtype*w)

{inti;

w[0].data='';w[0].weight=186;

w[1].data='a';w[1].weight=64;

w[2].data='b';w[2].weight=13;

w[3].data='c';w[3].weight=22;

w[4].data='d';w[4].weight=32;

w[5].data='e';w[5].weight=103;

w[6].data='f';w[6].weight=21;

w[7].data='g';w[7].weight=15;

w[8].data='h';w[8].weight=47;

w[9].data='i';w[9].weight=57;

w[10].data='j';w[10].weight=1;

w[11].data='k';w[11].weight=5;

w[12].data='l';w[12].weight=32;

w[13].data='m';w[13].weight=20;

w[14].data='n';w[14].weight=57;

w[15].data='o';w[15].weight=63;

w[16].data='p';w[16].weight=15;

w[17].data='q';w[17].weight=1;

w[18].data='r';w[18].weight=48;

w[19].data='s';w[19].weight=51;

w[20].data='t';w[20].weight=80;

w[21].data='u';w[21].weight=23;

w[22].data='v';w[22].weight=8;

w[23].data='w';w[23].weight=18;

w[24].data='x';w[24].weight=1;

w[25].data='y';w[25].weight=16;

w[26].data='z';w[26].weight=1;

for(i=0;i<27;i++)

{printf("%c",w[i].data);

printf("%d\t",w[i].weight);

}

return;

}

huffmantreecreatehuff(elemtype*w)

{inti,j,x1,x2;

intm1,m2,m;

huffmantreeHT,p;

m=2*n-1;

HT=(huffmantree)malloc((m+1)*sizeof(htnode));//0号单元未用

p=HT;p++;

for(i=1;i<=m;i++,p++,w++)//初始化HT

{if(i<=n)

{

p->data=w->data;

p->weight=w->weight;

}

else

{

p->data='\0';

p->weight=0;

}

p->parent=0;

p->lchild=0;

p->rchild=0;

p->flag=0;

}

for(i=1;i

{m1=m2=MAXVALUE;

x1=x2=0;

p=HT;

for(j=1;j<=n-1+i;j++)

{

if(p[j].weight

{m2=m1;

x2=x1;

m1=p[j].weight;

x1=j;

}

elseif(p[j].weight

{m2=p[j].weight;

x2=j;

}

}

p[x1].parent=n+i;

p[x2].parent=n+i;

p[x1].flag=1;

p[x2].flag=1;

p[n+i].weight=p[x1].weight+p[x2].weight;

p[n+i].lchild=x1;

p[n+i].rchild=x2;

}

clrscr();

for(i=1;i<=m;i++)

{printf("%d,%c,%d,%3d,%3d,%3d,%3d\n",i,p[i].data,p[i].flag,p[i].weight,p[i].parent,p[i].lchild,p[i].rchild);

if(i%15==0){

getch();

clrscr();}

}

return(HT);

}

HuffmanCodehuffmancode(huffmantreeht)

{char*cd;

intc,i,f,start;

HuffmanCodeHC;

//从叶子到根逆向求哈夫曼编码

HC=(HuffmanCode)malloc((n+1)*sizeof(char*));//分配n个字符的头指针向量

cd=(char*)malloc(n*sizeof(char));//分配求编码的工作区间

cd[n-1]='\0';//编码结束符

for(i=1;i<=n;i++)//逐个字符求哈夫曼编码

{start=n-1;//编码结束符位置

for(c=i,f=ht[i].parent;f!

=0;c=f,f=ht[f].parent)//从叶子到根逆向求编码

if(ht[f].lchild==c)cd[--start]='0';

elsecd[--start]='1';

HC[i]=(char*)malloc((n-start)*sizeof(char));//为第i个字符编码分配空间

strcpy(HC[i],&cd[start]);//从cd复制编码串到HC

}

for(i=1;i<=n;i++)

puts(HC[i]);

free(cd);//释放工作区间

return(HC);

}

voidencoding(huffmantreeht,char**hc)

{inti,j,k;

charsstring[MAXNODE];

clrscr();

flushall();

printf("inputhuffmancode\neg.:

thisisprogrammaismyfavorite:

\n");

gets(sstring);

for(i=0;i

{for(j=1;j<=n;j++)

if(sstring[i]==ht[j].data)

{k=j;

break;

}

if(k<=0||k>MAXNODE)

{printf("thereisn'tNO.%dchar\n",i);

continue;

}

printf("%c\tweight=%3d\t%s\n",ht[k].data,ht[k].weight,hc[k]);

}

}

 

voiddecoding(huffmantreeht)

{chara[MAXD];

intm,i;

clrscr();

scanf("%s",a);

m=2*n-1;

for(i=0;a[i]!

='\0';i++)

{if(a[i]=='0')m=ht[m].lchild;

elsem=ht[m].rchild;

if(m<=n)

{printf("%c",ht[m].data);

m=2*n-1;

}

}

}

main()

{elemtypew[n];/*字符和频度集合类型*/

charch;

huffmantreeht;/*哈夫曼树类型*/

HuffmanCodehc;/*编码类型*/

ch=getchar();

while(ch!

='q')/*当键入’q’时程序运行结束*/

{

while(ch!

='r'&&ch!

='c'&&ch!

='e'&&ch!

='d'&&ch!

='q')

ch=getchar();/*选取功能*/

switch(ch)

{case'r':

readdata(w);break;/*初始化(readdata),读取数据*/

case'c':

ht=createhuff(w);break;/*建立哈夫曼树(createhuff)*/

case'e':

hc=huffmancode(ht);encoding(ht,hc);break;

/*求字符集的哈夫曼编码(huffmancode)和求测试数据的编码(encoding)*/

case'd':

decoding(ht);break;/*译码(decoding)*/

case'q':

return;/*程序结束,返回*/

}

ch=getchar();

}

}

总结

在这三周的数据结构课程设计中,我的题目是:

哈夫曼编译码器设计,这三周课程设计中,通过该题目的设计过程,我加深了对树的数据结构以及二叉树的逻辑结构,存储结构的理解,对树的数据结构上基本运算的实现有所掌握,对课本中所学的各种数据结构进一步理解和掌握,学会了如何把学到的知识用于解决实际问题,锻炼了自己动手的能力。

一个人要完成所有的工作是非常困难和耗时的。

在以后的学习中我会更加注意自己各个方面的能力的协调发展。

在课程设计时我遇到了很多的问题,在老师的帮助,和对各种资料的查阅中,将问题解决,培养了我自主动手,独立研究的能力,为今后在学习工作中能更好的发展打下了坚实的基础。

三周的课程设计很短暂,但其间的内容是很充实的,在其中我学习到了很多平时书本中无法学到的东西,积累了经验,锻炼了自己分析问题,解决问题的能力,并学会了如何将所学的各课知识融会,组织,来配合学习,三周中我收益很大,学到很多。

参考文献

1.严蔚敏,陈文博编著.数据结构及应用算法教程,北京:

清华大学出版社,2001

2.苏仕华主编.数据结构自学辅导.北京:

清华大学出版社,2002

3.苏仕华主编.数据结构与算法解析.合肥:

中国科学技术大学生出版社,2004

4.谭浩强编著.C程序设计.北京:

清华大学出版社,1991

附件Ⅰ部分源程序代码

栈的应用——用栈来实行编译(左右括号配对)

算法:

voidpush(stacknode*st,elemtypex)/*将元素x入栈*/

{

if(st->top==m)/*判断栈ST是否已满*/

printf("thestackisoverflow!

\n");

else

{

st->top=st->top+1;

st->stack[st->top]=x;

}

}

voidpop(stacknode*st)/*将栈的栈顶元素出栈*/

{

st->top=st->top-1;

}

源程序:

#definem20

#defineelemtypechar

typedefstruct/*栈类型的定义*/

{

elemtyp

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1