Detect and return cycles in a given directed graph

In a directed graph, a cycle is a path that starts and ends at the same vertex, and visits at least one other vertex in between. Detecting and returning cycles in a given directed graph can be achieved using different approaches in Julia.

Approach 1: Depth-First Search (DFS)

One way to detect cycles in a directed graph is by performing a Depth-First Search (DFS) traversal. The idea is to maintain a visited array to keep track of visited vertices during the traversal. If we encounter a visited vertex again, it indicates the presence of a cycle.


function has_cycle_dfs(graph, start)
    visited = fill(false, length(graph))
    stack = [start]
    while !isempty(stack)
        vertex = pop!(stack)
        if visited[vertex]
            return true
        end
        visited[vertex] = true
        for neighbor in graph[vertex]
            if !visited[neighbor]
                push!(stack, neighbor)
            end
        end
    end
    return false
end

To use this approach, we need to represent the directed graph as an adjacency list, where each vertex is associated with a list of its neighboring vertices. The function has_cycle_dfs takes the graph and a starting vertex as input and returns true if a cycle is detected, and false otherwise.

Approach 2: Breadth-First Search (BFS)

Another way to detect cycles in a directed graph is by performing a Breadth-First Search (BFS) traversal. Similar to the DFS approach, we maintain a visited array to keep track of visited vertices. If we encounter a visited vertex again, it indicates the presence of a cycle.


function has_cycle_bfs(graph, start)
    visited = fill(false, length(graph))
    queue = [start]
    while !isempty(queue)
        vertex = dequeue!(queue)
        if visited[vertex]
            return true
        end
        visited[vertex] = true
        for neighbor in graph[vertex]
            if !visited[neighbor]
                enqueue!(queue, neighbor)
            end
        end
    end
    return false
end

Similar to the DFS approach, the graph needs to be represented as an adjacency list. The function has_cycle_bfs takes the graph and a starting vertex as input and returns true if a cycle is detected, and false otherwise.

Approach 3: Depth-Limited Search (DLS)

A third approach to detect cycles in a directed graph is by performing a Depth-Limited Search (DLS) traversal. DLS is similar to DFS, but with a depth limit to avoid infinite loops. If we encounter a visited vertex again within the depth limit, it indicates the presence of a cycle.


function has_cycle_dls(graph, start, depth_limit)
    visited = fill(false, length(graph))
    stack = [(start, 0)]
    while !isempty(stack)
        vertex, depth = pop!(stack)
        if visited[vertex]
            return true
        end
        visited[vertex] = true
        if depth < depth_limit
            for neighbor in graph[vertex]
                if !visited[neighbor]
                    push!(stack, (neighbor, depth + 1))
                end
            end
        end
    end
    return false
end

Similar to the previous approaches, the graph needs to be represented as an adjacency list. The function has_cycle_dls takes the graph, a starting vertex, and a depth limit as input and returns true if a cycle is detected within the depth limit, and false otherwise.

Among the three options, the choice depends on the specific requirements of the problem. If memory usage is a concern, the BFS approach may be preferred as it uses a queue instead of a stack. If the graph is expected to have cycles at shallow depths, the DLS approach with an appropriate depth limit can be efficient. Otherwise, the DFS approach is a general-purpose solution.

Rate this post

Leave a Reply

Your email address will not be published. Required fields are marked *

Table of Contents