若是您以爲本文有用,能夠在微博上關注我,每週我都會在微博上發佈新博客發表的通知,個人微博算法
###深度優先搜索性能
####介紹優化
若是您以爲這篇文章排版不舒服,請到個人微盤下載pdf:搜索算法-深度優先搜索code
深度優先搜索是一種用來遍歷或者搜索樹(TREE)或圖(GRAPH)結構的算法。搜索開始於某個根節點(從圖中選取某個節點),而後在開始回溯前儘量遠地探索到這一支的終點。遞歸
對於DFS的實際應用程序來講,DFS經常由於要搜索的圖的某一條搜索路徑太長(甚至是無限的)而陷入性能瓶頸,因此咱們常常制定DFS只能搜索到某個深度,圖片
若是用一個圖來表明深度優先搜索的過程,即以下圖:get
####深度優先遍歷的僞碼實現博客
相應的僞碼實如今《算法導論》這本書中有講解,書中用的方法十分巧妙,它用三種顏色來表明三種狀態it
如下是一個深度優先遍歷的遞歸實現:微博
DFS(G, s) for 在圖G中的每個節點v status[v] = WHITE // 進行其餘初始 DFS-VISIT(s) DFS-VISIT(v) status[v] = GRAY for 每個v的鄰接節點 if (status[v] == WHITE) DFS-VISIT(t) status[v] = BLACK
若是想實現深度優先遍歷的非遞歸實現,就須要用到stack來存儲未被訪問的節點,以便回溯時可以找到
DFS(G, s) stack visted, unvisited unvisited.push(s) while (!unvisited.empty()) // 只有當unvisted不空 current = unvisited.pop() for 每個current的鄰接節點v and 節點v不在visited中 // 在以上的圖例中是按從右向左的方式來遍歷這些鄰接節點 unvisited.push(v) visted.push(current)
非遞歸實現的圖片實例,圖片中顯示了unvisted棧中的數據狀況:
####深度優先搜索的僞碼實現
深度優先搜索與深度優先遍歷大部分實現是相同的,只是深度優先搜索會在找到終點時就退出搜索。
如下是深度優先搜索的僞碼實現:
DFS(G, s, d) stack visted, unvisited unvisited.push(s) while (!unvisited.empty()) // 只有當unvisted不空 current = unvisited.pop() if (current == d) break; for 每個current的鄰接節點v and 節點不在visited中 // 在以上的圖例中是按從右向左的方式來遍歷這些鄰接節點 v.prev = current unvisited.push(v) visted.push(current)
算法中經過記錄每個節點v都經過他的屬性prev記錄了他的前繼節點是哪個,最終能夠經過前繼節點構建出須要的路徑。
####深度優先搜索的優化
談到深度優先搜索的優化,咱們能夠想到在介紹中咱們說過:DFS經常由於要搜索的圖的某一條搜索路徑太長(甚至是無限的)而陷入性能瓶頸
,因此咱們在優化時應當針對這一點進行優化,即限制每次搜索的路徑長度,以便可以在必定長度的路徑以內找到較優解,當在必定長度以內不能找到合適的路徑時,咱們能夠增長限定的搜索路徑長度,來進一步進行深度優先搜索,這種方法叫作逐層加深的深度優先算法。
咱們根據上文中DFS的遞歸實現來對深度優先搜索,來對深度優先搜索作出優化。
DFS(G, s, d) for 在圖G中的每個節點v status[v] = WHITE // 進行其餘初始 for depth = 0 for max = 邊數/2, 邊數 do if DFS-VISIT(s, d, depth, max) break; DFS-VISIT(v, d, depth, max) if (depth > width) return false if (v == d) return true status[v] = GRAY for 每個v的鄰接節點t if (status[t] == WHITE) t.prev = v DFS-VISIT(t, d, depth + 1, max) status[v] = BLACK return false
####深度優先搜索的優勢
深度優先搜索,與廣度優先搜索相比,它沒必要遍歷全部分支,因此它的速度較快。它不必定能找到最優解,但能找到接近解。
####深度優先搜索的應用
深度優先的第一種應用:走迷宮,上一章列出的代碼是尋找一條有效的路徑,深度優先也能夠窮舉出迷宮中全部的路徑。只須要在每次找到迷宮出口時,不要結束程序,而繼續回溯,就能夠繼續尋找其餘走出迷宮的辦法,直到變量step爲0,程序退出。你能夠記錄每一種走法的路徑長度(step),最後獲得最優解。
深度優先的第二種應用:窮舉。用例子說明:列出 A ~ F 這六個字母所能列出的全部組合(必須6位,不容許重複)。固然你能夠用6重循環給出答案,可是隨着字母數量增多,深度優先會是你的不二選擇。下面繼續經過一些例子說明應用吧,著名的「八皇后問題」,「揹包問題」(固然也均可以用其餘算法),你們能夠在百度上搜索這兩個東東。