数据结构实验报告六 图.docx
- 文档编号:29862308
- 上传时间:2023-07-27
- 格式:DOCX
- 页数:15
- 大小:63.77KB
数据结构实验报告六 图.docx
《数据结构实验报告六 图.docx》由会员分享,可在线阅读,更多相关《数据结构实验报告六 图.docx(15页珍藏版)》请在冰豆网上搜索。
数据结构实验报告六图
(本实验项目方案受“教育部人才培养模式创新实验区(X3108005)”项目资助)
实验难度:
A□B□C□
序号
学号
姓名
成绩
1
2
3
指导教师
(签名)
学 期:
2010秋季学期
任课教师:
张德海
实验题目:
图及其应用
姓名:
申平
学号:
20091120185
电子邮件:
完成提交时间:
2010年12月27日
云南大学软件学院2010学年秋季学期
《数据结构实验》成绩考核表
学号:
姓名:
本人承担角色:
评分项目
评分指标
分值
得分
实验构思(10%)
1.实验目的明确
5
2.实验内容理解透彻、对实验所涉及到的知识点分析到位
5
实验设计(15%)
1.有对基本数据结构的抽象数据类型定义
5
2.实验方案设计完整,数据结构、算法选择合理
5
3.算法结构和程序功能模块之间逻辑清晰、有相应的流程图
5
实验实现(25%)
1.代码编写规范、风格统一、注释清楚易读
5
2.程序运行正常,测试结果正确
15
3.界面友好、易于操作、有较强的容错性
5
实验报告撰写(10%)
1.内容详实无缺漏,文字流畅、图表清楚
5
2.实验结果分析客观、详细,实验体会真实可信,对原实验方案的改进和对实验内容的发散性思考
5
个人工作量(30%)
1.个人完成工作量
15
2.个人技术水平
10
3.团队合作精神
5
实验运作(10%)
1.有一定用户群
5
2.应用前景分析
5
综合得分:
(满分100分)
指导教师:
年月日
(注:
此表在难度为C时使用,每个成员一份。
)
(下面的内容由学生填写,格式统一为,字体:
楷体,行距:
固定行距18,字号:
小四,个人报告按下面每一项的百分比打分。
难度A满分70分,难度B满分90分)
一、【实验构思(Conceive)】(10%)
1.本演示程序中,元素限定为char型。
2.演示程序以用户和计算机的对话方式执行,即在计算机终端显示“提示信息“后,由用户在键盘上输入符合演示程序中规则的图的边数,结点数;相应的先序和按层遍历会显示其后。
3.程序执行命令包括:
1)根据用户给出的图字符串进行对临接表的先序构建2)输出构建的临接表
4.测试数据
用户输入:
abc//d//e//结果:
DLR:
abcdeLDR:
cbdaeLRD:
cdbeaCeng:
abecd
用户输入:
ab/cd///e//结果:
DLR:
abcdeLDR:
bdcaeLRD:
dcbeaCeng:
abecd
二、【实验设计(Design)】(20%)
(本部分应包括:
抽象数据类型的功能规格说明、主程序模块、各子程序模块的伪码说明,主程序模块与各子程序模块间的调用关系)
为实现上述程序功能,需要三个抽象数据类型:
队列和图
1.图的抽象数据类型定义为:
⏹ADTGraph{
⏹数据对象V:
顶点集
⏹数据关系R:
R={VR}
⏹VR={
⏹基本操作:
⏹CreateGraph(&G,V,VR);//构造图
⏹DestroyGraph(&G);//销毁图
⏹LocateVex(G,u);//顶点u在图中位置
⏹GetVex(G,v);//取顶点v的值
⏹PutVex(&G,v,value);//顶点v赋值
⏹FirstAdjVex(G,v);//v的第一个邻接点
⏹NextAdjVex(G,v,w);//v相对于w的下一个邻接点
⏹InsertVex(&G,v);//增添顶点v
⏹DeleteVex(&G,v);//删除顶点v及相关弧
⏹InsertArc(&G,v,w);//增添弧
⏹DeleteArc(&G,v,w);//删除弧
⏹DFSTraverse(G,v,Visit());//深度优先搜索DFS
⏹BFSTraverse(G,v,Visit());//广度优先搜索BFS
⏹}
2.本程序包含四个模块:
1)主程序模块:
main()
{
初始化一个空队列;(利用CreateQueue(&Q);函数)
进入用户输入图顶点数和边数阶段;
进入用户输入图的边信息阶段;
根据用户输入的图的边信息进行对邻接表的构建(利用CreateGraph(&G);这个函数)
输出邻接表
两种遍历输出构建的邻接表(利用DFS(q,i);BFS(&G);这2个函数)
}
2)图单元模块-------实现图抽象数据类型。
3)邻接表2种遍历单元模块(包含队列单元模块)
4)图节点结构单元模块-------定义图的节点结构。
各模块是之间关系如下:
主程序模块
图单元模块-
邻接表2种遍历单元模块
图节点结构单元模块
三、【实现描述(Implement)】(30%)
(本部分应包括:
抽象数据类型具体实现的函数原型说明、关键操作实现的伪码算法、函数设计、函数间的调用关系,关键的程序流程图等,给出关键算法的时间复杂度分析。
)
1.元素类型(此程序固定为char)结点类型
typedefstruct{
int*base;
int*top;
intlength;
}Queue;//队列结点
typedefstructarcNode{
intlocate;
structarcNode*next;
}arcNode;//边结点
typedefstructVNode{
chardata;
arcNode*firstarc;
}VNode,V[20];//顶点结点
typedefstruct{
intvexnum,arcnum;
charkind;
Vvex;
}ALGraph;//图
2图的基本操作:
⏹CreatGraph(ALGraph*p)//创建邻接表
⏹DFS(VNode*p,inta);//先序遍历邻接表
⏹BFS(&G);//按层遍历邻接表
图所有操作代码:
voidCreatGraph(ALGraph*p){
inti,arc1,arc2;
chara,b;
arcNode*m,*n;
printf("\nPleaseenterthevexnum,thearcnumandthekindofthisGraph.\n");
scanf("%d",&(*p).vexnum);
scanf("%d",&(*p).arcnum);
printf("\nPleaseenterthedataofthevex.(MustBeDifferent!
!
!
)\n");
for(i=0;i<(*p).vexnum;i++){
(*p).vex[i].data=getche();
(*p).vex[i].firstarc=NULL;
}
printf("\n\nPleaseenterthearcofthisGraph,suchasac.\n");
for(i=0;i<(*p).arcnum;i++){
a=getche();
b=getche();
arc1=Locate(a);
arc2=Locate(b);
m=(arcNode*)malloc(sizeof(arcNode));
m->locate=arc2;
m->next=(*p).vex[arc1].firstarc;
(*p).vex[arc1].firstarc=m;
n=(arcNode*)malloc(sizeof(arcNode));
n->locate=arc1;
n->next=(*p).vex[arc2].firstarc;
(*p).vex[arc2].firstarc=n;
printf("ok!
\n");
}
}
voidDFS(VNode*p,inta){
intm;
VNode*q;
VNode*n;
n=p;
visit[a]=1;
printf("%c",n->data);
for(m=Firstarc(n);m!
=-1;m=Nextarc(n,m)){/*for(m=Firstarc(n);m!
=-1&&visit[m]==0;m=
if(visit[m]==0){Nextarc(n,m))大错特错!
!
!
*/
q=&(G.vex[m]);
DFS(q,m);
}
}
}
voidBFS(ALGraph*G){
inti;
intm;
arcNode*q;
for(i=0;i<(*G).vexnum;i++){
if(visit[i]==0){
IniQueue(&Q,i);
while(Q.length!
=0){
PopQ(&Q,&m);
if(visit[m]==0){
printf("%c",(*G).vex[m]);
}
visit[m]=1;/*至关重要*/
for(q=(*G).vex[m].firstarc;q;q=q->next){/*for(q=(*G).vex[i].firstarc;q&&visit[q->locate]==if(visit[q->locate]==0){0;q=q->next)大错特错!
!
!
*/
IniQueue(&Q,q->locate);
}
}
}
}
}
}
2.主函数和其它函数的算法
(1)主函数
main(){
CreateStack(&L);//创建空栈
CreateQueue(&Q);//创建空队列
T=(BiTNode*)malloc(sizeof(BiTNode));//先为二叉树的根创建空间
printf("PleaseEnteryourtree.(suchas:
ab/cd///e//)\n");//提示信息
CreateBitree(T);//先序创建二叉链表
printf("\nTheDLRofthistreeis:
");
Dlr(T,&L);//先序遍历二叉树
printf("\nTheLDRofthistreeis:
");
Ldr(T,&L);//中序遍历二叉树
printf("\nTheLRDofthistreeis:
");
Lrd(T);//后序遍历二叉树
printf("\nTheCENGofthistreeis:
");
Ceng(T);//按层遍历二叉树
getch();
}
(2)构造创建空栈、指针入栈、指针出栈的函数
voidCreateStack(SqStack*p){//创建空栈
p->base=(BiTree*)malloc(100*sizeof(BiTree));//特别注意:
p->base此时所指内容是BiTree*型指针,即指向BiTNode型的指针(指针指向指针)
p->top=p->base;
p->stacksize=100;
}
voidPush(SqStack*p,BiTNode*m){//指针入栈注意:
传入的是指向BiTNode型的指针
if(p->top-p->base>=p->stacksize)//当空间不够时
{
p->base=(BiTree*)realloc(p->base,(p->stacksize+10)*sizeof(BiTree));
p->top=p->base+p->stacksize;
p->stacksize+=10;}
*(p->top)=m;
p->top++;
}
voidPop(SqStack*p,BiTree*m)//指针出栈注意:
传入的是指向BiTree型的指针(不同于入栈时传入的是BiTNode型的指针)解释:
因为想要让某指针a指向其他的地址,必须让另一个指针b指向这个指针a,当改变b的内容(*b)时,也就改变了指针a。
因此此函数中m充当了b的角色,而a是调用此函数时传入的一个指向BiTNode型的指针,例如Pop(&L,&p)中p充当了a的角色。
{*m=*(p->top-1);//此时改变m的内容为另一个地址,即使p指针指向另一个新地址,达到了目的
p->top--;
}
(3)构造创建空队、指针入队、指针出队的函数
voidCreateQueue(Queue*p){//创建空队
p->base=(BiTree*)malloc(100*sizeof(BiTree));
p->top=p->base;
p->length=0;
}
voidPopQ(Queue*q,BiTree*m){//指针出队注意:
传入的是指向BiTree型的指针
*m=*(q->base);
q->base++;
q->length--;
}
voidIniQueue(Queue*q,BiTNode*p){//指针入队注意:
传入的是指向BiLNode型的指针
if(p->data!
='#'){//指针为空时就不必入队了,没必要再去访问空指针的内容了
*(q->top)=p;
q->top++;
q->length++;
}
}函数的调用关系:
Main
CreateStackCreateQueueCreateBitreeDlrLdrLrdCeng
PushPopIniQueuePopQ
四、【测试结果(Testing)】(10%)
(本部分应包括:
对实验的测试结果,应具体列出每次测试所输入的数据以及输出的数据,并对测试结果进行分析总结)
1.进入演示程序后即显示文本方式的用户界面:
2.进入主函数命令后,即提示键入您欲创建的二叉树的字符串,结束符为回车,输出结果
测试结果:
执行命令PleaseEnteryourtree.(suchas:
ab/cd///e//)
键入abc//d//e//
输出:
DLR:
abcdeLDR:
cbdaeLRD:
cdbeaCeng:
abecd
键入ab/cd///e//
输出:
DLR:
abcdeLDR:
bdcaeLRD:
dcbeaCeng:
abecd
键入abd//ef/g////c/h//
输出:
DLR:
abdefgchLDR:
dbfgeachLRD:
dgfebhcaCeng:
abcdehfg
五、【实验总结】(10%)
(本部分应包括:
自己在实验中完成的任务,注意组内的任意一位同学都必须独立完成至少一项接口的实现;对所完成实验的经验总结、心得)
开始的时候把T=(BiTNode*)malloc(sizeof(BiTNode))写在了CreateBitree函数中,发现结果总是不对,所有的元素都没被指针指上,也就是指针发生了错误,没有指向希望要指的内容。
于是我将开空间T=(BiTNode*)malloc(sizeof(BiTNode))写在了调用CreateBitree函数之前,这样T就指向了希望指的内容。
开始Pop函数是这样写的
voidPop(SqStack*p,BiLNode*m)
{
m=*(p->top-1);
p->top--;
}
应用是这样的:
Pop(&L,p)。
结果总不对,即指针仍然指向原地址,并未改变,后来发现了错误,将,BiLNode改为BiTree,将m改为*m,应用改为了这样的:
Pop(&L,&p)。
结果正确了。
开始把结构体typedefstructBiTNode{…}BiTNode,*BiTree的定义写在了结构体typedefstruct{…}SqStack定义的后面,结果运行时发生了错误。
经仔细检查后发现,SqStack中含有BiTree,因此必须将结构体typedefstructBiTNode{…}BiTNode,*BiTree的定义写在结构体typedefstruct{…}SqStack定义的前面。
(1)对于稀疏图,当然是SPFA的天下,不论是单源问题还是APSP问题,SPFA的效率都是最高的,写起来也比Dijkstra简单。
对于无向图的APSP问题还可以加入优化使效率提高2倍以上。
(2)对于稠密图,就得分情况讨论了。
单源问题明显还是Dijkstra的势力范围,效率比SPFA要高2-3倍。
APSP问题,如果对时间要求不是那么严苛的话简简单单的Floyd即可满足要求,又快又不容易写错;否则就得使用Dijkstra或其他更高级的算法了。
如果是无向图,则可以把Dijkstra扔掉了,加上优化的SPFA绝对是必然的选择。
六、【代码】(10%)
(本部分应包括:
完整的代码及充分的注释。
注意纸质的实验报告无需包括此部分。
格式统一为,字体:
Georgia,行距:
固定行距12,字号:
小五)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构实验报告六 数据结构 实验 报告