目錄
1 問題描述
深度優先查找(depth-first search,DFS)可以從任意頂點開始訪問圖的頂點,然后把該頂點標記為已訪問。在每次迭代的時候,該算法緊接着處理與當前頂點鄰接的未訪問頂點。這個過程一直持續,直到遇到一個終點——該頂點的所有鄰接頂點都已被訪問過。在該終點上,該算法沿着來路后退一條邊,並試着繼續從那里訪問未訪問的頂點。再后退到起始頂點上,並且起始頂點也是一個終點時,該算法最終停了下來。這樣,起始頂點所在的連通分量的所有頂點都被訪問過了。如果,未訪問過的頂點仍然存在,該算法必須從其中任一點開始,重復上述過程。
總之,記住一句話,深度優先查找就是先盡可能達到當前遍歷路徑能夠達到最長的路徑,一旦達到該路徑終點,再回溯,從原來已遍歷過頂點(PS:該頂點包含多個分支路徑)處開始新的分支路徑遍歷。
2 解決方案
2.1 蠻力法
此處借用算法設計與分析基礎(第三版)上一段概念介紹,及說明圖形介紹其具體遍歷過程,下面的具體代碼使用數據就是下圖中相關數據。


具體代碼如下:
package com.liuzhen.chapterThree; public class DepthFirstSearch { public int count = 0; //用於計算遍歷總次數 /* * adjMatrix是待遍歷圖的鄰接矩陣 * value是待遍歷圖頂點用於是否被遍歷的判斷依據,0代表未遍歷,非0代表已被遍歷 * result用於存放深度優先遍歷的頂點順序 */ public void dfs(int[][] adjMatrix,int[] value,char[] result){ for(int i = 0;i < value.length;i++){ if(value[i] == 0){ char temp = (char) ('a' + i); System.out.println(); System.out.println("深度為:"+i+",當前出發點:"+temp); result[i] = temp; //存放當前正在遍歷頂點下標字母 dfsVisit(adjMatrix,value,result,i); } } } /* * adjMatrix是待遍歷圖的鄰接矩陣 * value是待遍歷圖頂點用於是否被遍歷的判斷依據,0代表未遍歷,非0代表已被遍歷 * result用於存放深度優先遍歷的頂點順序 * number是當前正在遍歷的頂點在鄰接矩陣中的數組下標編號 */ public void dfsVisit(int[][] adjMatrix,int[] value,char[] result,int number){ value[number] = ++count; //把++count賦值給當前正在遍歷頂點判斷值數組元素,變為非0,代表已被遍歷 System.out.print("當前已行走頂點value["+number+"] = "+value[number]+" "); for(int i = 0;i < value.length;i++){ if(adjMatrix[number][i] == 1 && value[i] == 0){ //當當前頂點的相鄰有相鄰頂點可行走且其為被遍歷 char temp = (char) ('a' + i); result[count] = temp; //存放即將行走的頂點下標字母 System.out.println(" 當前i值:"+i+" 到達"+temp+"地"); dfsVisit(adjMatrix,value,result,i); //執行遞歸,行走第i個頂點 } } } public static void main(String[] args){ int[] value = new int[10]; //初始化后,各元素均為0 char[] result = new char[10]; int[][] adjMatrix = {{0,0,1,1,1,0,0,0,0,0}, {0,0,0,0,1,1,0,0,0,0}, {1,0,0,1,0,1,0,0,0,0}, {1,0,1,0,0,0,0,0,0,0}, {1,1,0,0,0,1,0,0,0,0}, {0,1,1,0,1,0,0,0,0,0}, {0,0,0,0,0,0,0,1,0,1}, {0,0,0,0,0,0,1,0,1,0}, {0,0,0,0,0,0,0,1,0,1}, {0,0,0,0,0,0,1,0,1,0}}; DepthFirstSearch test = new DepthFirstSearch(); test.dfs(adjMatrix,value,result); System.out.println(); System.out.println("判斷節點是否被遍歷結果(0代表未遍歷,非0代表已被遍歷):"); for(int i = 0;i < value.length;i++) System.out.print(" "+value[i]); System.out.println(); System.out.println("深度優先查找遍歷順序如下:"); for(int i = 0;i < result.length;i++) System.out.print(" "+result[i]); } }
運行結果:
深度為:0,當前出發點:a 當前已行走頂點value[0] = 1 當前i值:2 到達c地 當前已行走頂點value[2] = 2 當前i值:3 到達d地 當前已行走頂點value[3] = 3 當前i值:5 到達f地 當前已行走頂點value[5] = 4 當前i值:1 到達b地 當前已行走頂點value[1] = 5 當前i值:4 到達e地 當前已行走頂點value[4] = 6 深度為:6,當前出發點:g 當前已行走頂點value[6] = 7 當前i值:7 到達h地 當前已行走頂點value[7] = 8 當前i值:8 到達i地 當前已行走頂點value[8] = 9 當前i值:9 到達j地 當前已行走頂點value[9] = 10 判斷節點是否被遍歷結果(0代表未遍歷,非0代表已被遍歷): 1 5 2 3 6 4 7 8 9 10 深度優先查找遍歷順序如下: a c d f b e g h i j
參考資料:
