与深度优先一样,这里只写非连通图的遍历(去掉BFSTraverse()之后就是连通图的广度优先算法)。
首先是预定义和类型定义:
#define OK 1
#define ERROR 0
#define MVNum 100
typedef int Status;
typedef char VerTexType;
typedef int ElemType;
typedef int OtherInfo;
typedef struct ArcNode{
int adjvex;
ArcNode *nextarc;
OtherInfo info;
}ArcNode;
typedef struct{
VerTexType data;
ArcNode *firstarc;
}VNode,Adjvex[MVNum];
typedef struct{
Adjvex vertices;
int vexnum, arcnum;
}ALGraph;
typedef struct QNode{
ElemType da;
QNode *next;
}QNode,*QueueList;
typedef struct{
QueueList front;
QueueList rear;
}LinkQueue;
并声明一个bool类型数组记录是否已经遍历:
bool visited[MVNum];
队列的操作:
Status InitQueue(LinkQueue *Q)
{
Q->front = (QNode *)malloc(sizeof(QNode));
if (!Q->front)
return ERROR;
Q->front->next = NULL;
Q->rear = Q->front;
return OK;
}
Status EnQueue(LinkQueue *Q, ElemType e)
{
QNode *p;
p = (QNode *)malloc(sizeof(QNode));
p->da = e;
p->next = NULL;
Q->rear->next = p;
Q->rear = Q->rear->next;
return OK;
}
Status DeQueue(LinkQueue *Q, ElemType *e)
{
QNode *p;
if (Q->rear == Q->front)
return ERROR;
p = Q->front->next;
*e = p->da;
Q->front->next = p->next;
if (p == Q->rear)
Q->rear = Q->front;
free(p);
return OK;
}
创建图:
int LocateVex(ALGraph *G, VerTexType v)
{
int i;
for (i = 0; i < (G->vexnum); i++)
{
if (v == G->vertices[i].data)
return i;
}
}
Status CreateUDG(ALGraph *G)
{
VerTexType v1, v2;
ArcNode *p1, *p2;
int i, j, k;
printf("输入总节点数、总边数:");
scanf("%d %d", &G->vexnum, &G->arcnum);
fflush(stdin);
printf("输入所有节点的值:");
for (i = 0; i < G->vexnum; i++)
{
scanf("%c", &G->vertices[i].data);
G->vertices[i].firstarc = NULL;
visited[i] = false;
}
for (k = 0; k < G->arcnum; k++)
{
fflush(stdin);
printf("输入一条边的两个顶点值:");
scanf("%c %c", &v1, &v2);
i = LocateVex(G, v1);
j = LocateVex(G, v2);
p1 = (ArcNode *)malloc(sizeof(ArcNode));
p1->adjvex = j;
p1->nextarc = G->vertices[i].firstarc;
G->vertices[i].firstarc = p1;
p2 = (ArcNode *)malloc(sizeof(ArcNode));
p2->adjvex = i;
p2->nextarc = G->vertices[j].firstarc;
G->vertices[j].firstarc = p2;
}
return OK;
}
广度优先算法:
void BFS(ALGraph G, int v)
{
int w;
LinkQueue Q;
ArcNode *p;
printf("%c ", G.vertices[v].data);
visited[v] = true;
InitQueue(&Q);
EnQueue(&Q, v);
while (Q.front != Q.rear)
{
DeQueue(&Q, &w);
p = G.vertices[w].firstarc;
while (p)
{
if (!visited[p->adjvex])
{
printf("%c ", G.vertices[p->adjvex].data);
visited[p->adjvex] = true;
EnQueue(&Q, p->adjvex);
}
p = p->nextarc;
}
}
}
先遍历初始节点v,并在visited[]数组中标记为已经遍历,之后将v入队。当队列不为空的时候,表示并未完全遍历,则先让队头元素出队,遍历与其有关联的节点:让p指向地一条边,并检测该边的另一个节点是否已经遍历,如果尚未遍历,则遍历,标记为已经遍历,并将其序号入队。然后让p指向下一条边。直到p为空。
非联通图的广度优先遍历:
void BFSTraverse(ALGraph G)
{
int i;
for (i = 0; i < G.vexnum; i++)
{
if (!visited[i])
BFS(G, i);
}
}
加入main()函数:
int main(void)
{
ALGraph G;
CreateUDG(&G);
BFSTraverse(G);
printf("\n");
return 0;
}