前言
圖的周遊與前面文章中的二叉樹周遊還是存在很大差別的。所謂圖的周遊指的是從圖中的某一個頂點出發通路圖中的其餘頂點,并且需要保證每個頂點隻被通路一次。由于圖比二叉樹複雜得多,是以前面二叉樹的周遊算法在圖中是行不通的。因為對于任意一個頂點來講,都可能與其餘的頂點發生連接配接。如果不對通路的頂點做一些處理,出發重複通路的幾率是很高的。是以,一個基本思想是設定一個标記數組,主要用于标記已經被通路過的頂點。圖的周遊算法主要有兩種:深度優先周遊和廣度優先周遊。本篇文章主要介紹的是深度優先周遊算法。
深度優先周遊的具體過程
深度優先周遊,簡稱dfs。具體思想是不放過任何一個死角。在圖的周遊中就是從圖的某個頂點v出發,通路此頂點,然後從v的未被通路過的鄰接點出發深度優先周遊圖,直至圖中的所有和v有路徑相通的頂點都被通路到(對于連通圖來講)。
為了更好說明深度優先周遊的過程,以下面的圖為例:

上圖的鄰接表定義如下:
注意:頂點0的第一個元素是2而不是5,其頂點類似。
起點是頂點0,後面的周遊過程從頂點0開始,把頂點0标記為已通路
因為頂點2是頂點0的鄰接表的第一個元素,是以下一次遞歸從頂點2開始,同時把頂點2标記為已通路
頂點2的遞歸周遊開始,由于頂點2的鄰接表的第一個元素是0,但是0已經被通路過了,是以通路頂點1,1沒有被通路,于是将1标記為已通路,遞歸繼續從頂點1開始
查找上表中頂點1的第一個元素,是頂點0,由于已經被通路過,是以通路頂點2,2也被通路過了,于是從頂點1的遞歸周遊結束,傳回到頂點2繼續遞歸。
查找頂點2的下一個元素,頂點3,沒有被通路,于是将頂點3标記為已通路,遞歸于是從頂點3開始
查找頂點3鄰接表的第一個元素,是頂點5,沒有被通路,于是将頂點5标記為已通路,遞歸從頂點5開始
頂點5從其鄰接表查找第一個元素,是頂點3,已被通路過,繼續查找頂點0,也被通路,于是遞歸從5結束,傳回到頂點3繼續遞歸
查找頂點3鄰接表的下一個元素,是頂點4,沒有被通路過,于是将頂點4标記為已通路,遞歸從頂點4繼續開始
頂點4查找其鄰接表的第一個元素,發現頂點3已被通路過,繼續查找其下一個元素,發現頂點2也被通路過,于是遞歸從頂點4結束,傳回到頂點3繼續遞歸
頂點查找下一個元素是頂點2了,也是頂點3鄰接表的最後一個元素,發現頂點2已經被通路過了,是以遞歸從頂點3結束,傳回到頂點2繼續遞歸
頂點查找其鄰接表的下一個元素,是頂點4,也是其鄰接表最後一個元素,發現頂點已被通路過,是以遞歸從頂點2結束,傳回到頂點0繼續遞歸
頂點0繼續查找其鄰接表的下一個元素,發現頂點1餘頂點5都被通路過了,是以遞歸結束。總的周遊結束。
從以上過程來看,上圖的頂點通路次序依次是:0,2,1,3,5,4。
深度優先周遊算法的實作
首先需要定義一個存儲圖的資料結構,在java中可以使用鄰接表來實作圖存儲。具體而言就是,圖的頂點用一維數組存儲,每個頂點的鄰接頂點用一個單連結清單進行存儲。
圖的資料結構:鄰接表的實作
深度優先周遊算法的實作代碼:
深度優先周遊算法的非遞歸實作方式
使用非遞歸的方式與遞歸的思想是一緻的,不同的在于需要使用一個棧儲存周遊的頂點。下面是具體的實作代碼: