昨天讲了图,睡着了,今天运动会学了一下,回来写了一道。题目如下:
看一下题目,就是用领接表构建一个图,再寻找是否有特定的路径。
邻接表也没什么好说的,每个顶点节点存储相连接的边的信息。那么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; } }
以上就是我的实现。