实习四 图及其应用 (题目: 图遍历的演示 )
一、需求分析
1.问题描述:
很多涉及图上操作的算法都是以图的遍历操作为基础的。试写一个程序,演示连通的无向图上行遍全部结点的操作。
2.基本要求:
以邻接多重表为存储结构,实现连通无向图的深度优先和广度优先遍历。以用户指定的结点为起点,分别输出每种遍历下的结点访问序列
和相应生成树的边集。
3.测试数据:
实习四 图及其应用
题目: 图遍历的演示 实习时间:2012/11/20
一、需求分析
1.问题描述:
很多涉及图上操作的算法都是以图的遍历操作为基础的。试写一个程序,演示连通的无向图上行遍全部结点的操作。
2.基本要求:
以邻接多重表为存储结构,实现连通无向图的深度优先和广度优先遍历。以用户指定的结点为起点,分别输出每种遍历下的结点访问序列
和相应生成树的边集。
3.测试数据:
二、设计
1. 设计思想
(1)存储结构
邻接多重表为存储结构
(2)主要算法基本思想
所有代码思想均由老师授课所得:
深度优先搜索(Depth-first Search,DFS)
① 首先访问起始顶点v,再访问图中与v相邻接的且未被
访问过的任一顶点w1;
② 再从w1出发,访问与w1相邻接的且未被访问过的任一
顶点w2;
③ 从w2出发,重复与步骤②类似的访问,直至遇到一个
所有邻接点均被访问过的顶点为止;
④ 沿刚才访问的次序,反向回到一个尚有邻接点未被访
问过的顶点,再从该顶点出发,重复与步骤③相类似
的访问,直到所有的被访问过的顶点的邻接顶点均被
访问过为止。
广度优先搜索(Breadth-first Search,BFS)
① 访问起始顶点v后,依次访问与v相邻接的所有顶点
w1, w2, …, wt;
② 再按w1, w2, …, wt的顺序,访问其中每一个顶点的
所有未被访问过的邻接顶点;对w1为:w11, w12, …,
w1m;…;对wt为:wt1, wt2, …, wtn等;
③ 再按w11, w12, …, w1m, w21, …, wt1, wt2, …, wtn的顺序,
去访问它们各自的未被访问过的邻接顶点。依次类
推,直到图中所有被访问过的顶点的邻接顶点都被
访问过为止。
2. 设计表示
(1)函数调用关系图
main→Initilized→CreateGraph→SetMark→DFS→BFS
(2)函数接口规格说明
void Initilized(Graph *graph) // graph指向的图的初始化
void CreateGraph(Graph *graph) //graph指向的图的创建图
void SetMark(Graph *graph) //设置graph指向的图的顶点访问标记
void DFS(Graph *graph,int v) //深度遍历graph指向的图的点amlist [v]
void BFS(Graph *graph,int u) //广度遍历graph指向的图的点amlist [v]
3. 实现注释 (即各项功能的实现程度)
程序缺乏健壮性。
4. 详细设计(主要函数)
【1】void Initilized(Graph *graph)//图的初始化
{
graph=(Graph *)malloc (sizeof(Graph));
graph->numberOfVerts =0;
graph->numberOfEerts =0;
}
【2】void CreateGraph(Graph *graph)//图的创建图
{
ENode *p,*q,*e;
int i;
printf("请输入连通无向图的顶点数和边数 例如 3 3:\n");
scanf("%d %d",&graph->numberOfVerts,&graph->numberOfEerts);
for(i=1;i<=graph->numberOfVerts;i++)
{
printf("请输入第%d个顶点的信息:\n",i);
scanf("%s",&graph->amlist [i].data );
graph->amlist [i].number =i;
graph->amlist[i].firstedge=NULL;
graph->amlist [i].mark =0;
}
for(i=1;i<=graph->numberOfEerts;i++)
{
p=(ENode *)malloc(sizeof(ENode));
printf("请输入每条边的信息(编号小的在前 例如1 3回车1 2回车2 3)\n");
scanf("%d %d",&p->ivex,&p->jvex);
p->ilink =p->jlink =NULL;
if(graph->amlist [p->ivex ].firstedge==NULL )
graph->amlist [p->ivex ].firstedge =p;
else
{
q=graph->amlist [p->ivex ].firstedge ;
while(q!=NULL)
{
e=q;
if(q->ivex ==p->ivex )
q=q->ilink ;
else
q=q->jlink ;
}
if(e->ivex ==p->ivex )
e->ilink =p;
else
e->jlink =p;
}
if(graph->amlist [p->jvex ].firstedge==NULL )
graph->amlist [p->jvex ].firstedge =p;
else
{
q=graph->amlist [p->jvex ].firstedge ;
while(q!=NULL)
{
e=q;
if(q->ivex ==p->ivex )
q=q->ilink ;
else
q=q->jlink ;
}
if(e->ivex ==p->ivex )
e->ilink =p;
else
e->jlink =p;
}
}
}
【3】void SetMark(Graph *graph)//设置访问标记
{
int i;
for(i=1;i<=graph->numberOfVerts ;i++)
graph->amlist [i].mark =0;
}
【4】void DFS(Graph *graph,int v)//深度遍历
{
ENode *p;
printf("%d ",v);
graph->amlist [v].mark =1;
p=graph->amlist [v].firstedge ;
while(p!=NULL)
{
if(p->ivex ==v)
{
if(graph->amlist [p->jvex ].mark ==0)
{
printf("<%d,%d>\n",p->ivex ,p->jvex );
DFS(graph,p->jvex );
}
p=p->ilink ;
}
else
{
if(graph->amlist [p->ivex].mark ==0)
{
printf("<%d,%d>\n",p->jvex ,p->ivex );
DFS(graph,p->ivex );
}
p=p->jlink ;
}
}
}
【5】void BFS(Graph *graph,int u)//广度遍历
{
LinkQueue Q;
ENode *p;
InitQueue(&Q);
printf("%d ",u);
graph->amlist [u].mark =1;
QueueAppend(&Q,u);
while(Q.front !=Q.rear )
{
QueueDelete(&Q,&u);
p=graph->amlist [u].firstedge ;
while(p!=NULL)
{
if(p->ivex ==u)
{
if(graph->amlist [p->jvex ].mark ==0)
{
QueueAppend(&Q,p->jvex );
graph->amlist [p->jvex ].mark =1;
printf("<%d,%d>\n",p->ivex ,p->jvex );
printf("%d ",p->jvex );
}
p=p->ilink ;
}
else
{
if(graph->amlist [p->ivex ].mark ==0)
{
QueueAppend(&Q,p->ivex );
graph->amlist [p->ivex ].mark =1;
printf("<%d,%d>\n",p->jvex ,p->ivex );
printf("%d ",p->ivex );
}
p=p->jlink ;
}
}
}
}
三、调试分析
1.调试过程中遇到的主要问题是如何解决的;
调试过程中存在少许C语言的基础语法错误,经独立仔细观察和调试修改正确,最大的难题是将图中的各类算法实践要运用上几章节的内容,实现时需不断的温习以前的知识,出现多次错误。终于在自己独立多次多天修改下,终于完成。
2.对设计和编码的回顾讨论和分析;
总的来说,这个程序写的相当困难,虽然老师已经把大体算法思路都提到过。但是,由于算法和语法的知识掌握的太不牢固,对好多以前学的数据结构还不是特别熟悉,需要不断尝试与温习。所以,今后应该多温习多练习才好。
3.时间和空间复杂度的分析;
【1】:广度遍历算法 时间O(n),空间O(1)
【2】:深度遍历算法 时间O(n), 空间O(1)
4.改进设想;
程序能实现预期功能,只是其中的改进空间可能较大
【1】:图的构造函数
【2】:广度遍历算法
5.经验和体会等。
多动手编程,才能熟练灵活的掌握C语言基础知识,才能更好的理解掌握数据结构的精髓。从而避免基础语法错误,让代码变得更简洁高效。如此才能准确高效的解决问题。在今后的编程过程中要更注重代码的熟练掌握,多的温习代码思想,多的动手编程。
四、用户手册(即使用说明)
仅需按照提示的例子输入即可。若出错,则重新来过。
五、运行结果
运行环境:C-free
测试数据:
六、源程序清单
https://wenku.baidu.com/view/7b6254df640e52ea551810a6f524ccbff121cab5