【Python演算法】遍歷(Traversal) - 廣度優先(BFS) - 拾貝文庫網
文章推薦指數: 80 %
【Python演算法】遍歷(Traversal)、深度優先(DFS)、廣度優先(BFS)
【Python演算法】遍歷(Traversal)、深度優先(DFS)、廣度優先(BFS)
標籤:拓撲 並且 arc ever 連通圖 tin wal blog walk 圖結構:
非常強大的結構化思維(或數學)模型。
如果您能用圖的處理方式來規範化某個問題,即使這個問題本身看上去並不像個圖問題,也能使您離解決問題更進一步。
在眾多圖演算法中,我們常會用到一種非常實用的思維模型--遍歷(traversal):對圖中所有節點的探索及訪問操作。
圖的一些相關概念:
簡單圖(Simplegraph):無環並且無平行邊的圖.
路(path):內部點互不相同的鏈。
如果無向圖G中每一對不同的頂點x和y都有一條路,(即W(G)=1,連通分支數)則稱G是連通圖,反之稱為非連通圖。
兩端點相同的路(即閉路)稱為圈(cycle)。
樹(tree)是無圈連通無向圖。
樹中度數為1的結點稱為樹的葉結點。
樹中度數大於1的結點稱為樹的分支節點或內部結點。
不相交的若干樹稱為森林(forest),即森林的每個連通分支是樹。
定理1:T是樹<=>T中無環,且任何不同兩頂點間有且僅有一條路。
定理2:T是樹<=>T連通且|e|=n-1,|e|為T的邊數,n為T的頂點數。
由根到某一頂點v的有向路的長度,稱為頂點v的層數(level)。
根樹的高度就是頂點層數的最大值。
深度優先搜尋:
求連通簡單圖G的一棵生成樹的許多方法中,深度優先搜尋(depthfirstsearch)是一個十分重要的演算法。
基本思想:
任意選擇圖G的一個頂點V0作為根,通過相繼地新增邊來形成在頂點V0開始的路,其中每條新邊都與路上的最後一個頂點以及不在路上的一個頂點相關聯。
繼續儘可能多地新增邊到這條路。
若這條路經過圖G的所有頂點,則這條路即為G的一棵生成樹;
若這條路沒有經過G的所有頂點,不妨設形成這條路的頂點順序V0,V1,......,Vn。
則返回到路里的次最後頂點V(n-1).
若有可能,則形成在頂點v(n-1)開始的經過的還沒有放過的頂點的路;
否則,返回到路里的頂點v(n-2)。
然後再試。
重複這個過程,在所訪問過的最後一個頂點開始,在路上次返回的頂點,只要有可能就形成新的路,直到不能新增更多的邊為止。
深度優先搜尋也稱為回溯(backtracking)
栗子:
用深度優先搜尋來找出圖3-9所示圖G的生成樹,任意地從頂點d開始,生成步驟顯示在圖3-10。
廣度優先搜尋:
可用廣度優先搜尋(breadthfirstsearch)來產生連通簡單圖的生成樹。
基本思想:
從圖的頂點中任意第選擇一個根,然後新增與這個頂點相關聯的所有邊,在這個階段新增的新頂點成為生成樹裡1層上的頂點,任意地排序它們。
下一步,按照順序訪問1層上的每一個頂點,只要不產生迴路,就新增與這個頂點相關聯的每個邊。
這樣就產生了樹裡2的上的頂點。
遵循同樣的原則繼續下去,經有限步驟就產生了生成樹。
栗子:
用廣度優先搜尋找出圖3-9所示圖G的生成樹,選擇頂點f作為根:
兩種著名的基本遍歷策略:
深度優先搜尋(depth-firstsearch)
廣度優先搜尋(breadth-firstsearch)
找出圖的連通分量:
如果一個圖中的任何一個節點都有一條路徑可以到達其他各個節點,那麼它就是連通的。
連通分量:目標圖中最大(且獨立)的連通子圖。
從圖中的某個部分開始,逐步擴大其連通子圖的確認範圍,直至它再也無法向外連通為止。
defwalk(G,s,S=set()):
P,Q=dict(),set()
P[s]=None#s節點沒有前任節點
Q.add(s)#從s開始搜尋
whileQ:
u=Q.pop()
forvinG[u].difference(P,S):#得到新節點
Q.add(v)
P[v]=u#記錄前任節點
returnP
defcomponents(G):
comp=[]
seen=set()
foruinrange(9):
ifuinseen:continue
C=walk(G,u)
seen.update(C)
comp.append(C)
returncomp
if__name__=="__main__":
a,b,c,d,e,f,g,h,i=range(9)
N=[
{b,c,d},#a
{a,d},#b
{a,d},#c
{a,c,d},#d
{g,f},#e
{e,g},#f
{e,f},#g
{i},#h
{h}#i
]
comp=components(N)
print(comp)
深度優先搜尋:
遞迴版的深度優先搜尋:
defrec_dfs(G,s,S=None):
ifSisNone:S=set()
S.add(s)
foruinG[s]:
ifuinS:coontinue
rec_dfs(G,u,S)
迭代版的深度優先搜尋:
defiter_dfs(G,s):
S,Q=set(),[]
Q.append(s)
whileQ:
u=Q.pop()
ifuinS:continue
S.add(u)
Q.extend(G[u])
yieldu
if__name__=="__main__":
a,b,c,d,e,f,g,h,i=range(9)
G=[{b,c,d,e,f},#a
{c,e},#b
{d},#c
{e},#d
{f},#e
{c,g,h},#f
{f,h},#g
{f,g}#h
]
print(list(iter_dfs(G,a)))#[0,5,7,6,2,3,4,1]
通用性的圖遍歷函式
deftraverse(G,s,qtype=set()):
S,Q=set(),qtype()
Q.add(s)
whileQ:
u=Q.pop()
ifuinS:continue
S.add(u)
forvinG[u]:
Q.add(v)
yieldu
classstack(list):
add=list.append
g=list(traverse(G,0,stack))
基於深度優先搜尋的拓撲排序
defdfs_topsort(G):
S,res=set(),[]
defrecurse(u):
ifuinS:return
S.add(u)
forvinG[u]:
recurse(v)
res.append(u)
foruinG:
recurse(u)
res.reverse()
returnres
if__name__=="__main__":
a,b,c,d,e,f,g,h,i=range(9)
G={
‘a‘:set(‘bf‘),
‘b‘:set(‘cdf‘),
‘c‘:set(‘d‘),
‘d‘:set(‘ef‘),
‘e‘:set(‘f‘),
‘f‘:set(‘‘)
}
res=dfs_topsort(G)
迭代深度的深度優先搜尋
defiddfs(G,s):
yielded=set()
defrecurse(G,s,d,S=None):
ifsnotinyielded:
yields
yielded.add(s)
ifd==0:return
ifSisNone:S=set()
S.add(s)
foruinG[s]:
ifuinS:continue
forvinrecurse(G,u,d-1,S):
yieldv
n=len(G)
fordinrange(n):
iflen(yielded)==n:break
foruinrecurse(G,s,d):
yieldu
if__name__=="__main__":
a,b,c,d,e,f,g,h,i=range(9)
N=[
{b,c,d},#a
{a,d},#b
{a,d},#c
{a,b,c},#d
{g,f},#e
{e,g},#f
{e,f},#g
{i},#h
{h}#i
]
G=[{b,c,d,e,f},#a
{c,e},#b
{d},#c
{e},#d
{f},#e
{c,g,h},#f
{f,h},#g
{f,g}#h
]
p=list(iddfs(G,0))#[0,1,2,3,4,5,6,7]
m=list(iddfs(N,0))#[0,1,2,3]
廣度優先搜尋
importcollections
defbfs(G,s):
P,Q={s:None},collections.deque([s])
whileQ:
u=Q.popleft()
forvinG[u]:
ifvinP:continue
P[v]=u
Q.append(v)
returnP
強連通分量
如果有向圖的任何一對結點間是相互可達的,則稱這個有向圖是強連通的
deftr(G):
GT={}
foruinG:GT[u]=set()
foruinG:
forvinG[u]:
GT[v].add(u)
returnGT
defscc(G):
GT=tr(G)
sccs,seen=[],set()
foruindfs_topsort(G):
ifuinseen:continue
C=walk(GT,u,seen)
seen.update(C)
sccs.append(C)
returnsccs
defdfs_topsort(G):
S,res=set(),[]
defrecurse(u):
ifuinS:return
S.add(u)
forvinG[u]:
recurse(v)
res.append(u)
foruinG:
recurse(u)
res.reverse()
returnres
defwalk(G,s,S=set()):
P,Q=dict(),set()
P[s]=None
Q.add(s)
whileQ:
u=Q.pop()
print("u:",u)
print("S:",S)
forvinG[u].difference(P,S):
Q.add(v)
P[v]=u
returnP
if__name__=="__main__":
a,b,c,d,e,f,g,h,i=range(9)
G={
‘a‘:set(‘bc‘),
‘b‘:set(‘edi‘),
‘c‘:set(‘d‘),
‘d‘:set(‘ah‘),
‘e‘:set(‘f‘),
‘f‘:set(‘g‘),
‘g‘:set(‘eh‘),
‘h‘:set(‘i‘),
‘i‘:set(‘h‘)
}
sccs=scc(G)
#[{‘a‘:None,‘d‘:‘a‘,‘c‘:‘d‘,‘b‘:‘d‘},{‘e‘:None,‘g‘:‘e‘,‘f‘:‘g‘},{‘h‘:None,‘i‘:‘h‘}]
【Python演算法】遍歷(Traversal)、深度優先(DFS)、廣度優先(BFS)標籤:拓撲 並且 arc ever 連通圖 tin wal blog walk 原文地址:http://www.cnblogs.com/5poi/p/7466760.html
上一篇:PHP程式設計:ZendFramework動作助手FlashMessenger用法詳解下一篇:ZendFramework動作助手Redirector用法例項詳解
搜索
最新發布:
美容大作戰給大丹犬梳理毛髮的正確方法_養哈士奇的正確方法
杜賓犬血統的劃分_杜賓的價格純血統
怎樣在挑選的時候衡量蘇格蘭牧羊犬的能力_蘇格蘭牧羊犬
新手買博美犬一定要看教你如何辨別“星期狗”_狗狗蛀牙一定要拔嗎
防蟲攻略如何做好雪納瑞的驅蟲工作_卡斯羅犬訓練如何做好
兩個月的吉娃娃吃狗糧後拉稀了怎麼辦_兩個月貓貓糧
德國牧羊犬右後腿突然瘸了,沒事吧_德國牧羊犬吧
阿拉斯加犬不吃東西,沒食慾還嘔吐是怎麼了_狗狗不吃東西還嘔吐
剛買回來的鬥牛犬總是叫的不停如何是好_買回來的寵物不健康怎麼辦
秋田犬後背上長了一個包應該怎麼辦_貓中暑應該怎麼辦
寵物知識:狗狗突然開始藏食物了_狗狗腿突然瘸了
寵物問答大全:狗狗能吃桔子和橙子嗎_寵物健康問答
寵物問答大全:狗腎衰症狀_寵物健康問答
寵物問答大全:狗狗腿站不穩發抖流口水_狗狗突然抽搐站不穩
寵物知識:狗狗胃炎會自愈嗎_狗狗得了肺炎會自愈嗎
延伸文章資訊
- 1python 深度優先搜尋演算法DFS - 程序員學院
python 深度優先搜尋演算法DFS,給你一個由1 陸地和0 水組成的的二維網格,請你計算網格中島嶼的數量。 島嶼總是被水包圍,並且每座島嶼只能由水平方向 ...
- 2以Python實作演算法
以Python實作演算法– Algorithms Implements using Python ... BFS; 深度優先搜尋Depth-first Search, DFS; 最短路徑演算法S...
- 3【筆記】DFS (Depth First Search,深度優先搜尋) - Yui Huang ...
【用途】用來遍歷樹(tree)或圖(graph)的演算法。 ... 提醒:Python 預設的recursion depth很小,只有1000。 ... def DFS(now, pre):. ...
- 4BFS、DFS和dijkstra演算法-python - IT閱讀
BFS、DFS和dijkstra演算法-python ... bfs演算法,寬度優先搜尋演算法。 def bfs(graph,start): queue,visited = [start],[s...
- 5【ALGORITHM】使用帶有DFS演算法的Python的遞迴深度問題
DFS演算法已經在使用小的測試用例,但是當我用一個巨大的示例執行它時,它會丟擲“RunTimeError:最大遞迴深度超過”,所以我包含了 ...