1.深度優先搜索(Depth First Search)遍歷相似於樹的先根遍歷,是樹的先根遍歷的推廣。java
假設初始狀態是圖中全部的頂點不曾被訪問,則深度優先搜索可從圖中某個頂點V出發,訪問此頂點,而後依次從v的未被訪問的鄰接點出發深度優先遍歷圖,至關於一個遞歸的過程,直到圖中全部和v有路徑相通的頂點都被訪問到;node
若此時圖中還有頂點未被訪問,則選圖中的一個不曾被訪問的頂點作起始點,重複上述過程,直至圖中全部頂點都被訪問到爲止。算法
2.如下圖爲例,作個簡單的深度優先搜索遍歷過程:數組
該圖有v1,v2...到V9共9個頂點,假設從頂點V1開始出發進行搜索遍歷,在訪問了V1頂點以後,選擇鄰接點V2,由於V2不曾被訪問,則以V2爲起始點,進行深度優先搜索,(相似於迭代),此時V2的鄰接點有3個,分別爲V1,V4,V5,V2,選擇未被訪問的鄰接點V4,而後會以V4爲起始點,進行深度優先搜索,此時V4的鄰接點爲V2和V8,V2已經被訪問,頂點V4選擇不曾被訪問的頂點V8,這時會以V8爲起始點作優先搜索遍歷,V8的鄰接點是V4和V5,而V4已經被訪問,因此V8選擇不曾被訪問的頂點V5,V5的鄰接點都被訪問了,則回到V8,V8的全部鄰接點也被訪問了,回到V4,v2,到達V1,此時V1會選擇未被訪問的頂點V3,而後會以V3爲起始點進行深度優先搜索,V3會選擇V6,而後以V6爲起始頂點作深度優先搜索,V6選擇未被訪問的鄰接點V9,而V9會選擇未被訪問的V7,而後以V7爲起始點作深度優先搜索遍歷,發現V7的鄰接點都已被訪問,則回到V9,V9的鄰接點也已被訪問 ,則回到V6,回到V3,V1,此時發現V1的鄰接點已經所有被訪問。並且圖中其餘頂點也已經被訪問,全部的頂點都已經被訪問,說明此次的深度有限搜素遍歷已經所有完成。函數
由此獲得的頂點訪問的順序爲:code
V1->V2->V4->V8->V5->V3->V6->V9->V7遞歸
3.很顯然,上述遍歷的過程是一個遞歸的過程。爲了在遍歷中區分頂點是否已經被遍歷,須要附設訪問標誌數組visited[0..n-1],n是指頂點的個數,其初值爲false.一旦某個頂點被訪問,其相應的份量值爲true,visited[i]=true.it
4.代碼附上:採用的是以鄰接表的存儲結構class
/** * 從第i個頂點出發遞歸深度優先遍歷圖 * @param i * @param visited */ public void DFS(int i, boolean[] visited) { VNode v = mVexs[i]; visited[i] = true; ENode node= v.firstEdge; System.out.println(i+"("+mVexs[i].data+")"); while(node!=null){ if(!visited[node.ivex]){ DFS(node.ivex,visited); } node=node.nextEdge; } } public void DFS() { boolean[] visisted = new boolean[mVexs.length]; //建立一個以頂點數爲容量長度的布爾數組用來存取頂點數是否被訪問的標誌 //初始化頂點標誌數組 for (int i = 0; i < mVexs.length; i++) { visisted[i] = false; } for (int i = 0; i < mVexs.length; i++) { if (!visisted[i]) { //對未訪問的頂點調用DFS() DFS(i, visisted); } } }
5.算法複雜度搜索
分析上面的算法,在遍歷圖時,對圖中的每一個頂點至多調用一次DFS函數,由於一旦某個頂點被標誌爲已被訪問,就再也不從它出發進行深度優先搜索了。所以,遍歷圖的過程實質上是對每一個頂點查找其鄰接點的過程。其耗費時間取決於圖所採用的存儲結構。
當用二維數組 表示鄰接矩陣做圖的存儲結構時,查找每一個頂點的鄰接點須要時間爲O(n*n),n爲頂點的個數。
而當以鄰接表做圖的存儲結構時,查找鄰接點的所需時間爲O(e),其中e爲無向圖中邊的數,或有向圖中弧的個數。
由此,當以鄰接表作存儲結構時,深度優先搜索遍歷圖的時間複雜度爲O(n+e)