深度优先搜索(Depth First Search),类似于树的前序遍历,搜索模型是栈,运用的是递归思想,以下面的无向图为例:
伪代码实现如下:
其中u 为 v 的先辈或父母。
DFS(G)
for each vertex u ∈ V [G] do color[u] ← WHITE π[u] ← NIL //第1-3行,把所有顶点置为白色,所有π 域被初始化为NIL。 time ← 0 //复位时间计数器 for each vertex u ∈ V [G] do if color[u] = WHITE then DFS-VISIT(u) //调用DFS-VISIT访问u,u成为深度优先森林中一棵新的树 //第5-7行,依次检索V中的顶点,发现白色顶点时,调用DFS-VISIT访问该顶点。每个顶点u 都对应于一个发现时刻d[u]和一个完成时刻f[u]。
DFS-VISIT(u)
color[u] ← GRAY time ← time +1 d[u] ← time //记录u被发现的时间 for each v ∈ Adj[u] //检查并访问 u 的每一个邻接点 v do if color[v] = WHITE //如果v 为白色,则递归访问v。 then π[v] ← u //置u为 v的先辈 DFS-VISIT(v) color[u] ← BLACK //u 置为黑色,表示u及其邻接点都已访问完成 f [u] ← time ← time +1 //访问完成时间记录在f[u]中。
实验环境为ubuntu14.04 x86
邻接表实现:
#include <stdio.h> #include <malloc.h> #define MAX_VERTEX_NUM 50 typedef char vertexType; typedef int edgeType; /* 边表 */ typedef struct ArcNode { int adjIndex; 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; int visit[MAX_VERTEX_NUM] = {0}; void DFS(ALGraph *G, int i) { visit[i] = 1; printf("%c ", G->adjList[i].data); ArcNode *arcNodePt = G->adjList[i].firstArc; while (arcNodePt) { if (!visit[arcNodePt->adjIndex]) { DFS(G, arcNodePt->adjIndex); } arcNodePt = arcNodePt->nextArc; } // printf("recursion back\n"); } void DFSTraverse(ALGraph *G) { int i; // for (i = 0; i < G->vexNum; i++) // { // visit[i] = 0; // } for (i = 0; i < G->vexNum; i++) { if (!visit[i]) { DFS(G, i); } } } 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); DFSTraverse(&G); return 0; }
运行结果: A F G H E D I C B (与输入顺序有关)
邻接矩阵实现:
#include <stdio.h> #include <malloc.h> #define MAX_VERTEX_NUM 50 typedef char vertexType; typedef int edgeType; typedef struct { vertexType vexs[MAX_VERTEX_NUM]; edgeType arc[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; int vexNum; int edgeNum; }Graph; int visit[MAX_VERTEX_NUM] = {0}; 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 DFS(Graph G, int i) { visit[i] = 1; printf("%c ", G.vexs[i]); for (int j = 0; j < G.vexNum; j++) { if (G.arc[i][j] == 1 && !visit[j]) { DFS(G, j); } } } void DFSTraverse(Graph G) { for (int i = 0; i < G.vexNum; i++) { if (!visit[i]) { DFS(G, i); } } } int main(int argc, char const *argv[]) { Graph G; CreateALGraph(&G); DFSTraverse(G); return 0; }
运行结果: A B C D E F G H I