簡體   English   中英

如何檢測無向圖是否具有循環並使用BFS或DFS將其輸出

[英]How to detect if an undirected graph has a cycle and output it using BFS or DFS

關於此的另一個問題僅回答了如何檢測周期,也沒有輸出周期。 因此,我想在無向圖上編寫一個在O(V + E)時間(V =頂點,E =邊)中運行BFS或DFS的算法,並輸出一個循環。

到目前為止,我所了解的是BFS / DFS的工作方式,並且如果您訪問已被標記為已訪問的節點,則可以使用BFS來檢測周期。

要使用DFS檢測和輸出循環,只需在到達每個頂點時對其進行標記即可; 如果標記了當前頂點的任何子代,則說明您有一個涉及該子代的循環。 此外,您知道該子頂點是DFS遇到的屬於該特定循環的第一個頂點,並且自DFS首次遇到該頂點以來DFS中的每個移動(即此后尚未返回的每個遞歸調用)在循環中訪問了另一個頂點。 您需要傳遞回調用堆棧的唯一信息是此子頂點,或者是一個特殊值,指示未找到循環。 您可以將此作為返回值傳回:

dfs(v, p) {
    marked[v] = true
    For each neighbour u of v:
        If u != p:   # I.e. we ignore the edge from our parent p
            If marked[u]:
                Append v to cycleVertices
                Return u   # Cycle!
            Else:
                result = dfs(u, v)
                If result == FINISHED:
                    # Some descendant found a cycle; now we're just exiting
                    Return FINISHED
                Else if result != NOCYCLE:
                    # We are in a cycle whose "top" vertex is result.
                    Append v to cycleVertices
                    If result == v:
                        return FINISHED   # This was the "top" cycle vertex
                    Else:
                        return result     # Pass back up

    marked[v] = false    # Not necessary, but (oddly?) not harmful either ;)
    Return NOCYCLE
}

在為某個頂點r (以及任何非頂點值nil )調用dfs(r, nil) ,如果找到一個cycleVertices則會為其填充一個循環。

[編輯:正如胡安·洛佩斯(Juan Lopes)所指出的那樣,未標記頂點是不必要的,並且可能會造成混淆; 但是,有趣的是,它不會影響無向圖的時間復雜度。]

如果您使用的是DFS,則可以根據所訪問的節點是否已經被訪問來打印出節點的名稱,以遞歸方式進行操作:

define function DFSVisit(node, cycle):
    if node.visited is true:
        push node.name to cycle
        return true
    else 
        set node.visited to true

    for each child of node:
        if DFSVisit(child, cycle) is true:
            set foundCycle to true
            break out of for loop

    if foundCycle is true:
        if (cycle.length <= 1 or cycle[first] != cycle[last]):
            push node.name to cycle
        return true
    else 
        return false

到最后,循環將包含在圖中找到的循環,否則它將為空。 還要注意,顯示循環的順序取決於您對循環的“推”方式(向后推將向后打印,向前推將按順序打印)

編輯:非常感謝@j_random_hacker幫助我調試了偽代碼!

暫無
暫無

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

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