歐拉回路問題(算法導論22.2-8 和22-3)

22.3 歐拉回路的算法來自1873年的Hierholzer,前提是假設圖G存在歐拉回路,即有向圖任意點的出度和入度相同。從任意一個起始點v開始遍歷,直到再次到達點v,即尋找一個環,這會保證一定可以到達點v,因爲遍歷到任意一個點u,由於其出度和入度相同,故u一定存在一條出邊,所以一定可以到達v。將此環定義爲C,如果環C中存在某個點x,其有出邊不在環中,則繼續以此點x開始遍歷尋找環C’,將環C、C’連接起來也是一個大環,如此往復,直到圖G中所有的邊均已經添加到環中。

數據結構如下:

(1) 使用循環鏈表CList存儲當前已經發現的環;

(2) 使用一個鏈表L保存當前環中還有出邊的點;

(3) 使用鄰接表存儲圖G

 

使用如下的步驟可以確保算法的複雜度爲O(E):

(1) 將圖G中所有點入L,取L的第一個結點

(2) 直接取其鄰接表的第一條邊,如此循環往復直到再次到達點v構成環C,此過程中將L中無出邊的點刪除。環C與環CList合併,只要將CList中的點v使用環C代替即可。

(3) 如果鏈表L爲空表示歐拉回路過程結束,否則取L的第一個結點,繼續步驟(2)

 

22.2-8要求將無向圖的每條邊恰好按照兩個方向各走一次,實際上可以將此無向圖看作一個有向圖,無向圖中的任意一條邊(u,v),都擴充成爲有向圖中的兩條邊(u,v)和(v,u),根據一筆畫的歐拉定理,因爲此有向圖任意點的出度和入度相同,故此有向圖存在歐拉回路,而且可以從任意點開始。

此問題在BFS(寬度優先搜索)章節,剛開始無論如何也無法和BFS聯繫起來,直到看到22.3中歐拉回路的算法才逐漸明白。算法思路如下:

(1) 與傳統的歐拉回路算法類似,只不過此處的環很簡單,直接是BFS中的邊,注意確保每條邊訪問一次且僅訪問一次;

(2) 當訪問結點u時,將環路徑中的點u替換爲一個小環路徑,即所有與u相鄰的邊且沒有被訪問過的邊,具體來說包括所有的tree edge,同時還有第一次訪問的cross edge

舉例如下:

 

(1) 第一輪BFS,隊列中僅在結點A,環路徑爲A

(2) 第二輪BFS,訪問到邊A=>B時,環路徑爲A=>B=>A,再訪問到A=>C時,環路徑爲A=>B=>A=>C=>A,隊列中有點B、C,環路徑爲A=>B=>A=>C=>A

(3) 第三輪BFS,隊列中有D、E、F,環路徑爲A=>(B=>D=>B=>E=>B)=>A=>(C=>E=>C=>F=>C)=>A

(4) 第四輪BFS,隊列中爲空,最終的環路徑爲

A=>(B=>D=>B=>(E=>F=>E)=>B)=>A=>(C=>E=>C=>F=>C)=>A

發佈了72 篇原創文章 · 獲贊 28 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章