圖,就是由一些小圓點(稱爲頂點)和鏈接這些小圓點的直線(稱爲邊)組成的。例如:數組
上圖是由五個頂點(編號爲一、二、三、四、5)和五條邊(1-二、1-三、1-五、2-四、3-5)組成。spa
如今咱們從1號頂點開始遍歷這個圖(遍歷指的是把每個頂點都訪問一次)。使用深度優先搜索來遍歷這個圖咱們將獲得如下結果:code
在此我想用一句話來形容 「一路走到頭,不撞牆不回頭」。blog
顯而易見,深度優先搜索遍歷是沿着圖的某一條分支遍歷直到末端,而後回溯,再沿着另外一條進行一樣的遍歷,直到全部的頂點都被訪問過爲止。get
那麼問題來了,該如何實現這一過程呢?io
首先,咱們來解決如何存儲一個圖的問題。最經常使用的方法是使用一個二維數組e來存儲,以下:class
上圖二維數組中第 i 行第 j 列表示的就是頂點 i 到頂點 j 是否有邊。1 表示有邊,∞ 表示沒有邊,0 表示本身到本身(i=j)。這種存儲圖的方法稱爲圖的鄰接矩陣存儲法。變量
同時咱們發現:這個二維數組是沿着主對角線對稱的,所以上面這個圖是無向圖。無向圖指的是圖的邊沒有方向,例如邊1-5表示,1號頂點能夠到5號頂點,5號頂點也能夠到達1號頂點。搜索
void dfs(int cur)//cur是當前所在的頂點編號 { printf("%d ",cur); sum++; //每訪問一個頂點sum就加1 if(sum==n) return; //全部的頂點都已經訪問過則直接退出 for(i=1;i<=n;i++) //從1號頂點到n號頂點依次嘗試,看哪些頂點與當前頂點cur有邊相連 { //判斷當前頂點cur到頂點i是否有邊,並判斷頂點i是否已訪問過 if(e[cur][i]==1 && book[i]==0) { book[i]==1; //標記頂點i已經訪問過 dfs(i); //從頂點i再出發繼續遍歷 } } return; }
在上面的代碼中變量cur存儲的是當前正在遍歷的頂點,二維數組e存儲的就是圖的邊(鄰接矩陣),數組 book 用來記錄哪些頂點已經訪問過,變量 sum 用來記錄已經訪問過多少個頂點,變量 n 存儲的是圖的頂點的總個數。完整代碼以下:遍歷
#include<stdio.h> int book[101],sum,n,e[101][101]; void dfs(int cur)//cur是當前所在的頂點編號 { int i; printf("%d ",cur); sum++; //每訪問一個頂點sum就加1 if(sum==n) return; //全部的頂點都已經訪問過則直接退出 for(i=1;i<=n;i++) //從1號頂點到n號頂點依次嘗試,看哪些頂點與當前頂點cur有邊相連 { //判斷當前頂點cur到頂點i是否有邊,並判斷頂點i是否已訪問過 if(e[cur][i]==1 && book[i]==0) { book[i]==1; //標記頂點i已經訪問過 dfs(i); //從頂點i再出發繼續遍歷 } } return; } int main() { int i,j,m,a,b; scanf("%d %d",&n,&m); for(i=1;i<=n;i++) //初始化二維矩陣 for(j=1;j<=n;j++) if(i == j) e[i][j]=0; else e[i][j]=99999999; //在這裏假設99999999爲正無窮 //讀入頂點之間的邊 for(i=1;i<=m;i++) { scanf("%d %d",&a,&b); e[a][b] = 1; e[b][a] = 1;//這裏是無向圖,因此須要將e[b][a]也賦爲1 } //從1號頂點出發 book[1]=1; //標記1號頂點已被訪問 dfs(1); //從1號頂點開始遍歷 getchar();getchar(); return 0; }