赫夫曼树数据结构课设报告.docx
《赫夫曼树数据结构课设报告.docx》由会员分享,可在线阅读,更多相关《赫夫曼树数据结构课设报告.docx(22页珍藏版)》请在冰豆网上搜索。
赫夫曼树数据结构课设报告
课程设计(论文)任务书
软件 学院 软件工程 专业 2011-3 班
一、课程设计(论文)题目 数据结构课程设计
二、课程设计(论文)工作自2012年12月17日起至2012年12月18日止。
三、课程设计(论文)地点:
软件工程实训中心
四、课程设计(论文)内容要求:
1.本课程设计的目的
(1)使学生熟练掌握抽象数据类型的组织和定义;
(2)使学生熟练掌握数据类型的定义和实现;
(3)培养学生组织和分析数据的能力;
(4)培养学生分析和应用基于不同数据结构的算法的能力;
(5)提高学生的科技论文写作能力。
2.基本要求:
每位同学在以下题目中任选一题(在方框中打勾),独立完成课程设计:
□约瑟夫环:
参见《数据结构题集》P179。
□赫夫曼编/译码器:
参见《数据结构题集》P149。
□井字棋:
参见《数据结构》教材P2。
设计棋谱,当对方落子后,能从棋谱中选择一种
应对方式,并能判断胜负。
3.课程设计论文编写要求
(1)要按照书稿的规格打印誊写课设报告;
(2)报告分为封面、任务书(本文档)、正文、课程设计体会和参考文献四部分;
学生签名:
年月日
课程设计(论文)评审意见
(1)题目分析(20分):
优( )、良( )、中( )、一般( )、差( );
(2)流程分析 (30分):
优( )、良( )、中( )、一般( )、差( );
(3)数据定义 (30分):
优( )、良( )、中( )、一般( )、差( );
(4)代码编写 (10分):
优( )、良( )、中( )、一般( )、差( );
(5)创新能力 (10分):
优( )、良( )、中( )、一般( )、差( );
(6)格式规范性、设计态度及考勤是否降等级:
是( )、否( )
评阅人:
职称:
讲师
年月日
正文
一、数据结构定义
1.抽象数据类型
本设计中用到的数据结构ADT定义如下:
ADTHuffmanTree{
数据对象T:
具有相同特性的数据元素的集合
数据关系R:
满足最有二叉树的关系
基本操作P:
Init(&t)
操作结果:
钩子一个空赫夫曼树t。
Encode()
操作结果:
利用赫夫曼树进行编码
Decode()
操作结果:
利用赫夫曼树进行译码
}
2.存储结构定义
数据存储结构的C语言定义如下:
typedefstructBinTree{
intdata;
structBinTree*lchild,*rchild;
}BinTree,*BinTree;
3.基本操作
数据结构的基本操作实现如下:
CreateHuffmanTree(&HT);
初始条件:
给出HuffmanTree的定义。
操作结果:
构造HuffmanTree。
HuffumanCoding(HuffmanTreeHT,HuffmanCode&HC)
初始条件:
HT存在。
操作结果:
得出编码HC。
PrintHuffmanCode(HuffmanTreeHT,HuffmanCodeHC)
初始条件:
HT,HC存在。
操作结果:
显示字符与其对应的编码。
二、解题过程
1.问题分解
该问题主要应实现以下功能:
(1)I:
初始化(Initialization)。
从终端读入字符集大小n,以及n个字符和n个权值,建立赫夫曼树,并将它存于文件hfmTree中。
(2)E:
编码(Encoding)。
利用已建好的赫夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
(3)D:
译码(Decoding)。
利用已建好的赫夫曼树将文件CodeFile中的代码进行译码,结果存入文件Textfile中。
2.模块结构
系统主要由3个模块组成,分别是:
(1)主函数
(2)编码功能
(3)译码功能
模块之间的结构如下:
(1)intmain()
主函数:
利用已建好的哈夫曼树(如不在内存,则从文件hfmtree.txt中读入)
对文件中的正文进行编码,然后将结果存入文件codefile.txt中。
如果正文中没有要编码的字符,则键盘读入并存储到ToBeTran文件中。
读入ToBeTran中将要编码的内容,将编码好的哈夫曼编码存储到CodeFile中。
(2)Encoding
编码功能:
对输入字符进行编码
(3)Decoding
译码功能:
利用已建好的哈夫曼树将文件codefile.txt中的代码进行译码,结果存入文件textfile.dat中。
3.解题思路
各模块的实现步骤为
(1)voidmain()//主函数
{
inti=0,n=0;
int*w,weight[MAX];
charin;
huftreetree[MAX];
charin;
while(in!
='5')
{
printf("****************赫夫曼编/译码*************\n");
rintf("I.InitE.EncodingD.DecodingQ.Exit");
printf("请输入您要操作的步骤:
");
switch(in)
{
case'I':
printf(“请输入字符个数:
\n");
scanf("%d",&n);
printf("请输入字符信息和权值:
\n");
for(i=1;i<=n;i++)
{
scanf("cha[i],weight[i]");
}
huffman(tree,w,n);break;
case'E':
huffmancode(tree,code,n);break;
case'D':
tohuffmancode(n);break;
case'Q':
decode(cha,tree,n);break;
}
}
(2)voidtohuffmancode(intn)//编码部分
{
inti=0,j;
charanychar[9999];
printf("请输入您要编码的字符串:
\n");
scanf("%s",&a);
printf("编码为:
\n");
for(anychar[i]!
='\0';i++)
{
j=0;
for(anychar[i]!
=cha[j]&&j<=n;)j++;
if(j<=n)
printf("",j\n);
}
}
(3)voiddecode(dharch[],hufftreetree[],intn)//译码
{
Inti,j,m,charb;
M=2*n-1;
I=m;
Printf("请输入编码:
\n");
Scanf("%s",&b);
Printf("译码为:
\n");
While(b!
=10){
If(tree[i],lchild==0)
{
printf("j=i,i=m",i);
}
}
If(tree[j].lchild!
=0)
Printf("ERROR");
}
三、实现
代码及注释
#include
#include
#include
#defineMAXVAL10000.0
structhufmtreenode{//赫夫曼树结点数据类型
chardata;
floatweight;//结点权值
intparent,lchild,rchild;//父结点,左、右孩子结点
};
structhufmtree{//赫夫曼树数据类型
hufmtreenode*node;//结点数组(根据n的值动态分配)
intn;//叶子结点数
};
structCodetype{//赫夫曼编码数据类型
char*bits;//编码流数组,n为为哈夫曼树中叶子结点的数目,编码的长度不可能超过n
intstart;//编码实际在编码流数组里的开始位置
};
voidSortHufmtree(hufmtree*tree){//将赫夫曼树n个叶子结点由大到小排序
inti,j,k;
hufmtreenodetemp;
if(tree==NULL)
return;
for(i=0;in;i++)
{
k=i;
for(j=i+1;jn;j++)
if(tree->node[j].weight>tree->node[k].weight)
k=j;
if(k!
=i)
{
temp=tree->node[i];
tree->node[i]=tree->node[k];
tree->node[k]=temp;
}
}
}
Codetype*HuffmanCode(hufmtree*tree){//赫夫曼编码的生成
inti,j,p,k;
Codetype*code;
if(tree==NULL)
returnNULL;
code=(Codetype*)malloc(tree->n*sizeof(Codetype));
for(i=0;in;i++)
{
printf("%c",tree->node[i].data);
code[i].bits=(char*)malloc(tree->n*sizeof(char));
code[i].start=tree->n-1;
j=i;
p=tree->node[i].parent;
while(p!
=-1){
if(tree->node[p].lchild==j)
code[i].bits[code[i].start]='0';
else
code[i].bits[code[i].start]='1';
code[i].start--;
j=p;
p=tree->node[p].parent;
}
for(k=code[i].start+1;kn;k++)
printf("%c",code[i].bits[k]);
printf("\n");
}
returncode;
}
hufmtree*BuildHuffmanTree(hufmtree*tree){//构建叶子结点已初始化的赫夫曼树
//tree中所有叶子结点已初始化
inti,j,p1,p2,m;
floatsmall1,small2;
m=2*(tree->n)-1;
for(i=tree->n;i{
tree->node[i].parent=-1;
tree->node[i].lchild=-1;
tree->node[i].rchild=-1;
tree->node[i].weight=0.0;
}
for(i=tree->n;i{
small1=small2=MAXVAL;
for(j=0;j<=i-1;j++)
{
if(tree->node[j].parent==-1&&tree->node[j].weight<=small1)
{
small1=tree->node[j].weight;
p1=j;
}
}
for(j=0;j<=i-1;j++)
{
if(tree->node[j].parent==-1&&tree->node[j].weight<=small2&&(j!
=p1))
{
small2=tree->node[j].weight;
p2=j;
}
}
tree->node[p1].parent=tree->node[p2].parent=i;
tree->node[i].weight=tree->node[p1].weight+tree->node[p2].weight;
tree->node[i].lchild=p1;
tree->node[i].rchild=p2;
}
returntree;
}
hufmtree*CreateHuffmanTreeFromSourceFile(){//通过解析源文件建立赫夫曼树
FILE*textfile,*datafile;
charch,sourcefilename[100];
inti,j=0,n=0;
floatcount[128];//用于统计字符在源文件中出现的次数,27表示26个英文字母和1个空格字符
hufmtree*tree;
//打开一个源文件
printf("\n请输入源文件所在路径:
\n");
scanf("%s",sourcefilename);
if((textfile=fopen(sourcefilename,"r"))==NULL){
printf("\n找不到文件%s\n",sourcefilename);
returnNULL;
}
for(i=0;i<128;i++)
count[i]=0;
//对源文件中各字符的个数统计
ch=fgetc(textfile);
while(!
feof(textfile)){
for(i=0;i<128;i++)
if(ch==char(i)){
count[i]++;
break;
}
ch=fgetc(textfile);
}
//将统计结果写入权值信息文件thedata.txt中,并构建赫夫曼树
datafile=fopen("thedata.txt","w");
for(i=0;i<128;i++)
if(count[i]!
=0)
n++;
fprintf(datafile,"%d\n",n);
tree=(hufmtree*)malloc(sizeof(hufmtree));
tree->node=(hufmtreenode*)malloc((2*n-1)*sizeof(hufmtreenode));
tree->n=n;
printf("\n源文件的字符集及其权值信息如下:
\n");
for(i=0;i<128;i++)
if(count[i]!
=0)
{
fprintf(datafile,"%c%f\n",char(i),count[i]);
printf("%c%.0f\n",char(i),count[i]);
tree->node[j].data=char(i);
tree->node[j].weight=count[i];
tree->node[j].parent=-1;
tree->node[j].lchild=-1;
tree->node[j].rchild=-1;
j++;
}
SortHufmtree(tree);
BuildHuffmanTree(tree);
fclose(textfile);
fclose(datafile);
printf("\n赫夫曼属构建完毕,现已将权值信息保存至thedata.txt\n");
returntree;
}
hufmtree*CreateHuffmanTreeByInput(){//通过用户输入建立赫夫曼树
intn;
hufmtree*tree;
inti,m;
FILE*datafile;
tree=(hufmtree*)malloc(sizeof(hufmtree));
datafile=fopen("data.txt","w");
//由用户输入字符与权值信息并将其写入thedata.txt,同时进行赫夫曼树初始化
printf("请输入字符数:
");
scanf("%d",&n);
if(n<=0)
{
printf("\n亲!
您输入有误哦!
\n");
returnNULL;
}
tree->node=(hufmtreenode*)malloc((2*n-1)*sizeof(hufmtreenode));
tree->n=n;
m=2*n-1;
for(i=0;i{
tree->node[i].parent=-1;
tree->node[i].lchild=-1;
tree->node[i].rchild=-1;
tree->node[i].weight=0.0;
}
fprintf(datafile,"%d\n",n);
for(i=0;i{
printf("输入第%d个字符及其权值:
",i+1);
tree->node[i].data=getche();
scanf("%f",&tree->node[i].weight);
fprintf(datafile,"%c%f\n",tree->node[i].data,tree->node[i].weight);
}
fclose(datafile);
//赫夫曼树构建
SortHufmtree(tree);
BuildHuffmanTree(tree);
printf("\n赫夫曼树构建完毕,已将权值信息存入thedata.txt\n");
returntree;
}
hufmtree*CreateHuffmanTreeFromDataFile(){//通过读取权值信息文件建立赫夫曼树
FILE*datafile;
inti,n;
hufmtree*tree;
if((datafile=fopen("data.txt","r"))==NULL){
printf("\n赫夫曼树未构建成功!
\n");
returnNULL;
}
//赫夫曼树初始化
fscanf(datafile,"%d",&n);
fgetc(datafile);
tree=(hufmtree*)malloc(sizeof(hufmtree));
tree->node=(hufmtreenode*)malloc((2*n-1)*sizeof(hufmtreenode));
tree->n=n;
for(i=0;itree->node[i].data=fgetc(datafile);
fscanf(datafile,"%f\n",&tree->node[i].weight);
tree->node[i].parent=-1;
tree->node[i].lchild=-1;
tree->node[i].rchild=-1;
}
fclose(datafile);
//赫夫曼树构建
SortHufmtree(tree);
BuildHuffmanTree(tree);
returntree;
}
hufmtree*Encoding(hufmtree*tree){//对源文件进行编码并将其输出至新文件
FILE*textfile,*codefile;
charch,sourcefilename[50];
inti,j;
Codetype*code;
if(tree==NULL)//如果内存中尚未建立赫夫曼树
{//试从thedata.txt中读取权值信息并建立赫夫曼树
tree=CreateHuffmanTreeFromDataFile();
if(tree==NULL)
returnNULL;
}
//读取源文件
printf("\n请输入源文件所在路径:
\n");
scanf("%s",sourcefilename);
if((textfile=fopen(sourcefilename,"r"))==NULL){
printf("\n找不到文件%s\n",sourcefilename);
returnNULL;
}
printf("\n源文件的原文如下:
\n");
ch=fgetc(textfile);
while(!
feof(textfile)){
printf("%c",ch);
ch=fgetc(textfile);
}
//编码
printf("\n字符集的赫夫曼编码如下:
\n");
code=HuffmanCode(tree);
//将源文件中各字符编码并写入codefile
codefile=fopen("CodeFile.txt","w");
fseek(textfile,0,SEEK_SET);
ch=fgetc(textfile);
while(!
feof(textfile))
{
for(i=0;in;i++)
if(ch==tree->node[i].data){
for(j=code[i].start+1;jn;j++)
fputc(code[i].bits[j],codefile);
break;
}
if(i==tree->n)//在赫夫曼树中找不到与文本内容里对应的字符
{
printf("\n字符%c不在赫夫曼树中,不能正确编码!
\n",ch);
fclose(codefile);
returnNULL;
}
ch=fgetc(textfile);
}
fclose(codefile);
printf("\n编码已成功,已将代码写入至CodeFile.txt,代码如下:
\n");
codefile=fopen("CodeFile.txt","r");
ch=fgetc(codefile);
while(!
feof(codefile)){
printf("%c",ch);
ch=fgetc(codefile);
}
printf("\n");
fclose(textfile);
fclose(codefile);
returntree;
}
voidDecoding(hufmtree*tree)//对编码文件进行译码并将其输出至新文件
{
FILE*codefile,*decodef