简体   繁体   中英

How to implement recursive DFS in Python efficiently?

I am trying to implement recursive DFS in Python. My attempt is:

def dfs_recursive(graph, vertex, path=[]):
    path += [vertex]

    for neighbor in graph[vertex]:
        # print(neighbor)
        if neighbor not in path:  # inefficient line
            path = dfs_recursive(graph, neighbor, path)

    return path


adjacency_matrix = {"s": ["a", "c", "d"], "c": ["e", "b"],
                    "b": ["d"], "d": ["c"], "e": ["s"], "a": []}

Unfortunately, the line if neighbor not in path is very inefficient and not what I am supposed to do. I would like the output to be the nodes that are visited in order, but without duplicates. So in this case:

['s', 'a', 'c', 'e', 'b', 'd']

How can I output the nodes that are visited in DFS order but without duplicates efficiently?

Using a dict :

def dfs_recursive(graph, vertex, path={}):
    path[vertex] = None

    for neighbor in graph[vertex]:
        if neighbor not in path:
            dfs_recursive(graph, neighbor)

    return path

adjacency_matrix = {"s": ["a", "c", "d"], "c": ["e", "b"],
                    "b": ["d"], "d": ["c"], "e": ["s"], "a": []}

print(*dfs_recursive(adjacency_matrix, "s"))

Output:

s a c e b d

You could do something like this:

def dfs_recursive(graph, vertex, dic, path):

    dic[vertex] = 1;
    path += vertex
    for neighbor in graph[vertex]:

        if not neighbor in dic: 
           dfs_recursive(graph, neighbor, dic, path)



graph = {"s": ["a", "c", "d"], "c": ["e", "b"],
                    "b": ["d"], "d": ["c"], "e": ["s"], "a": []}

path = [];
dic = {}
dfs_recursive(graph,"s",dic,path);

print(path)

You need to have a dictionary for efficient lookups, if you want path you could add it to a different structure as shown above.

You could use an OrderedDict for your path variable. That will make the in operator run in constant time. Then to turn that into a list, just get the keys from that dict, which are guaranteed to be in insertion-order.

I would also put the recursive part of the overall function into a separate function. That way you don't have to pass path as an argument in each recursive call:

from collections import OrderedDict

def dfs_recursive(graph, vertex):
    path = OrderedDict()

    def recur(vertex):
        path[vertex] = True
        for neighbor in graph[vertex]:
            if neighbor not in path:
                recur(neighbor)

    recur(vertex)
    return list(path.keys())

adjacency_matrix = {"s": ["a", "c", "d"], "c": ["e", "b"],
                    "b": ["d"], "d": ["c"], "e": ["s"], "a": []}

print(dfs_recursive(adjacency_matrix, "s"))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM