深度優先搜索和廣度優先搜索
搜索-遍歷
- 每個節點都要訪問一次
- 每個節點僅訪問一次
- 對於節點的訪問順序不同
深度優先: depth first search
廣度優先: breadth first search
優先級優先搜索(啓發式搜索,推薦算法)適用於現實中業務場景
深度優先搜索 depth first search
一開始是遞歸的終止條件, 處理當前層,然後遞歸到下一層,
處理當前層,相等於訪問了node, 將node節點加到已訪問的節點去,所以終止條件就是,如果這個節點已經訪問過了,就直接返回.
遞歸到下一層, 就是處理子節點, 二叉樹(左孩子,右孩子), 多叉樹(children),圖(聯通的相鄰節點)
多叉樹和二叉樹兩種遍歷模板基本相同, 不同是二叉樹遍歷模板把判斷一個節點是否被訪問過放在函數的最開始, 而多叉樹遍歷模板是把判斷一個節點是否被訪問過放在遍歷children節點的過程中,但是這裏要保證,在多叉樹最開始遞歸的那個節點是沒有被訪問過的.
針對上述多叉樹 的遍歷模板爲了和樹的遍歷模板一致,就改爲下面DFS代碼-遞歸寫法
這個也支持非遞歸寫法,就是手動維護一個棧,將其加進去,其實是手動模擬了一個遞歸,用棧來進行表示.
樹的深度優先遍歷順序
樹遍歷順序過程:
比如剛開始訪問的是root,這樣root就先放到visited中,root在visited之後就從root.children裏面找next_node, 所以它的next_node都沒有被訪問過,所以會先訪問最左邊結點, 這裏當最左邊的節點被拿出來,判斷沒有被visited,因爲處了root visited過其他節點都還未visited過,那麼就會直接調用dfs, next_node就把最左邊節點放進去,再把visited也一起放進去, 遞歸調用的特色是不會等循環跑完,就直接進入到下一層,也就是當前夢境,寫了一層循環,在第一層循環的時候,我就要開始下到新的一層夢境中.
所以 當訪問1之後馬上在1這層循環中就會訪問2,訪問2的時候再馬上繼續下層3,同理4,看4, 3, 2依次有無兒子,發現沒有,返回到1, 1有其他兒子5,然後6, 7…這麼一個順序.
圖的深度優先遍歷順序
假設從S節點開始走,先走A,選擇走A之後,它不會繼續走B和C,走A後馬上走更深一層的下一個節點D,依次走D,G,E,B,在走S時發現走過了,所以就不走了就會回到G之後再走下一個分支F,再走C…發現都走完了.
廣度優先搜索 breadth first search
廣度優先遍歷用隊列.
廣度優先遍歷順序是一層一層向下
def BFS(graph, start, end):
queue = []
queue.push([start]) // 或者 queue.append([start]) ????
while queue:
node = queue.pop()
visited.add(node)
process(node)
nodes = generate_related_nodes(node)
queue.push(nodes)
# other processing work
有一個排隊的隊列queue,先把最開始的節點放到隊列中,每次從隊列裏面取之後,把兒子節點再放到隊列中,依次處理, 先入先出.