放假前课上讲了广度搜索,这两天一直在复习电路基础,今天晚上才把这道题给写了,题目如下:
这个题就是把上一道题的深度变成广度了,输入构建图都没有变,所以我就稍微改了一下上次的代码,加了几个队列函数。
先把3 3 1 2 3 1 2 1 3 2 1构建为下面的图:
广度搜索其实是一种队列的操作,每次取队列头,把队列头边表的所有节点入队,然后把队列头出队列,循环直到队列头是所找节点或队列空(没找到),寻找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; }; struct edgeNodeQueue { int nodeQueue[3000]; int n; }; 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 breadthFirstSearch (char flags[],struct graphList *gList,int cur,int find,struct edgeNodeQueue *queue); void clearQueue(struct edgeNodeQueue *queue); void pushQueue (struct edgeNodeQueue *queue,int vex); void unshiftQueue (struct edgeNodeQueue *queue); 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}; struct edgeNodeQueue queue; clearQueue (&queue); if (breadthFirstSearch (flags,gList,cur,find,&queue)) { printf ("yes"); } else { printf ("no"); } } int breadthFirstSearch (char flags[],struct graphList *gList,int cur,int find,struct edgeNodeQueue *queue) { int headVex; struct edgeNode *p; headVex=cur; pushQueue(queue,headVex); while (queue->n>=0) { headVex=queue->nodeQueue[0]; if (find==gList->vex[headVex].vex) { return 1; } if (flags[headVex]==0) { flags[headVex]=1; p=gList->vex[headVex].head; while (p) { pushQueue(queue,p->headVex); p=p->next; } } unshiftQueue(queue); } return 0; } void clearQueue(struct edgeNodeQueue *queue) { int i; for (i=0;i<=2999;i++) { queue->nodeQueue[i]=0; } queue->n=-1; } void pushQueue (struct edgeNodeQueue *queue,int vex) { (queue->n)++; queue->nodeQueue[queue->n]=vex; } void unshiftQueue (struct edgeNodeQueue *queue) { int i; for (i=1;i<=queue->n;i++) { queue->nodeQueue[i-1]=queue->nodeQueue[i]; } (queue->n)--; }
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};//初始化路径记录数组 struct edgeNodeQueue queue; clearQueue (&queue);//清空队列 if (breadthFirstSearch (flags,gList,cur,find,&queue)) { printf ("yes");//找到 } else { printf ("no");//未找到 } }
int breadthFirstSearch (char flags[],struct graphList *gList,int cur,int find,struct edgeNodeQueue *queue) { int headVex; struct edgeNode *p; headVex=cur; pushQueue(queue,headVex);//循环准备 while (queue->n>=0)//进入循环,队空结束循环 { headVex=queue->nodeQueue[0];//队列头 if (find==gList->vex[headVex].vex)//若找到,返回1 { return 1; } if (flags[headVex]==0)//若此节点未走过 { flags[headVex]=1;//标记为走过 p=gList->vex[headVex].head; while (p)//将边表中每一个节点入队 { pushQueue(queue,p->headVex); p=p->next; } } unshiftQueue(queue);//队列头出队列 } return 0;//搜索完未找到,返回0 }
void clearQueue(struct edgeNodeQueue *queue) { int i; for (i=0;i<=2999;i++)//遍历清空 { queue->nodeQueue[i]=0; } queue->n=-1; }
void pushQueue (struct edgeNodeQueue *queue,int vex) { (queue->n)++;//队列个数增加 queue->nodeQueue[queue->n]=vex;//入队 }
void unshiftQueue (struct edgeNodeQueue *queue) { int i; for (i=1;i<=queue->n;i++)//队列头出队列 { queue->nodeQueue[i-1]=queue->nodeQueue[i]; } (queue->n)--;//队列个数减少 }
以上就是我的实现。