深度优先搜索(Breadth First Search),类似于树的层序遍历,搜索模型是队列,还是以下面的无向图为例:
实验环境是Ubuntu 14.04 x86
伪代码实现如下:
其中u
为
v
的先辈或父母。
BFS(G, s)
for each vertex u ∈ V [G] - {s} do color[u] ← WHITE d[u] ← ∞ π[u] ← NIL //除了源顶点s之外,第1-4行置每个顶点为白色,置每个顶点u的d[u]为无穷大,置每个顶点的父母为NIL。 color[s] ← GRAY // 将源顶点s置为灰色,这是因为在过程开始时,源顶点已被发现。 d[s] ← 0 π[s] ← NIL //将源顶点的父顶点置为NIL。 Q ← Ø ENQUEUE(Q, s) //第8、9行,初始化队列Q,使其仅含源顶点s。 while Q ≠ Ø do u ← DEQUEUE(Q) //确定队列头部Q头部的灰色顶点u,并将其从Q中去掉。 for each v ∈ Adj[u] //for循环考察u的邻接表中的每个顶点v do if color[v] = WHITE then color[v] ← GRAY d[v] ← d[u] + 1 π[v] ← u //u记为该顶点的父母 ENQUEUE(Q, v) //插入队列中 color[u] ← BLACK
队列推荐使用链式队列。
邻接表实现:
#include <stdio.h> #include <malloc.h> #define MAX_VERTEX_NUM 50 typedef char vertexType; typedef int edgeType; typedef int QueueElemType; /* 边表 */ typedef struct ArcNode { int adjIndex; struct ArcNode *nextArc; edgeType weight; }ArcNode; /* 顶点表 */ typedef struct VNode { vertexType data; ArcNode *firstArc; }VNode, AdjList[MAX_VERTEX_NUM]; /* 图结构 */ typedef struct { AdjList adjList; int vexNum; int edgeNum; }ALGraph; typedef struct QueueNode { QueueElemType data; struct QueueNode *next; }QueueNode; typedef struct { QueueNode *front; QueueNode *rear; }LinkQueue; int visit[MAX_VERTEX_NUM] = {0}; void initLinkQueue(LinkQueue *queue) { QueueNode *head = (QueueNode*)malloc(sizeof(QueueNode)); if(head == NULL) { printf("malloc failed\n"); return; } head->next = NULL; queue->front = queue->rear = head; return; } void insertLinkQueue(LinkQueue *queue, QueueElemType data) { QueueNode *newNode = (QueueNode *)malloc(sizeof(QueueNode)); if(NULL == newNode) { printf("malloc failed\n"); return; } newNode->data = data; newNode->next = NULL; queue->rear->next = newNode; queue->rear = newNode; return; } int deleteLinkQueue(LinkQueue *queue, QueueElemType *data) { QueueNode *p; if (queue->front == queue->rear) { printf("no element!\n"); return 0; } p = queue->front->next; *data = p->data; queue->front->next = p->next; if (p == queue->rear) { queue->rear = queue->front; } free(p); return 1; } void BFSTraverse(ALGraph G) { QueueElemType q; LinkQueue queue; ArcNode *adjEdge; int index = 0; initLinkQueue(&queue); for (int i = 0; i < G.vexNum; i++) { if (!visit[i]) { visit[i] = 1; printf("%c ", G.adjList[i].data); insertLinkQueue(&queue, i); while (deleteLinkQueue(&queue, &q)) { adjEdge = G.adjList[q].firstArc; while (adjEdge) { index = adjEdge->adjIndex; if (!visit[index]) { visit[index] = 1; printf("%c ", G.adjList[index].data); insertLinkQueue(&queue, index); } adjEdge = adjEdge->nextArc; } } } } } void CreateALGraph(ALGraph *G) { int i, j, k; ArcNode *e; int c; printf("输入顶点数和边数:\n"); scanf("%d %d", &G->vexNum, &G->edgeNum); setbuf(stdin, NULL); for (i = 0; i < G->vexNum; i++) { printf("输入顶点信息:\n"); scanf("%c", &G->adjList[i].data); G->adjList[i].firstArc = NULL; while((c = getchar()) != '\n' && c != EOF); } for (k = 0; k < G->edgeNum; k++) { printf("输入边(vi,vj)的顶点序号i,j:\n"); scanf("%d %d", &i, &j); while((c = getchar()) != '\n' && c != EOF); e = (ArcNode*)malloc(sizeof(ArcNode)); if (NULL == e) { return; } e->adjIndex = j; e->nextArc = G->adjList[i].firstArc; G->adjList[i].firstArc = e; // double direction copy e = (ArcNode *)malloc(sizeof(ArcNode)); if (NULL == e) { return; } e->adjIndex = i; e->nextArc = G->adjList[j].firstArc; G->adjList[j].firstArc = e; } } int main(int argc, char const *argv[]) { ALGraph G; CreateALGraph(&G); BFSTraverse(G); return 0; }
运行结果: A F B G E I C H D
邻接矩阵实现:
#include <stdio.h> #include <malloc.h> #define MAX_VERTEX_NUM 50 typedef char vertexType; typedef int edgeType; typedef int QueueElemType; typedef struct { vertexType vexs[MAX_VERTEX_NUM]; edgeType arc[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; int vexNum; int edgeNum; }Graph; typedef struct QueueNode { QueueElemType data; struct QueueNode *next; }QueueNode; typedef struct { QueueNode *front; QueueNode *rear; }LinkQueue; int visit[MAX_VERTEX_NUM] = {0}; void initLinkQueue(LinkQueue *queue) { QueueNode *head = (QueueNode*)malloc(sizeof(QueueNode)); if(head == NULL) { printf("malloc failed\n"); return; } head->next = NULL; queue->front = queue->rear = head; return; } void insertLinkQueue(LinkQueue *queue, QueueElemType data) { QueueNode *newNode = (QueueNode *)malloc(sizeof(QueueNode)); if(NULL == newNode) { printf("malloc failed\n"); return; } newNode->data = data; newNode->next = NULL; queue->rear->next = newNode; queue->rear = newNode; return; } int deleteLinkQueue(LinkQueue *queue, QueueElemType *data) { QueueNode *p; if (queue->front == queue->rear) { printf("no element!\n"); return 0; } p = queue->front->next; *data = p->data; queue->front->next = p->next; if (p == queue->rear) { queue->rear = queue->front; } free(p); return 1; } void CreateALGraph(Graph *G) { int i, j, k; int c; printf("输入顶点数和边数:\n"); scanf("%d %d", &G->vexNum, &G->edgeNum); setbuf(stdin, NULL); for (i = 0; i < G->vexNum; i++) { printf("输入第%d个顶点信息:\n", i + 1); scanf("%c", &G->vexs[i]); while((c = getchar()) != '\n' && c != EOF); } for (i = 0; i < G->vexNum; i++) { for (j = 0; j < G->vexNum; j++) { G->arc[i][j] = 0; } } for (k = 0; k < G->edgeNum; k++) { printf("输入边(vi,vj)的下标i,j:\n"); scanf("%d %d", &i, &j); while((c = getchar()) != '\n' && c != EOF); // set a default weight G->arc[i][j] = G->arc[j][i] = 1; } } void BFSTraverse(Graph G) { LinkQueue queue; QueueElemType q; initLinkQueue(&queue); for(int i = 0; i < G.vexNum; i++) { if (!visit[i]) { visit[i] = 1; printf("%c ", G.vexs[i]); insertLinkQueue(&queue, i); while (deleteLinkQueue(&queue, &q)) { for (int j = 0; j < G.vexNum; j++) { if (G.arc[q][j] == 1 && !visit[j]) { visit[j] = 1; printf("%c ", G.vexs[j]); insertLinkQueue(&queue, j); } } } } } } int main(int argc, char const *argv[]) { Graph G; CreateALGraph(&G); BFSTraverse(G); return 0; }
运行结果:A B F C G I E D H