基本思想
1、从图中某个顶点V0出发,并访问此顶点;
2、从V0出发,访问V0的各个未曾访问的邻接点W1,W2,…,Wk;然后,依次从W1,W2,…,Wk出发访问各自未被访问的邻接点;
3、重复步骤2,直到全部顶点都被访问为止。
类似于树的按层次遍历,也就是一层一层地遍历,图的广度优先遍历从图中的某个结点出发,访问它的邻结点再访问邻结点的邻结点,由近及远。
如上图:从A出发,依次访问A结点的邻接点B、C、D,再访问B的邻接E,再访问C的邻接点F,左边访问完后,访问右边D的邻结点G和H,再访问G的邻接点 I, 至此所有的结点都已访问,遍历过程结束。遍历顺序为:
A->B->C->D->E->F->G->H->I
这里需要借助一个辅助的队列和来暂时存放已经访问过的结点,和
访问标志数组。
C语言代码:
#include<stdio.h>
#include<stdlib.h>
#define MaxVex 20
typedef char Vertex;
typedef struct SStation //接邻结点结构
{
int adjvex; //该边所指的顶点的位置
int weight; //权值,路的距离
struct SStation *next;
}StationNode;
typedef struct
{
Vertex data; //顶点信息,如站点名称
StationNode *firstedge; //指向第一条依附该顶点的弧的指针
}VNode,Vex[MaxVex];
typedef struct{
Vex vertices; //邻接表
bool visited[MaxVex]; //访问标志数组
int n,e; //顶点数和边数
}ALGraph;
//队列定义及相关操作(广度遍历会用到此循环队列)
typedef struct LoopQueue
{
int data[MaxVex];
int front,rear;
}Queue;
void InitQueue(Queue &Q)
{//初始化队列
Q.front = Q.rear = 0;
}
bool QueueFull(Queue &Q)
{//判断队满
if((Q.rear+1)%MaxVex == Q.front)
return true;
else
return false;
}
bool QueueEmpty(Queue &Q)
{//判断队空
if(Q.front == Q.rear)
return true;
else
return false;
}
void EnQueue(Queue &Q,int e)
{//入队
if(!QueueFull(Q))
{
Q.data[Q.rear] = e;
Q.rear = (Q.rear+1)%MaxVex;
}
}
void DeQueue(Queue &Q,int &e)
{//出队列
if(!QueueEmpty(Q))
{
e = Q.data[Q.front];
Q.front = (Q.front+1)%MaxVex;
}
}
void InitVexs(ALGraph &G)
{//建立顶点表
int i;
printf("建立顶点表,请输入顶点个数: ");
scanf("%d",&(G.n));
for(i=0; i<G.n; i++)
{
printf("\n请输入第%d个顶点:",i+1);
fflush(stdin);
G.vertices[i].data = getchar();
G.vertices[i].firstedge = NULL;
}
}
void InitEdge(ALGraph &G)
{//建立边表
StationNode *s;
int i,j,k,w;
fflush(stdin);
printf("建立边表,请输入边数: ");
scanf("%d",&(G.e));
for(k=0;k<G.e;k++)
{
fflush(stdin);
printf("\n读入(vi-vj)的顶点对序号和权值,中间用','隔开:"); //新建邻接结点
scanf("%d,%d",&i,&j,&w);
s = (StationNode*)malloc(sizeof(StationNode));
s->adjvex = j;
s->weight = w;
s->next = NULL;
if(!G.vertices[i].firstedge)
G.vertices[i].firstedge = s; //接在表头
else
{
StationNode *p = G.vertices[i].firstedge;
while(p->next)
p = p->next;
p->next = s;
}
}
}
void Visit(ALGraph &G,int i)
{
printf("%c->",G.vertices[i].data);
G.visited[i] = true;
}
void BFSTraverse(ALGraph &G)
{//广度优先非递归遍历图,借助队列和访问标志数组
int j,u;
Queue Q;
InitQueue(Q);
for(j=0; j<G.n; j++)
G.visited[j] = false; //初始时默认所有顶点都未访问过
for(j=0; j<G.n; j++)
if(!G.visited[j]) //序号为j未的顶点未访问过
{
Visit(G,j);
EnQueue(Q,j); //结点j入队列
while(!QueueEmpty(Q))
{
DeQueue(Q,u); //队头元素出队并置为u
for(StationNode *p = G.vertices[u].firstedge; p != NULL; p=p->next)
if(!G.visited[p->adjvex])
{
Visit(G,p->adjvex);
EnQueue(Q,p->adjvex);
}//if
}//while
} //if
}//BFSTraverse
int main()
{
ALGraph G;
InitVexs(G);
InitEdge(G);
printf("广度优先遍历结果: ");
BFSTraverse(G);
system("PAUSE");
return 0;
}