深度優先搜索(Depth First Search),相似於樹的前序遍歷,搜索模型是棧,運用的是遞歸思想,如下面的無向圖爲例:html
僞代碼實現以下:shell
其中u 爲 v 的先輩或父母。ubuntu
DFS(G)spa
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)code
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 x86htm
鄰接表實現:blog
#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