dfs遍历和bfs遍历python_广度优先遍历(BFS)和深度优先遍历(DFS)
BFS:
思想:
對于圖中的初始節點,先遍歷初始節點的一階鄰居,當初始節點的一階鄰居都被遍歷完了之后,再遍歷初始節點的二階鄰居,直至所有節點都被遍歷完(或找到符合條件的節點)
過程:
三要素:(1)先入先出的一個容器:隊列;(2)圖中的節點:最好寫成單獨的一個類表示;(3)已訪問集合:避免重復訪問。
算法過程:
(1)首先將根節點放入隊列中
(2)取出隊列中的第一個節點進行訪問,并將其所有未被訪問的鄰居節點添加到隊列中
(3)若隊列為空則算法結束
時間復雜度:
廣度優先遍歷算法的時間復雜度并不確定,取決于用何種方式來表示圖。
實例:
力扣第279題完全平方數,題目鏈接(https://leetcode-cn.com/problems/perfect-squares/):
給定正整數 n,找到若干個完全平方數(比如 1, 4, 9, 16, …)使得它們的和等于 n。你需要讓組成和的完全平方數的個數最少。
分析:本題可以用動態規劃的方法解,此處用廣度優先遍歷的方法解題
首先我們把正整數n看作是圖中的初始節點,用完全平方數表示圖中的邊,n減去完全平方數后表示n的鄰居節點。因此本題可以轉換為找從n到0的最短路徑。
#定義圖中節點的類型,包含val和passed(經過的路徑數)
class Node:
def __init__(self,val,passed = 0):
self.val = val
self.passed = passed
class Solution:
def numSquares(self, n: int) -> int:
jiedian = [Node(n)]#將初始節點放入隊列
visited = [0]*n + [1]#定義節點是否被訪問過,避免訪問重復的節點
while jiedian:
tmp = jiedian.pop(0)#彈出首節點
#判斷是否符合條件
for i in range(1,int(math.sqrt(tmp.val)+1)):
tmp_val = tmp.val - i*i
if tmp_val == 0:
return tmp.passed + 1
elif visited[tmp_val] == 0:
jiedian.append(Node(tmp_val,tmp.passed + 1))#將節點的鄰居節點添加到隊列
visited[tmp_val] = 1#將節點進行標記,避免重復訪問
DFS:
思想:
從初始節點出發,一直沿著某條邊訪問下去,直至該路徑上的所有節點均被訪問過,再回到初始節點,從初始節點出發,沿著另一條路徑開始訪問,直至圖中所有節點均被訪問。
過程:
三要素:(1)先入先出的一個容器:棧;(2)圖中的節點:最好寫成單獨的一個類表示;(3)已訪問集合:避免重復訪問。
算法過程:
(1)先將初始節點放入隊列中
(2)將隊列中取出第一個節點進行訪問,將它某一個未被訪問的節點加入隊列中
(3)重復2
(4)若不存在為訪問的鄰居節點,將上一級節點加入到隊列中,重復2
(5)直至隊列為空
時間復雜度:
與BFS類似。
實例:
力扣695. 島嶼的最大面積(題目鏈接https://leetcode-cn.com/problems/max-area-of-island/)
給定一個包含了一些 0 和 1 的非空二維數組 grid 。
一個 島嶼 是由一些相鄰的 1 (代表土地) 構成的組合,這里的「相鄰」要求兩個 1 必須在水平或者豎直方向上相鄰。你可以假設 grid 的四個邊緣都被 0(代表水)包圍著。
找到給定的二維數組中最大的島嶼面積。(如果沒有島嶼,則返回面積為 0 。)
分析:
圖中每塊陸地都可以當作一個節點,兩個1上下左右相連視為一條邊,則可以構成很多圖。
#深度優先遍歷搜索
class Solution:
def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
ans = 0#存儲結果
for i, m in enumerate(grid):
for j, n in enumerate(m):
strack = [(i,j)]#棧
tmp = 0#記錄每一塊的面積
while strack:
cur_i, cur_j = strack.pop()#彈出棧尾的數據
if cur_i<0 or cur_j<0 or cur_i==len(grid) or cur_j==len(grid[0]) or grid[cur_i][cur_j] != 1:
continue
grid[cur_i][cur_j] = 0#避免重復訪問
tmp += 1
for k,p in [[0,1],[0,-1],[1,0],[-1,0]]:
next_i = cur_i + k
next_j = cur_j + p
strack.append((next_i,next_j))
ans = max(ans,tmp)
return ans
其實此題還可以用廣度優先遍歷的方法解答:
class Solution:
def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
ans = 0#存儲結果
for i, m in enumerate(grid):
for j, n in enumerate(m):
strack = [(i,j)]#隊列
tmp = 0#記錄每一塊的面積
while strack:
cur_i, cur_j = strack.pop(0)#先彈出隊首的數據
if cur_i<0 or cur_j<0 or cur_i==len(grid) or cur_j==len(grid[0]) or grid[cur_i][cur_j] != 1:
continue
grid[cur_i][cur_j] = 0
tmp += 1
for k,p in [[0,1],[0,-1],[1,0],[-1,0]]:
next_i = cur_i + k
next_j = cur_j + p
strack.append((next_i,next_j))
ans = max(ans,tmp)
return ans
總結:
通過上面這個題,可以看出廣度優先和深度優先的區別只是遍歷圖中節點的順序不同,廣度優先遍歷的順序是先遍歷節點的所有一階鄰居節點,然后所有二階鄰居節點。。。***可以借助隊列這種數據結構實***現。深度優先遍歷的是沿著一條邊不停遍歷下去,直至結束,才開始下一條邊,可以借助棧來實現。
原文鏈接:https://blog.csdn.net/scp_6453/article/details/106601947
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的dfs遍历和bfs遍历python_广度优先遍历(BFS)和深度优先遍历(DFS)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ubuntu mysql emma_ub
- 下一篇: Mysql删除语句优化_MySQL性能优