数据结构 实验报告Word文档下载推荐.docx
- 文档编号:21325024
- 上传时间:2023-01-29
- 格式:DOCX
- 页数:23
- 大小:159.78KB
数据结构 实验报告Word文档下载推荐.docx
《数据结构 实验报告Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《数据结构 实验报告Word文档下载推荐.docx(23页珍藏版)》请在冰豆网上搜索。
……
}
(2).创建哈夫曼树。
CreateHT(ht,n);
(3).创建哈夫曼编码。
CreateHCode(ht,hcd,n);
(4).显示菜单。
showmenu();
getchar();
接收用户的输入的选择后使用switch函数调用相关函数实现相应的功能。
2.菜单模式。
进行完数据的初始化,字符的编码等工作之后,此时,showmenu函数起主要作用,用户的选择所需的功能,switch函数根据用户的选择,调用想干函数实现所要求的功能。
三.详细设计:
1.main函数的设计——在main函数中首先需进行数据的初始化,创建哈夫曼树,创建哈夫曼编码,然后才能显示菜单,让用户选择相应的功能,因为前三步是后面的函数实现的基础,不能直接进行菜单功能的选择。
voidmain()
{
intn,i=0;
charsymbol,number=0;
HTNodeht[M];
HCodehcd[N];
scanf("
%d"
&
n);
getchar();
//吃掉回车
while(symbol=getchar(),symbol!
='
#'
)//symbol记录每个字符
{
if(symbol!
\n'
)
{
ht[i].data=symbol;
i++;
}
for(i=0;
i<
n;
i++)
printf("
%c:
ht[i].data);
scanf("
ht[i].weight);
printf("
CreateHT(ht,n);
while(number!
4'
fflush(stdin);
showmenu();
%c"
number);
switch(number)
case'
1'
:
DispHCode(ht,hcd,n);
break;
2'
DispHCode2(ht,hcd,n);
3'
print(ht,n);
default:
\n输入错误,请重新输入:
system("
cls"
感谢使用,再见!
2.创建哈夫曼树:
voidCreateHCode(HTNodeht[],HCodehcd[],intn)//求每个叶子结点的哈夫曼编码
inti,f,c;
HCodehc;
hc.start=n;
//指向编码的最后一位,从末位到首位求编码
c=i;
//指向当前叶子结点
f=ht[i].parent;
//指向当前叶子结点的双亲
while(f!
=-1)//有对应的双亲
if(ht[f].lchild==c)//当前叶子结点是其双亲的左孩子
hc.cd[hc.start--]='
0'
;
else//当前叶子结点是其双亲的右孩子
c=f;
//得到某一位的编码数字后,令c指向双亲
f=ht[f].parent;
//f指向双亲的双亲
hc.start++;
//让start指向编码的首位
hcd[i]=hc;
//将求得的编码赋值给hcd[i]
3创建哈夫曼编码:
4.显示每个字符对应的哈夫曼编码以及出现的次数。
voidDispHCode(HTNodeht[],HCodehcd[],intn)//输出每个字符对应的编码
inti,k;
输出每个字符出现的次数:
%d"
ht[i].data,ht[i].weight);
输出哈夫曼编码:
%c:
\t"
for(k=hcd[i].start;
k<
=n;
k++)
hcd[i].cd[k]);
5.翻译一串字符串:
voidDispHCode2(HTNodeht[],HCodehcd[],intn)//输出字符串对应的编码
inti,j,k;
charstring[100];
请输入一串英文字符:
本科实验报告专用纸
scanf("
%s"
string);
i=0;
将字符翻译成哈夫曼编码:
while(string[i]!
\0'
)//将字符串中的每个字符与用户在此前输入的每个字符进行比较,
{//若相同则输出其哈夫曼编码,从而将字符串翻译成编码。
for(j=0;
j<
j++)
if(string[i]==ht[j].data)
for(k=hcd[j].start;
{
hcd[j].cd[k]);
}
}
6.输出树的中序与先序遍历的结果。
根据二叉树的性质,我们知道,先序遍历(或后序遍历)+中序遍历可以唯一的确定一棵哈夫曼树,因此我们采用通过先序遍历和中序遍历的形式来输入哈夫曼树。
代码如下:
voidpreorderprint(HTNodeht[],inta)//先序遍历哈夫曼树
ht[a].weight);
if(ht[a].lchild!
=-1)
preorderprint(ht,ht[a].lchild);
if(ht[a].rchild!
preorderprint(ht,ht[a].rchild);
}//输出先序遍历结果
voidinorderprint(HTNodeht[],inta)//中序遍历输出哈夫曼树
inorderprint(ht,ht[a].lchild);
if(ht[a].rchild!
inorderprint(ht,ht[a].rchild);
}//输出中序遍历结果
intselectmax(HTNodeht[],intn)//以上两个函数必须在找到根结点的前提下进行
intmaxweight=0,maxi=0,i;
if(ht[i].weight>
maxweight)
maxi=i;
returnmaxi;
}//找到权值最大的结点,即根结点
主函数中这样调用这两个函数selectmax(ht,2*n-1)的值传给了inta
preorderprint(ht,selectmax(ht,2*n-1));
inorderprint(ht,selectmax(ht,2*n-1));
函数调用的关系图如下:
四:
调试分析:
调试程序是一个漫长的过程,虽然遇到了很多问题,但不一一列举了。
这里只讲讲在调试过程中遇到的两个最主要的问题及解决的途径。
1函数调用与参数传递的问题
问题概述:
原先的程序中设定了一个初始化函数init用于接收用户输入的各个字符和权值,进行树和编码的构建,结果程序运行得不到正确的结果。
voidinit(intn,inti,charsymbol,charnumber,HTNodeht[],HCodehcd[])
{
//printf("
欢迎使用\n"
请输入各个不同字符,不包括回车和空格,以#号结束:
'
&
symbol!
}
}
运行情况:
编译后有两个警告:
(仍然能够运行)
大学本科实验报告专用纸
(没有输出编码)
(没有翻译字符)
(希望输出序列,但很明显是乱码)
(得不到应有的结果)
原因分析:
估计是传值调用的问题
解决方法:
取消init函数,将它的内容转移到main函数,这样就得到了正确的结果
2改前不能接收空格
原先的程序中if(symbol!
)限制了用户不得输入空格。
只要用户不输入空格参与HUFFMAN树构建是不会出现问题的。
程序运行成功,结果正确。
但是空格又是一个比较重要的字符,在文
本中经常出现,因此把空格也作为一个字符,参与HUFFMAN树构建是非常必要的。
遇到的困难:
经过简单的修改,写成if(symbol!
)会出现以下问题:
(仍然能够创建树和编码)
(但翻译的时候会出错)
空格是可以参与HUFFMAN的构建的,只是在翻译的时候空格会被忽略,其实问题在于输入字符串的时候,scanf对空格和回车都是作为退出标志所导致
修改办法:
1.将scanf改为gets,因为gets是只以回车作为退出标志
2.另外在一次错误输入后,程序会陷入死循环,问题也是输入的时候scanf是之吃一个字符,这样万一输入多个字符,那别的字符留在缓存区,下次就会读它们,而不是读新的输入,为了解决这个问题调用了函数fflush(stdin)
对程序的改动有这些地方:
改前if(symbol!
改后if(symbol!
改前voidDispHCode2(HTNodeht[],HCodehcd[],intn)//输出每个字符对应的编码
改后
voidDispHCode2(HTNodeht[],HCodehcd[],intn)//输出每个字符对应的编码
请输入一串字符:
gets(string);
改前
while(number!
showmenu();
……
//getchar();
修改过后的程序(即最终版)运行如下:
这时候空格也能翻译了,从结果来看是正确的。
(3)经验和体会。
通过这次实验,学到了不少,感受也很深。
从着手做这个课题,到最终完成,经过了一个漫长而艰辛的过程。
编写和调试程序可以说是最让我们感到困难的。
有时候看来是一点点小问题,但是真正要把它修改过来,使程序运行得到正确结果,还是一件不容易的事情。
看来要学好计算机课程,编程一定要下苦功。
编程与逻辑推理一样,要求严谨,慎重的思维模式,我们认为做其他事情也应该要这样。
没有严谨,慎重的态度,很多事情都做不了。
做这个实验对我们来说压力是非常大的,这主要是由于我们自身水平的问题,和时间上的限制。
程序不能运行成功的时候,使我们一度感到非常苦恼,担心这个课题设计也许没办法完成。
还好有老师的指导和同学的帮助,使我们可以最终完成任务。
在这里向老师和帮助过我们的同学表示诚挚的感谢。
遇到问题一定要多问多思考,还有努力工作,认真对待,保持良好的心态,这使得我们有可能获得成功。
以上是我们的一点经验与体会。
五:
用户使用说明:
1.首先,用户进入此哈夫曼编译程序的友好界面。
如下:
2.用户根据“友情提示”,输入相关的数据。
3.用户可以查看每个字符的编码。
4.程序根据用户输入的数据,构建一棵哈夫曼树,并将各字符译成
5.编码形式。
6.按照先序遍历和中序遍历的原理,输出哈夫曼树序列,唯一确定一棵哈夫曼树。
7.程序编译完毕,退出哈夫曼编译系统。
8.用户需要注意的问题
(1)注意一定要输入不同的字符,否则同一个字符对应两个编码,会得到不希望的结果
(2)输入字符个数少于限定的个数,也能翻译,但某些叶子结点所代表的字符是未知的
(3)输入字符个数多于限定的个数,也能翻译,但超出限定范围的字符(如d)不被接收
注意超出限定范围的字符(如d)是没有被翻译的,而直接跳过。
(4).用户请注意,此程序在针对字符改变权值的时候,必须重新初始化,继而实现各个功能。
六.测试结果说明:
1.测试一:
“欢迎使用”
8
ABCDEFGH#
A:
5
B:
29
C:
7
D:
E:
14
F:
23
G:
3
H:
11
5B:
29C:
7D:
8E:
14F:
23G:
3H:
A:
0001
B:
10
C:
1110
D:
1111
E:
110
F:
01
G:
0000
H:
001
按先序遍历输出每个结点的权值:
10042198351123582929141578
按中序遍历输出每个结点的权值:
38519114223100295814297158
3.测试数据:
字符
ABCDEFGHIJKL
频度
18664132232103211547571532
MNOPQRSTUVWXYZ
205763151485180238181161
功能1:
输出每个字符出现的次数及对应的哈夫曼编码
:
186A:
64B:
13C:
22D:
32E:
103F:
21G:
15H:
47I:
57J:
1K:
5L:
32M:
20N:
57O:
63P:
15Q:
1R:
48S:
51T:
80U:
23V:
8W:
18X:
1Y:
16Z:
1
111
1010
100000
00000
10110
010
110011
100001
I:
0110
J:
1100001000
K:
11000011
L:
10111
M:
110010
N:
0111
O:
1001
P:
100010
Q:
1100001001
R:
0010
S:
0011
T:
1101
U:
00001
V:
1100000
W:
110001
X:
1100001010
大学本科实验报告专用纸
Y:
100011
Z:
1100001011
/******************请选择你要实现的功能:
(1~5)*****************/
1.显示每个字符对应的编码及出现的次数
2.翻译字符串
3.显示树的中序与先序遍历结果
4.退出(quit)
/**************************************************************/
功能2:
翻译字符串:
功能3:
输出字符串的先序和中序遍历
功能4:
退出编译系统。
七.附录:
#include"
1.h"
//包含了各需要使用的头文件,及各种定义,方便用户在进行相类似的程序时直接使用。
主要包括了:
#include<
stdio.h>
string.h>
stdlib.h>
#defineN900
//最大叶子结点数
#defineM2*N-1//最大结点数
typedefstruct
chardata;
//结点数据(字符),由用户输入
intweight;
//结点权值(字符出现的次数),由用户输入
intparent;
intlchild;
intrchild;
}HTNode;
//哈夫曼树的结点
charcd[N];
intstart;
}HCode;
//编码
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 实验报告 实验 报告