图的广度优先遍历BFS(邻接矩阵实现)c语言
广度优先遍历也叫广度优先搜索(Breadth First Search)。
它的遍历规则:
- 先访问完当前顶点的所有邻接点。
- 先访问的顶点的邻接点先于后访问顶点的邻接点被访问。
算法思想:
使用队列的数据结构(FIFO (First In First Out)),将一个顶点加入队列,然后在队列中删除顶点,并且将该顶点相连的所有顶点依次加入队列中,再循环处理这些顶点,直至所有顶点均被访问。(类似树的层序遍历)
算法所需:
对队列的基本操作熟悉
代码实现如下:
#include<stdio.h> #include<stdlib.h> #define MAX 10 #define INFINITY 65535 #define TRUE 1 #define FALSE 0 typedef char VertexType; typedef int EdgeType; typedef int Boole; //布尔类型 存储TRUE FALSE Boole visited[MAX]; //访问标志数组 typedef int QElemType; //链队列的数据类型 typedef int Status; /*邻接矩阵结构*/ typedef struct { VertexType vexs[MAX]; //顶点表 EdgeType arc[MAX][MAX]; //邻接矩阵 可看作边表 int numVertexes,numEdges; //顶点数和边数 }MGraph; /*队列结构*/ typedef struct QNode { QElemType data; struct QNode *next; }QNode,*QueuePtr; typedef struct { QueuePtr front,rear; //队头队尾指针 }LinkQueue; //构造邻接矩阵 void create(MGraph *G) { int i,j,k,w; printf("请输入顶点数和边数: "); scanf("%d%d",&G->numVertexes,&G->numEdges); fflush(stdin); for(i=0;i<G->numVertexes;i++) //建立顶点表 { printf(" 第%d个顶点",i+1); scanf("%c",&G->vexs[i]); getchar(); } for(i=0;i<G->numVertexes;i++) //矩阵初始化 for(j=0;j<G->numVertexes;j++) G->arc[i][j]=INFINITY; for(k=0;k<G->numEdges;k++) { printf("输入边(Vi,Vj)的上下标i,j和权w(空格隔开):"); scanf("%d%d%d",&i,&j,&w); G->arc[i][j]=w; G->arc[j][i]=G->arc[i][j]; } } //输出邻接矩阵 void Output(MGraph *G) { int i,j,count=0; for(i=0;i<G->numVertexes;i++) printf(" %c",G->vexs[i]); printf(" "); for(i=0;i<G->numVertexes;i++) { printf("%4c",G->vexs[i]); for(j=0;j<G->numVertexes;j++) { printf(" %d",G->arc[i][j]); count++; if(count%G->numVertexes==0) printf(" "); } } } //创建空队列 Status InitQueue(LinkQueue &Q) { Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode)); if(!Q.front) exit(0); Q.front->next=NULL; return 1; } //入队列 //将s作为新元素加入队尾 Status EnQueue(LinkQueue &Q,int i) { QueuePtr s; s=(QueuePtr)malloc(sizeof(QNode)); if(!s) exit(0); s->data=i; s->next=NULL; Q.rear->next=s; Q.rear=s; return 1; } //检验是否为空 Status QueueEmpty(LinkQueue Q) { if(Q.front->next==NULL) return 0; else return 1; } //出队列 Status DeQueue(LinkQueue *Q,int *i) { QueuePtr p; if(Q->front==Q->rear) return 0; p=Q->front->next; //该写法值得商榷 //相当于p储存第一个结点 *i=p->data; Q->front->next=p->next; if(p==Q->rear) //若队头是队尾 ,删除后将rear指向头结点 Q->rear==Q->front; free(p); return 1; } /*广度遍历*/ void BFSTraverse(MGraph G) { int i,j; LinkQueue Q; for(i=0;i<G.numVertexes;i++) visited[i]=FALSE; InitQueue(Q); //&的用法?? 初始化队列 for(i=0;i<G.numVertexes;i++) { if(!visited[i]) //未访问过 该顶点 { visited[i]=TRUE; printf("%c->",G.vexs[i]); EnQueue(Q,i); //将其入队列 while(!QueueEmpty(Q)) { DeQueue(&Q,&i); //将队中元素出队列,赋值给i for(j=0;j<G.numVertexes;j++) { if(G.arc[i][j]==1&&!visited[j]) //其他顶点与该顶点存在边 且未访问过 { visited[j]=TRUE; printf("%c",G.vexs[j]); EnQueue(Q,j); //入队列 } } } } } } int main() { MGraph G; create(&G); printf("邻接矩阵数据如下: "); Output(&G); printf(" "); BFSTraverse(G); printf(" 图遍历完毕"); return 0; }
下一篇:
Java判断输入月份有多少天