昨天讲了图,睡着了,今天运动会学了一下,回来写了一道。题目如下:
看一下题目,就是用领接表构建一个图,再寻找是否有特定的路径。
邻接表也没什么好说的,每个顶点节点存储相连接的边的信息。那么3 3 1 2 3 1 2 1 3 2 1可以构建下面的图:
深度搜索中,我使用了回溯和递归,记录下已走过的顶点,避免走进死循环,若找到路径,直接返回1,否则返回0,以便后续的输出,寻找1 3的步骤如下:
以下是我的实现:
#include <stdio.h>
#include <stdlib.h>
struct edgeNode
{
int headVex;
struct edgeNode *next;
};
struct vexNode
{
int vex;
struct edgeNode *head;
};
struct graphList
{
struct vexNode vex[3000];
int vexNum;
int edgeNum;
};
void run ();
void createNewGraphList (struct graphList *gList);
void clearVexNodes (struct graphList *gList);
int findVex (int vex,struct graphList *gList);
void createNewEdgeNode (int n,struct graphList *gList);
void existWay (struct graphList *gList);
int depthFirstSearch (char flags[],struct graphList *gList,int cur,int find);
int main()
{
run ();
return 0;
}
void run ()
{
struct graphList gList;
createNewGraphList (&gList);
existWay (&gList);
}
void createNewGraphList (struct graphList *gList)
{
scanf ("%d%d",&(gList->vexNum),&(gList->edgeNum));
clearVexNodes (gList);
int i;
for (i=0;i<gList->vexNum;i++)
{
scanf ("%d",&(gList->vex[i].vex));
}
int vex,n;
for (i=0;i<gList->edgeNum;i++)
{
scanf ("%d",&vex);
n=findVex (vex,gList);
createNewEdgeNode (n,gList);
}
}
void clearVexNodes (struct graphList *gList)
{
int i;
for (i=0;i<gList->vexNum;i++)
{
gList->vex[i].vex=0;
gList->vex[i].head=NULL;
}
}
int findVex (int vex,struct graphList *gList)
{
int i;
for (i=0;i<gList->vexNum;i++)
{
if (vex==gList->vex[i].vex)
{
return i;
}
}
return -1;
}
void createNewEdgeNode (int n,struct graphList *gList)
{
struct edgeNode *p,*q;
int vex;
p=(struct edgeNode *)malloc(sizeof(struct edgeNode));
scanf ("%d",&vex);
p->headVex=findVex (vex,gList);
p->next=NULL;
if (gList->vex[n].head==NULL)
{
gList->vex[n].head=p;
}
else
{
q=gList->vex[n].head;
while (q->next)
{
q=q->next;
}
q->next=p;
}
}
void existWay (struct graphList *gList)
{
int vi,cur,find;
scanf ("%d%d",&vi,&find);
cur=findVex (vi,gList);
char flags[3000]={0};
if (depthFirstSearch (flags,gList,cur,find))
{
printf ("yes");
}
else
{
printf ("no");
}
}
int depthFirstSearch (char flags[],struct graphList *gList,int cur,int find)
{
struct edgeNode *p;
int nextCur;
if (gList->vex[cur].vex==find)
{
return 1;
}
else
{
flags[cur]=1;
p=gList->vex[cur].head;
while (p)
{
if (!flags[p->headVex])
{
nextCur=p->headVex;
if (depthFirstSearch (flags,gList,nextCur,find))
{
return 1;
}
}
p=p->next;
}
flags[cur]=0;
return 0;
}
}
以下是个函数的注释:
void run ()
{
struct graphList gList;
createNewGraphList (&gList);//创建图
existWay (&gList);//是否存在路径
}
void createNewGraphList (struct graphList *gList)
{
scanf ("%d%d",&(gList->vexNum),&(gList->edgeNum));//输入顶点数,边数
clearVexNodes (gList);//清空所有顶点节点
int i;
for (i=0;i<gList->vexNum;i++)//遍历输入顶点
{
scanf ("%d",&(gList->vex[i].vex));
}
int vex,n;
for (i=0;i<gList->edgeNum;i++)//遍历构建边表
{
scanf ("%d",&vex);//输入边尾(箭头尾,不是箭头尖)
n=findVex (vex,gList);//得到边尾节点的位置
createNewEdgeNode (n,gList);//在边尾的表中创建新的边节点
}
}
void clearVexNodes (struct graphList *gList)
{
int i;
for (i=0;i<gList->vexNum;i++)//遍历清空
{
gList->vex[i].vex=0;
gList->vex[i].head=NULL;
}
}
int findVex (int vex,struct graphList *gList)
{
int i;
for (i=0;i<gList->vexNum;i++)//遍历寻找
{
if (vex==gList->vex[i].vex)//若找到就返回位置
{
return i;
}
}
return -1;//否则返回-1
}
void createNewEdgeNode (int n,struct graphList *gList)
{
struct edgeNode *p,*q;
int vex;
p=(struct edgeNode *)malloc(sizeof(struct edgeNode));//创建边节点
scanf ("%d",&vex);
p->headVex=findVex (vex,gList);//存入边头节点的位置
p->next=NULL;//next设为空
if (gList->vex[n].head==NULL)//若该顶点节点的边表为空
{
gList->vex[n].head=p;//表头就是新边节点
}
else//若不空
{
q=gList->vex[n].head;
while (q->next)//找到最后一个边节点
{
q=q->next;
}
q->next=p;//加入新边节点
}
}
void existWay (struct graphList *gList)
{
int vi,cur,find;
scanf ("%d%d",&vi,&find);//输入寻找的路径起点和终点
cur=findVex (vi,gList);//起点的位置
char flags[3000]={0};//初始化路径记录数组
if (depthFirstSearch (flags,gList,cur,find))
{
printf ("yes");//若找到
}
else
{
printf ("no");//若未找到
}
}
int depthFirstSearch (char flags[],struct graphList *gList,int cur,int find)
{
struct edgeNode *p;
int nextCur;
if (gList->vex[cur].vex==find)//若当前节点是所找节点,返回1
{
return 1;
}
else
{
flags[cur]=1;//记录当前顶点走过
p=gList->vex[cur].head;
while (p)//遍历所有边节点
{
if (!flags[p->headVex])//若未走过
{
nextCur=p->headVex;
if (depthFirstSearch (flags,gList,nextCur,find))//递归寻找,若以此顶点找到,返回1,剩下路径不找了
{
return 1;
}
}
p=p->next;
}
flags[cur]=0;//未找到,当前顶点标记未走过,返回上一顶点
return 0;
}
}
以上就是我的实现。