簡體   English   中英

拓撲排序算法(DFS)在Python中的實現

[英]Topological Sort Algorithm (DFS) Implementation in Python

我是 python 和算法的新手。 一段時間以來,我一直在嘗試實現一種拓撲排序算法,但似乎無法創建一個有效的結構。 我創建的函數在 adj 列表中表示的圖表上運行。

當我有一個 DFS 時,節點是自上而下發現的,以及已經訪問過但沒有再次處理的節點:

def DFS(location, graph, visited = None): 
  if visited == None: 
      visited = [False for i in range(len(graph))]
  if visited[location] == True:
      return
    
  visited[location] = True
  node_visited.append(location)

  for node in graph[location]:
      DFS(node, graph, visited)
  return visited

當我嘗試構建拓撲排序算法時,我創建了一個新的 function,它主要檢查要添加到排序列表中的節點的“可用性”(即:是否已訪問其相鄰節點)

def availability(graph, node):
    count = 0
    for neighbour in graph[node]:
        if neighbour in available_nodes:
            count += 1
    if count != 0:
        return False
    return True

但是,我的問題是,一旦我訪問了節點路徑以到達圖表的底部,DFS 就不允許我重新訪問那些節點。 因此,一旦我發現路徑的盡頭,我所做的任何更新都無法處理。

我的方法可能完全不對,但我想知道是否有人可以幫助改進我的實施設計,或者解釋實施通常是如何完成的。 提前致謝。

您不需要可用性檢查來使用 DFS 進行拓撲排序。

DFS 本身確保在其子節點已被處理之前您不會離開節點,因此如果您在 DFS 完成時將每個節點添加到列表中,它們將以(反向)拓撲順序添加。

不過,不要忘記繪制整個圖表,如下所示:

def toposort(graph):
    visited = [False for i in range(len(graph))]
    result = []

    def DFS(node):
        if visited[node]:
            return
        visited[node] = True
        for adj in graph[node]:
              DFS(adj)
        result.append(node)
    
    for i in range(len(graph)):
        DFS(i)

    return result
class Graph:

    def __init__(self):
        self.edges = {}

    def addNode(self, node):
        self.edges[node] = []

    def addEdge(self, node1, node2):
        self.edges[node1] += [node2]

    def getSub(self, node):
        return self.edges[node]

    def DFSrecu(self, start, path):

        for node in self.getSub(start):
            if node not in path:
                path = self.DFSrecu(node, path)

        if start not in path:
            path += [start]

        return path

    def topological_sort(self, start):
        topo_ordering_list = self.DFSrecu(start, [])
        # this for loop it will help you to visit all nodes in the graph if you chose arbitrary node
        # because you need to check if all nodes in the graph is visited and sort them
        for node in g.edges:
            if node not in topo_ordering_list:
                topo_ordering_list = g.DFSrecu(node, topo_ordering_list)
        return topo_ordering_list


if __name__ == "__main__":
    g = Graph()
    for node in ['S', 'B', 'A', 'C', 'G', 'I', "L", 'D', 'H']:
        g.addNode(node)

    g.addEdge("S", "A")
    g.addEdge("S", "B")
    g.addEdge("B", "D")
    g.addEdge("D", "H")
    g.addEdge("D", "G")
    g.addEdge("H", "I")
    g.addEdge("I", "L")
    g.addEdge("G", "I")



    last_path1 = g.topological_sort("D")
    last_path2 = g.topological_sort("S")

    print("Start From D: ",last_path1)
    print("start From S: ",last_path2)

Output:

從 D 開始:['L', 'I', 'H', 'G', 'D', 'A', 'B', 'S', 'C']

從 S 開始:['A', 'L', 'I', 'H', 'G', 'D', 'B', 'S', 'C']

你可以在這里看到 'C' 包含在拓撲排序列表中,即使它沒有連接到任何其他節點但圖中的 'C' 並且你需要訪問她這就是你需要在 topological_sort() function 中循環的方式

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM