哈呼曼编译器设计说明书Word格式.docx
《哈呼曼编译器设计说明书Word格式.docx》由会员分享,可在线阅读,更多相关《哈呼曼编译器设计说明书Word格式.docx(18页珍藏版)》请在冰豆网上搜索。
对于这样的问题,可以利用计算机运算速度快的特点,先搜索查找所有可能出现的情况,再根据题目条件从所有可能的情况中,删除那些不符合条件的解。
由哈夫曼算法的定义可知,初始森林中共有n棵只含有根结点的二叉树。
算法的的第二步是:
将当前森林中的两棵根结点权值最小的二叉树,合并成一棵新的二叉树,每合并一次,森林中就减少一棵树,产生一个新结点。
则要进行n-1次合并,所以共产生n-1个新结点。
由此可知,最终求得的哈夫曼树中一共有2n-1个结点。
其中,n个结点是初始森林中的n个孤立结点。
并且哈夫曼树中没有度数为1的分支的结点。
采用哈夫曼编码方案,即应用哈夫曼树构造使电文的编码总长最短的编码方案。
正文
1.采用类C语言定义相关的数据类型
(1)哈夫曼树的存储结构定义为:
typedefstruct/*字符集的元素结构*/
{chardata;
intweight;
//权值
}elemtype;
typedefstruct/*哈夫曼树的元素结构*/
intflag;
intparent,lchild,rchild;
//左右孩子及双亲指针
}htnode,*huffmantree;
//动态分配数组存储哈夫曼树
typedefchar**HuffmanCode;
//动态分配数组存储哈夫曼编码表
(2)哈夫曼树的存储结构描述:
#include<
stdio.h>
stdlib.h>
string.h>
#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;
=2*num;
i++)/*输入num个结点的权值*/
HT[i].weight=cnt[i];
for(i=num+1;
=2*num-1;
{/*在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;
=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'
;
//编码结束符标志
=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
puts(HC[i]);
free(cd);
//释放工作空间
return(HC);
(3)求测试数据的编码(encoding)算法:
voidencoding(huffmantreeht,char**hc)//根据哈夫曼树HT求哈夫曼编码表HC
{inti,j,k;
charsstring[MAXNODE];
clrscr();
flushall();
inputhuffmancode\neg.:
thisisprogrammaismyfavorite:
\n"
);
gets(sstring);
for(i=0;
strlen(sstring);
{for(j=1;
j<
j++)
if(sstring[i]==ht[j].data)
{k=j;
break;
(4)哈夫曼译码算法:
voiddecoding(huffmantreeht)//代码文件的译码
{chara[MAXD];
intm,i;
scanf("
%s"
a);
m=2*n-1;
a[i]!
='
{if(a[i]=='
)m=ht[m].lchild;
elsem=ht[m].rchild;
if(m<
=n)
{printf("
%c"
ht[m].data);
3.函数调用关系图:
4.调试分析:
a.调试中遇到的问题及对问题的解决方法:
在对源程序进行调试时,当输入字符后,应正确判断所输入的字符是否满足程序的需求,且保正所输入字符后所输出语句功能唯一。
则在源程序中加入了一条while()判断语句,若while()判断语句中表达式成立,就重新获取一个字符,然后对while()语句进行重新判断,直到while()判断语句中表达式不成立,就执行switch()语句中于其输入字符相对应的case’’语句.其程序语句如下:
while(ch!
r'
&
ch!
c'
e'
d'
q'
)
ch=getchar();
/*选取功能*/
switch(ch)
{case'
:
readdata(w);
break;
/*初始化(readdata),读取数据*/
case'
ht=createhuff(w);
/*建立哈夫曼树(createhuff)*/
hc=huffmancode(ht);
encoding(ht,hc);
/*求字符集的哈夫曼编码(huffmancode)和求测试数据的编码(encoding)*/
decoding(ht);
/*译码(decoding)*/
return;
/*程序结束,返回*/
b.算法的时间复杂度和空间复杂度
时间复杂度:
建立哈夫曼树:
O(n³
对文件中正文进行编码:
O(n2)
对文件中的代码进行译码:
O(n)
5测试结果
对下列给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:
“THISPROGRAMISMYFAVORITE“。
字符空格ABCDEFGHIJKLM
频度1866413223210321154757153220
字符NOPQRSTUVWXYZ
频度5763151485180238181161
输入r后:
输入c后:
输入e后:
6.源程序(带注释)
#defineMAXNODE35//哈夫曼树最多节点数
typedefstruct/*字符集的元素结构*/
//左右孩子及双亲节点
//动态分配数组存储哈夫曼编码表
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='
w[3].weight=22;
w[4].data='
w[4].weight=32;
w[5].data='
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='
w[17].weight=1;
w[18].data='
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;
27;
{printf("
%c"
w[i].data);
printf("
%d\t"
w[i].weight);
return;
huffmantreecreatehuff(elemtype*w)
{inti,j,x1,x2;
intm1,m2,m;
huffmantreeHT,p;
HT=(huffmantree)malloc((m+1)*sizeof(htnode));
//0号单元未用
p=HT;
p++;
=m;
i++,p++,w++)//初始化HT
{if(i<
p->
data=w->
data;
weight=w->
weight;
else
data='
weight=0;
parent=0;
lchild=0;
rchild=0;
flag=0;
n;
i++)//该循坏开始构造哈夫曼树
{m1=m2=MAXVALUE;
x1=x2=0;
for(j=1;
=n-1+i;
if(p[j].weight<
m1&
p[j].flag==0)
{m2=m1;
x2=x1;
m1=p[j].weight;
x1=j;
elseif(p[j].weight<
m2&
{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;
%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();
return(HT);
//从叶子到根逆向求哈夫曼编码
HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
//分配n个字符的头指针向量
//分配求编码的工作区间
//编码结束符
i++)//逐个字符求哈夫曼编码
//编码结束符位置
c=f,f=ht[f].parent)//从叶子到根逆向求编码
//为第i个字符编码分配空间
//从cd复制编码串到HC
free(cd);
//释放工作区间
voidencoding(huffmantreeht,char**hc)
if(k<
=0||k>
MAXNODE)
thereisn'
tNO.%dchar\n"
i);
continue;
%c\tweight=%3d\t%s\n"
ht[k].data,ht[k].weight,hc[k]);
voiddecoding(huffmantreeht)
main()
{elemtypew[n];
/*字符和频度集合类型*/
charch;
huffmantreeht;
/*哈夫曼树类型*/
HuffmanCodehc;
/*编码类型*/
)/*当键入’q’时程序运行结束*/
总结
在这三周的数据结构课程设计中,我的题目是:
哈夫曼编译码器设计,这三周课程设计中,通过该题目的设计过程,我加深了对树的数据结构以及二叉树的逻辑结构,存储结构的理解,对树的数据结构上基本运算的实现有所掌握,对课本中所学的各种数据结构进一步理解和掌握,学会了如何把学到的知识用于解决实际问题,锻炼了自己动手的能力。
一个人要完成所有的工作是非常困难和耗时的。
在以后的学习中我会更加注意自己各个方面的能力的协调发展。
在课程设计时我遇到了很多的问题,在老师的帮助,和对各种资料的查阅中,将问题解决,培养了我自主动手,独立研究的能力,为今后在学习工作中能更好的发展打下了坚实的基础。
三周的课程设计很短暂,但其间的内容是很充实的,在其中我学习到了很多平时书本中无法学到的东西,积累了经验,锻炼了自己分析问题,解决问题的能力,并学会了如何将所学的各课知识融会,组织,来配合学习,三周中我收益很大,学到很多。
参考文献
1.严蔚敏,陈文博编著.数据结构及应用算法教程,北京:
清华大学出版社,2001
2.苏仕华主编.数据结构自学辅导.北京:
清华大学出版社,2002
3.苏仕华主编.数据结构与算法解析.合肥:
中国科学技术大学生出版社,2004
4.谭浩强编著.C程序设计.北京:
清华大学出版社,1991
附件Ⅰ部分源程序代码
栈的应用——用栈来实行编译(左右括号配对)
算法:
voidpush(stacknode*st,elemtypex)/*将元素x入栈*/
if(st->
top==m)/*判断栈ST是否已满*/
thestackisoverflow!
st->
top=st->
top+1;
stack[st->
top]=x;
voidpop(stacknode*st)/*将栈的栈顶元素出栈*/
{
top-1;
源程序:
#definem20
#defineelemtypechar
typedefstruct/*栈类型的定义*/
elemtyp