算法-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. 深度優先搜索

“走迷宮”。假設你站在迷宮的某個岔路口,然後想找到出口。你隨意選擇一個岔路口來走,走着走着發現走不通的時候,你就回退到上一個岔路口,重新選擇一條路繼續走,直到最終找到出口。這種走法就是一種深度優先搜索策略。實線箭頭表示遍歷,虛線箭頭表示回退。但深度優先搜索最先找出來的路徑,並不是頂點 s 到頂點 t 的最短路徑。深度優先搜索用的是回溯思想,回溯思想非常適合用遞歸來實現。

                                        

 

 

   黑色表起始點,紅色表終點。按照左下右上的方向順序走,即,如果左邊可以走,我們先走左邊。然後遞歸下去,沒達到終點或者走不通了,回溯上一個位置......

  首先往左走,走不通了就回溯到上一步(左右都走過了再回溯)、上一步到起點,按左下右上的順序走。

                                   

 

深度優先搜索 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:

                                                                    

 

 

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.

  1. 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.
  2. 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.

 

https://xiaqiu2233.github.io/2017/10/04/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E5%B9%BF%E5%BA%A6%E5%92%8C%E6%B7%B1%E5%BA%A6%E4%BC%98%E5%85%88%E9%81%8D%E5%8E%86%EF%BC%88%E5%85%88%E5%BA%8F%E3%80%81%E4%B8%AD%E5%BA%8F%E3%80%81%E5%90%8E%E5%BA%8F%EF%BC%89/

 

https://www.geeksforgeeks.org/bfs-vs-dfs-binary-tree/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章