数据结构之图:有向图的拓扑排序,Python代码实现——26
生活随笔
收集整理的這篇文章主要介紹了
数据结构之图:有向图的拓扑排序,Python代码实现——26
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
有向圖的拓?fù)渑判?/h1>
拓?fù)渑判蚪榻B
什么是拓?fù)渑判?#xff1f;
- 一個(gè)有向圖的拓?fù)渑判?#xff08;Topological sort 或 Topological ordering)是根據(jù)其有向邊從頂點(diǎn)U到頂點(diǎn)V對(duì)其所有頂點(diǎn)的一個(gè)線性排序
- 舉個(gè)例子:讓一個(gè)拓?fù)渑判虻膱D中的所有頂點(diǎn)代表某項(xiàng)要執(zhí)行的任務(wù)組合,那么它的邊就可以代表要執(zhí)行要執(zhí)行其中某一項(xiàng)任務(wù)必須要先先于另外一項(xiàng)任務(wù)的限制條件,在這個(gè)例子中,拓?fù)渑判蚓褪沁@項(xiàng)任務(wù)組合的有效排序
有向圖中的環(huán)
知道了拓?fù)渑判蚩梢杂脕?lái)解決優(yōu)先級(jí)問(wèn)題后,還要確保要解決排序問(wèn)題的圖中沒(méi)有環(huán):
- 如果學(xué)習(xí)x課程前必須先學(xué)習(xí)y課程,學(xué)習(xí)y課程前必須先學(xué)習(xí)z課程,學(xué)習(xí)z課程前必須先學(xué)習(xí)x課程,那么一定是有問(wèn)題了, 我們就沒(méi)有辦法學(xué)習(xí)了,因?yàn)檫@三個(gè)條件沒(méi)有辦法同時(shí)滿足。其實(shí)這三門課程x、y、z的條件組成了一個(gè)環(huán):
如何檢測(cè)有向圖中的環(huán)
借助一個(gè)列表ontrack,其索引代表圖中的頂點(diǎn)
基于DFS使用Python代碼實(shí)現(xiàn)拓?fù)渑判?/h2>
檢測(cè)圖中的環(huán)
檢測(cè)的目標(biāo),對(duì)應(yīng)的實(shí)現(xiàn)了這張圖的類方法:點(diǎn)擊回到上一節(jié)查看代碼
主要屬性和方法
graph為需要進(jìn)行拓?fù)渑判虻膱D;marked標(biāo)記當(dāng)前節(jié)點(diǎn)是否已經(jīng)搜索完畢;has_cycle用于標(biāo)記當(dāng)前圖中是否存在環(huán);ontrack標(biāo)記當(dāng)次所處搜索中頂點(diǎn)是否已經(jīng)遍歷過(guò)
Python代碼實(shí)現(xiàn)
class DirectedCycle:def __init__(self, graph):self.graph = graphself.marked = [False for _ in range(self.graph.num_vertices)]self.has_cycle = Falseself.ontrack = [False for _ in range(self.graph.num_vertices)]def dfs(self):"""We need to search every vertex of this graph"""def dfs(index):self.marked[index] = Trueself.ontrack[index] = Truefor vertex in self.graph.adj_list[index]:if not self.ontrack[vertex]:dfs(vertex)if self.ontrack[vertex]:self.has_cycle = Truereturnself.ontrack[index] = Falsefor i in range(self.graph.num_vertices):if not self.marked[i]:dfs(i)if __name__ == '__main__':graph = Digraph(5)graph.point_edge(3, 0)graph.point_edge(0, 2)graph.point_edge(2, 1)graph.point_edge(1, 0)graph.point_edge(1, 4)DC = DirectedCycle(graph)print(DC.has_cycle)DC.dfs()print(DC.has_cycle)運(yùn)行結(jié)果
False True使用DFS實(shí)現(xiàn)圖中頂點(diǎn)的拓?fù)渑判?/h4>
主要屬性方法設(shè)計(jì)
排序步驟
點(diǎn)擊查看圖對(duì)應(yīng)的類方法
Python代碼實(shí)現(xiàn)
class DepthFirstOrder:def __init__(self, graph):self.graph = graphself.marked = [False for _ in range(self.graph.num_vertices)]self.stack = []def dfs(self):"""Search each vertex and rank its order"""def dfs(index):self.marked[index] = Truefor x in self.graph.adj_list[index]:if not self.marked[x]:dfs(x)self.stack.insert(0, index)for i in range(self.graph.num_vertices):# for i in [5, 4, 3, 2, 1, 0]:if not self.marked[i]:dfs(i)return self.stackdef sort_vertices(self):return self.dfs()if __name__ == '__main__':graph = Digraph(6)# graph.point_edge(0, 3)graph.point_edge(0, 2)graph.point_edge(0, 3)graph.point_edge(2, 4)graph.point_edge(3, 4)graph.point_edge(4, 5)graph.point_edge(1, 3)print(graph.adj_list)DF = DepthFirstOrder(graph)print(DF.sort_vertices())運(yùn)行結(jié)果:
[[2, 3], [3], [4], [4], [5], []] [1, 0, 3, 2, 4, 5]排序結(jié)果會(huì)受到對(duì)頂點(diǎn)遍歷的順序影響,但是最終結(jié)果一定會(huì)是一條有效的符合邏輯的排序
檢測(cè)一張圖是否有環(huán),并進(jìn)行拓?fù)渑判?/h4>
調(diào)用前面所實(shí)現(xiàn)的方法即可,點(diǎn)擊查看代碼中使用到的圖對(duì)應(yīng)的類方法
from Structure.graph.digraph import Digraph from Structure.graph.DepthFirstOrder import DepthFirstOrder from Structure.graph.DirectedCycle import DirectedCycleclass TopoLogical:def __init__(self, graph):self.order = Noneself.cycle = DirectedCycle(graph)if not self.cycle.has_cycle:DFO = DepthFirstOrder(graph)self.order = DFO.sort_vertices()def has_cycle(self):# return self.cycle.has_cyclereturn not self.orderdef stack(self):return self.orderif __name__ == '__main__':graph = Digraph(6)graph.point_edge(0, 2)graph.point_edge(0, 3)graph.point_edge(2, 4)graph.point_edge(3, 4)graph.point_edge(4, 5)graph.point_edge(1, 3)print(graph.adj_list)TL = TopoLogical(graph)print(TL.has_cycle())print(TL.stack())運(yùn)行結(jié)果
[[2, 3], [3], [4], [4], [5], []] False [1, 0, 3, 2, 4, 5]總結(jié)
以上是生活随笔為你收集整理的数据结构之图:有向图的拓扑排序,Python代码实现——26的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 回溯算法背包问题迭代c语言,回溯法解决0
- 下一篇: websocket python爬虫_p