数据结构图的遍历实验报告.docx
《数据结构图的遍历实验报告.docx》由会员分享,可在线阅读,更多相关《数据结构图的遍历实验报告.docx(9页珍藏版)》请在冰豆网上搜索。
数据结构图的遍历实验报告
实验项目名称:
图的遍历
一、实验目的
应用所学的知识分析问题、解决问题,学会用建立图并对其进行遍历,提高实际编程能力及程序调试能力。
二、实验内容
问题描述:
建立有向图,并用深度优先搜索和广度优先搜素。
输入图中节点的个数和边的个数,能够打印出用邻接表或邻接矩阵表示的图的储存结构。
三、实验仪器与设备
计算机,Code:
:
Blocks。
四、实验原理
用邻接表存储一个图,递归方法深度搜索和用队列进行广度搜索,并输出遍历的结果。
5、实验程序及结果
#defineINFINITY10000/*无穷大*/
#defineMAX_VERTEX_NUM40
#defineMAX40
#include
#include
#include
#include
typedefstructArCell{
intadj;
}ArCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedefstruct
{charname[20];
}infotype;
typedefstruct
{infotypevexs[MAX_VERTEX_NUM];
AdjMatrixarcs;
intvexnum,arcnum;
}MGraph;
intLocateVex(MGraph*G,char*v)
{intc=-1,i;
for(i=0;ivexnum;i++)
if(strcmp(v,G->vexs[i].name)==0)
{c=i;break;}
returnc;}
MGraph*CreatUDN(MGraph*G)//初始化图,接受用户输入
{
inti,j,k,w;
charv1[20],v2[20];
printf("请输入图的顶点数,弧数:
");
scanf("%d%d",&G->vexnum,&G->arcnum);
printf("结点名字:
\n");
for(i=0;ivexnum;i++){
printf("No.%d:
",i+1);
scanf("%s",G->vexs[i].name);}
for(i=0;ivexnum;i++)
for(j=0;jvexnum;j++)
G->arcs[i][j].adj=INFINITY;
printf("请输入一条边依附的两个顶点和权值:
\n");
for(k=0;karcnum;k++)
{printf("第%d条边:
\n",k+1);
printf("起始结点:
");
scanf("%s",v1);
printf("结束结点:
");
scanf("%s",v2);
//printf("边的权值:
");
//scanf("%d",&w);
i=LocateVex(G,v1);j=LocateVex(G,v2);
if(i>=0&&j>=0){
//G->arcs[i][j].adj=w;
G->arcs[j][i]=G->arcs[i][j];
}}
returnG;
}
intFirstAdjVex(MGraph*G,intv)
{
inti;
if(v<=0&&vvexnum){//v合理
for(i=0;ivexnum;i++)
if(G->arcs[v][i].adj!
=INFINITY)
returni;
}
return-1;
}
voidVisitFunc(MGraph*G,intv)
{
printf("%s",G->vexs[v].name);
}
intNextAdjVex(MGraph*G,intv,intw)
{
intk;
if(v>=0&&vvexnum&&w>=0&&wvexnum)//v,w合理
{
for(k=w+1;kvexnum;k++)
if(G->arcs[v][k].adj!
=INFINITY)
returnk;
}
return-1;
}
intvisited[MAX];
voidDFS(MGraph*G,intv)//从第v个顶点出发递归地深度优先遍历图G
{
intw;
visited[v]=1;
VisitFunc(G,v);//访问第v个结点
for(w=FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,v,w))
if(!
visited[w]){
DFS(G,w);
printf("%d",G->arcs[v][w]);}
}
voidDFSTraverse(MGraph*G,char*s)//深度优先遍历
{intv,k;
for(v=0;vvexnum;v++)
visited[v]=0;
k=LocateVex(G,s);
if(k>=0&&kvexnum){
for(v=k;v>=0;v--){
if(!
visited[v])
DFS(G,v);}
for(v=k+1;vvexnum;v++)
if(!
visited[v])
DFS(G,v);
}
}
typedefstructQnode
{
intvexnum;
structQnode*next;
}QNode,*QueuePtr;
typedefstruct
{
QueuePtrfront;
QueuePtrrear;
}LinkQueue;
intInitQueue(LinkQueue*Q)
{
Q->front=Q->rear=(QueuePtr)malloc(sizeof(QNode));
if(!
Q->front)exit(0);
Q->front->next=NULL;
return1;
}
voidEnQueue(LinkQueue*Q,inta)
{
QueuePtrp;
p=(QueuePtr)malloc(sizeof(QNode));
if(!
p)exit(0);
p->vexnum=a;
p->next=NULL;
Q->rear->next=p;
Q->rear=p;
}
intDeQueue(LinkQueue*Q,int*v)
{QueuePtrp;
if(Q->front==Q->rear)
{printf("结点不存在!
\n");exit(0);}
p=Q->front->next;
*v=p->vexnum;
Q->front->next=p->next;
if(Q->rear==p)
Q->front=Q->rear;
return*v;
}
intQueueEmpty(LinkQueue*Q)
{
if(Q->rear==Q->front)
return0;
return1;
}
intVisited[MAX];
voidBFSTraverse(MGraph*G,char*str)//广度优先遍历
{intw,u,v,k;
LinkQueueQ,q;
for(v=0;vvexnum;v++)Visited[v]=0;
InitQueue(&Q);InitQueue(&q);
k=LocateVex(G,str);
for(v=k;v>=0;v--)
if(!
Visited[v])
{
Visited[v]=1;
VisitFunc(G,v);
EnQueue(&Q,v);//v入队
while(!
QueueEmpty(&Q))
{
DeQueue(&Q,&u);//出队
for(w=FirstAdjVex(G,u);w>=0;w=NextAdjVex(G,u,w))
if(!
Visited[w])
{
Visited[w]=1;
VisitFunc(G,v);
EnQueue(&Q,w);
}
}
}
for(v=k+1;vvexnum;v++)
if(!
Visited[v])
{
Visited[v]=1;
VisitFunc(G,v);
EnQueue(&Q,v);//v入队
while(!
QueueEmpty(&Q))
{
DeQueue(&Q,&u);//出队
for(w=FirstAdjVex(G,u);w>=0;w=NextAdjVex(G,u,w))
if(!
Visited[w])
{
Visited[w]=1;
VisitFunc(G,v);
EnQueue(&Q,w);
}
}
}
}
voidmain()
{
MGraph*G,b;
charv[10];
G=CreatUDN(&b);
printf("请输入起始结点名称:
");
scanf("%s",v);
printf("\n深度优先遍历:
\n");
DFSTraverse(G,v);
printf("\n广度优先遍历:
\n");
BFSTraverse(G,v);
getch();
}
6、实验总结
实验要求输入图中节点的个数和边的个数,能够打印出用邻接表或邻接矩阵表示的图的储存结构。
在设计中其中用邻接表表示的节点的值只能是数字,但用邻接矩阵表示的节点的值可以是字母。
但用邻接表形式要相对简单一些。
深度优先采取的递归思想。
首先,将从起点,沿某条边,顺势遍历下去,直到不能继续遍历下去。
这时,又从起点的另一结点开始,遍历下去。
如此往复,知道将所有结点遍历完。
广度优先得使用队列。
首先,将起点入队,并标为已访问。
进入循环,当队列不为空时,出队,输出,并将与出队的元素相邻的且未访问的结点全部放入队列,标为已访问。
一次循环,只有一个结点出队,大于等于0个结点入队。
实验程序中大量使用了循环,使时间复杂度加大了很多,因此此程序比较适合于密集图,应用于稀疏图中就有点浪费时间了。