演算法-03 | 深度優先DFS| 廣度優先BFS
1. 搜尋演算法
在樹(圖/狀態集)中尋找特定節點
深度優先搜尋演算法和廣度優先搜尋演算法都是基於“圖”這種資料結構。
圖上的搜尋演算法就是,在圖中找出從一個頂點出發,到另一個頂點的路徑。圖上的搜尋演算法有深度優先、廣度優先搜尋演算法,和A*A∗、IDA*IDA∗等啟發式搜尋演算法。
廣度優先搜尋和深度優先搜尋是圖上的兩種最常用、最基本的搜尋演算法,僅適用於狀態空間不大的搜尋。它們比A*A∗、IDA*IDA∗等啟發式搜尋演算法要簡單粗暴,沒有什麼優化,所以也叫作暴力搜尋演算法。
廣度優先搜尋,採用地毯式層層推進,從起始頂點開始,依次往外遍歷。廣度優先搜尋需要藉助佇列來實現,遍歷得到的路徑就是起始頂點到終止頂點的最短路徑。
深度優先搜尋,採用回溯思想,適合用遞迴或棧來實現。遍歷得到的路徑並不是最短路徑。
深度優先和廣度優先搜尋的時間複雜度都是 O(E),空間複雜度都是 O(V)。其中E代表邊,O代表頂點。
搜尋 -- 遍歷
- 每個節點都要訪問一次
- 每個節點僅僅要訪問一次
- 對於節點的訪問順序不限
- 深度優先:depth first search
- 廣度優先:breadth first search
還有是按照優先順序優先進行搜尋,(可按現實場景進行定義,更適合於現實中很多的業務場景。這種演算法稱為 啟發式搜尋)
2. 深度優先搜尋
“走迷宮”。假設你站在迷宮的某個岔路口,然後想找到出口。你隨意選擇一個岔路口
黑色表起始點,紅色表終點。按照左下右上的方向順序走,即,如果左邊可以走,我們先走左邊。然後遞迴下去,沒達到終點或者走不通了,回溯上一個位置......
首先往左走,走不通了就回溯到上一步(左右都走過了再回溯)、上一步到起點,按左下右上的順序走。
深度優先搜尋Depth-First-Search
遍歷順序 : 用棧
DFS python程式碼模板
DFS 程式碼 - 遞迴寫法 visited = set() def dfs(node, visited): if node in visited: # terminator # already visited return visited.add(node) # process current node here. ... for next_node in node.children(): if not next_node in visited: dfs(next_node, visited) DFS 程式碼 - 非遞迴寫法 def DFS(self, tree): if tree.root is None: return [] visited, stack = [], [tree.root] while stack: node = stack.pop() visited.add(node) process (node) nodes = generate_related_nodes(node) stack.push(nodes) # other processing work ...View Code
3. 廣度優先搜尋Breadth-First-Search
廣度優先搜尋(Breadth-First-Search),簡稱 BFS。它是一種“地毯式”層層推進的搜尋策略,即先查詢離起始頂點最近的,然後是次近的,依次往外搜尋:
廣度優先搜尋較之深度優先搜尋之不同在於,深度優先搜尋旨在不管有多少條岔路,先一條路走到底,不成功就返回上一個路口然後就選擇下一條岔路,而廣度優先搜尋旨在面臨一個路口時,把所有的岔路口都記下來,然後選擇其中一個進入,然後將它的分路情況記錄下來,然後再返回來進入另外一個岔路,並重復這樣的操作。
順序遍歷: 用佇列
BFS的python程式碼模板:
BFS 程式碼 def BFS(graph, start, end): queue = [] queue.append([start]) visited.add(start) while queue: node = queue.pop() visited.add(node) process(node) nodes = generate_related_nodes(node) queue.push(nodes) # other processing work ... DFS 程式碼 - 遞迴寫法 visited = set() def dfs(node, visited): visited.add(node) # process current node here. ... for next_node in node.children(): if not next_node in visited: dfs(next node, visited)View Code
https://www.geeksforgeeks.org/difference-between-bfs-and-dfs/
4. DFS| BFS與 Tree的遍歷的關係
A Tree is typically traversed in two ways:
- Breadth First Traversal (Or Level Order Traversal)
- Depth First Traversals
- Inorder Traversal (Left-Root-Right)
- Preorder Traversal (Root-Left-Right)
- Postorder Traversal (Left-Right-Root)
BFS and DFSs of above Tree
Breadth First Traversal : 1 2 3 4 5
Depth First Traversals:
Preorder Traversal : 1 2 4 5 3
Inorder Traversal : 4 2 5 1 3
Postorder Traversal : 4 5 2 3 1
All four traversals require O(n) time as they visit every node exactly once.
here is difference in terms of extra space required.
- Extra Space required for Level Order Traversal is O(w) where w is maximum width of Binary Tree. In level order traversal, queue one by one stores nodes of different level.
- Extra Space required for Depth First Traversals is O(h) where h is maximum height of Binary Tree. In Depth First Traversals, stack (or function call stack) stores all ancestors of a node.