*y=i;
}
//对文件tobetrans中的正文进行编码,然后将结果存入文件codefile中
voidCoding()
{
FILE*fp,*fw;
inti,f,c,start;
char*cd;
HuffmanCodeHC;
if(n==0)
n=Read_tree(HT);//从文件hfmtree.txt中读入赫夫曼树,返回叶子结点数
//求赫夫曼树中各叶子节点的字符对应的的编码,并存于HC指向的空间中
{
HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
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));
strcpy(HC[i],&cd[start]);
}
free(cd);
}
if((fp=fopen("tobetrans.txt","rb"))==NULL)
printf("Openfiletobetrans.txterror!
\n");
if((fw=fopen("codefile.txt","wb+"))==NULL)
printf("Openfilecodefile.txterror!
\n");
chartemp;
fscanf(fp,"%c",&temp);//从文件读入第一个字符
while(!
feof(fp))
{
for(i=1;i<=n;i++)
if(HT[i].ch==temp)break;//在赫夫曼树中查找字符所在的位置
for(intr=0;HC[i][r]!
='\0';r++)//将字符对应的编码存入文件
fputc(HC[i][r],fw);
fscanf(fp,"%c",&temp);//从文件读入下一个字符
}
fclose(fw);
fclose(fp);
printf("\n已将文件hfmtree.txt成功编码,并已存入codefile.txt中!
\n\n");
}
//将文件codefile中的代码进行译码,结果存入文件textfile中
voidDecoding()
{
FILE*fp,*fw;
intm,i;
char*code,*text,*p;
if(n==0)
n=Read_tree(HT);//从文件hfmtree.txt中读入赫夫曼树,返回叶子结点数
if((fp=fopen("codefile.txt","rb"))==NULL)
printf("Openfilecodefile.txterror!
\n");
if((fw=fopen("textfile.txt","wb+"))==NULL)
printf("Openfiletextfile.txterror!
\n");
code=(char*)malloc(sizeof(char));
fscanf(fp,"%c",code);//从文件读入一个字符
for(i=1;!
feof(fp);i++)
{
code=(char*)realloc(code,(i+1)*sizeof(char));//增加空间
fscanf(fp,"%c",&code[i]);//从文件读入下一个字符
}
code[i-1]='\0';
//codefile.txt文件中的字符已全部读入,存放在code数组中
text=(char*)malloc(100*sizeof(char));
p=text;
m=2*n-1;
if(*code=='0')
find(HT,code,text,HT[m].lchild,m);//从根节点的左子树去找
else
find(HT,code,text,HT[m].rchild,m);//从根节点的右子树去找
for(i=0;p[i]!
='\0';i++)//把译码好的字符存入文件textfile.txt中
fputc(p[i],fw);
fclose(fp);
fclose(fw);
printf("\n已将codefile.txt文件成功译码,兵已存入textfile.txt文件!
\n\n");
}
//将文件codefi1e以紧凑格式显示在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件codeprint中。
voidPrint_code()
{
FILE*fp,*fw;
chartemp;
inti;
if((fp=fopen("codefile.txt","rb"))==NULL)
printf("Openfilecodefile.txterror!
\n");
if((fw=fopen("codeprint.txt","wb+"))==NULL)
printf("Openfilecodeprint.txterror!
\n");
printf("\n文件codefi1e显示如下:
\n");
fscanf(fp,"%c",&temp);//从文件读入一个字符
for(i=1;!
feof(fp);i++)
{
printf("%c",temp);
if(i%50==0)printf("\n");
fputc(temp,fw);//将该字符存入文件codeprint.txt中
fscanf(fp,"%c",&temp);//从文件读入一个字符
}
printf("\n\n已将此字符形式的编码写入文件codeprint.txt中!
\n\n");
fclose(fp);
fclose(fw);
}
//将已在内存中的哈夫曼树显示在屏幕上,并将此字符形式的哈夫曼树写入文件treeprint中。
voidPrint_tree()
{
unsignedcharT[100][100];
inti,j,m=0;
FILE*fp;
if(n==0)
n=Read_tree(HT);//从文件hfmtree.txt中读入赫夫曼树,返回叶子结点数
Convert_tree(T,0,&m,2*n-1);//将内存中的赫夫曼树转换成凹凸表形式的树,存于数组T中
if((fp=fopen("treeprint.txt","wb+"))==NULL)
printf("Openfiletreeprint.txterror!
\n");
printf("\n打印已建好的赫夫曼树:
\n");
for(i=1;i<=2*n-1;i++)
{
for(j=0;T[i][j]!
=0;j++)
{
if(T[i][j]==''){printf("");fputc(T[i][j],fp);}
else
{printf("%d",T[i][j]);fprintf(fp,"%d\n",T[i][j]);}
}
printf("\n");
}
fclose(fp);
printf("\n已将该字符形式的哈夫曼树写入文件treeprint.txt中!
\n\n");
}
//从文件hfmtree.txt中读入赫夫曼树,返回叶子节点数
intRead_tree(HuffmanTree&HT)
{
FILE*fp;
inti,n;
HT=(HuffmanTree)malloc(sizeof(HTNode));
if((fp=fopen("hfmtree.txt","r"))==NULL)
printf("Openfilehfmtree.txterror!
\n");
for(i=1;!
feof(fp);i++)
{
HT=(HuffmanTree)realloc(HT,(i+1)*sizeof(HTNode));//增加空间
fread(&HT[i],sizeof(HTNode),1,fp);//读入一个节点信息
}
fclose(fp);
n=(i-1)/2;
returnn;
}
//译码时根据01字符串寻找相应叶子节点的递归算法
voidfind(HuffmanTree&HT,char*code,char*text,inti,intm)
{
if(*code!
='\0')//若译码未结束
{
code++;
if(HT[i].lchild==0&&HT[i].rchild==0)//若找到叶子节点
{
*text=HT[i].ch;//将叶子节点的字符存入text中
text++;
if((*code=='0'))
find(HT,code,text,HT[m].lchild,m);//从根节点的左子树找
else
find(HT,code,text,HT[m].rchild,m);//从根节点的右子树找
}
else//如果不是叶子节点
if(*code=='0')
find(HT,code,text,HT[i].lchild,m);//从该节点的左子树去找
else
find(HT,code,text,HT[i].rchild,m);//从该节点的右子树去找
}
else
*text='\0';//译码结束
}
//将文件中的赫夫曼树转换成凹凸表形式的赫夫曼树打印出来
voidConvert_tree(unsignedcharT[100][100],ints,int*i,intj)
{
intk,l;
l=++(*i);
for(k=0;k
T[l][k]='';
T[l][k]=HT[j].weight;
if(HT[j].lchild)
Convert_tree(T,s+1,i,HT[j].lchild);
if(HT[j].rchild)
Convert_tree(T,s+1,i,HT[j].rchild);
T[l][++k]='\0';
}
四.调试步骤
1.赫夫曼树节点的数据类型定义为:
typedefstruct{//赫夫曼树的结构体
charch;
intweight;//权值
intparent,lchild,rchild;
}HTNode,*HuffmanTree;
2.voidHuffmanCoding(HuffmanTree&,char*,int*,int);建立赫夫曼树的算法,此函数块调用了Select()函数。
voidselect(HuffmanTreeHT,intj,int*x,int*y);从已建好的赫夫曼树中选择parent为0,weight最小的两个结点。
3.利用已建好的哈夫曼树从文件hfmtree.txt中读入,对文件中的正文进行编码,然后将结果存入文件codefile.txt中。
4.coding
编码功能:
对输入字符进行编码
5.Decoding
译码功能:
利用已建好的哈夫曼树将文件codefile.txt中的代码进行译码,结果存入文件textfile.txt中。
6.Print()打印功能函数:
输出哈夫曼树以及对应的编码。
5.运行结果
六.分析与思考
我的课程设计题目是赫夫曼编译码器。
最初做这个程序的时候,让我觉得完成这次程序设计真的是太难了,然后我查阅了课本,并去图书馆借了资料,在写这个程序的时候也参考了网上的设计流程,写完刚运行时出现了很多问题。
尤其是编码错误,导致内存无法read,通过同组人员的交流请教,逐渐明白过来,然后经过不知道多少次修改才顺利运行。
本次试验也让我明白了理论与实际相结合的重要性,并提高了自己组织数据及编写大型程序的能力,培养了基本的、良好的程序设计技能以及合作能力。
通过对各个步骤各个流程的控制,逐渐让我产生了兴趣,在实际编写过程中,和同学们相互讨论让我学到的不仅仅是一些解决问题的方法,更是解决问题的思想。
数据结构实验报告
实验五
一.实验内容:
查找表是数据处理的重要操作,试建立有100个结点的二叉排序树进行查找,然后用原数据建立AVL树,并比较两者的平均查找长度。
【基本要求】
(1)以链表作为存储结构,实现二叉排序树的建立、查找和删除。
(2)根据给定的数据建立平衡二叉树。
(3)比较二叉排序树和平衡二叉树的平均查找长度。
二.实验目的
熟练掌握顺序查找、折半查找及二叉排序树、平衡二叉树上的查找、插入和删除的方法,比较它们的平均查找长度。
三.程序清单
#include
#include
#include
#defineEQ(a,b)((a)==(b))
#defineLT(a,b)((a)<(b))
#defineLQ(a,b)((a)>(b))
usingnamespacestd;
typedefintKeytype;
typed