如何从递归函数返回值而不是打印到控制台?

时间:2019-04-08 07:58:23

标签: python-3.x depth-first-search

我想获得图中两个节点ij之间的所有路径。我正在使用DFS完成此操作。该代码有效。但是,我不想print到控制台的路径(请参见print(path)函数中的searchPaths(self, i, j, visited, path)行)。我想return。但是,由于它是递归函数,因此return无法正常工作。返回path以便我可以将其用于其他计算的正确方法是什么?

class Graph:
    def __init__(self, edges=dict()):
        '''Initializes a Graph. Variables:
            - edges: dictionary with edge tuples as keys (i,j) and
            weight w_ij as values.'''
        self.edges = edges


    def searchPaths(self, i, j, visited, path):
        '''Searches all possible paths from node i to node j.'''
        # Set current node as visited and store it in path 
        visited[i] = True 
        path.append(i)
        # If current node is not same as destination, recursively
        # search adjacent nodes.        
        if i != j:
            for u in self.adjacencyList[1].get(i, []):
                if visited[u] == False:
                    self.searchPaths(u, j, visited, path)
        else:
            print(path)
        # Remove current vertex from path and mark as unvisited
        path.pop()
        visited[i] = False


    def printAllPaths(self, i, j):
        '''Print all possible paths from node i to node j.'''
        # Set all nodes as not visited 
        visited = {n: False for n in self.nodes}
        # Create a list to store the path 
        path = []
        # Call recursive function to search for paths
        self.searchPaths(i, j, visited, path)

    @property
    def adjacencyList(self):
        '''Returns the adjacency list.'''
        ingoing, outgoing = {}, {}
        for edge in self.edges.keys():
            i, j = edge[0], edge[1]
            outgoing[i] = outgoing.get(i, []) + [j]
            ingoing[j] = ingoing.get(j, []) + [i]
        ingoing = {k:set(v) for k,v in ingoing.items()}
        outgoing = {k:set(v) for k,v in outgoing.items()}
        return ingoing, outgoing

作为一个激励示例,可以使用以下边缘:edges = {(1, 2): 1, (2, 1): 2, (2, 3): 2, (3, 2): 3, (3, 5): 2, (5, 4): 8, (5, 6): 9, (7, 6): 4, (7, 8): 4, (8, 9): 1, (8, 10): 3, (9, 10): 2, (10, 7): 5, (10, 11): 8, (12, 13): 3, (13, 14): 1, (14, 12): 2, (15, 14): 4}。搜索从i=7j=11的路径时,应该获得两条路径:[7,8,9,10,11][7,8,10,11]

1 个答案:

答案 0 :(得分:0)

让我们看看是否可以完成这项工作。

您的代码分析

这很奇怪:为什么将节点标记为未访问? 这可能什么也不会改变,甚至更糟的是,甚至可能导致您的代码出现问题。

# Remove current vertex from path and mark as unvisited path.pop() visited[i] = False

目标定义

我们希望:

  • 最后一次返回路径的调用。
  • 中间调用将成为中继信息(返回所有路径)的桥梁

尝试

class Graph:
    def __init__(self, edges=dict()):
        '''Initializes a Graph. Variables:
            - edges: dictionary with edge tuples as keys (i,j) and
            weight w_ij as values.'''
        self.edges = edges
        self.get_nodes()

    def get_nodes(self):
        self.nodes = set()
        for i,j in self.edges:
            self.nodes.add(i)
            self.nodes.add(j)

    def searchPaths(self, i, j, visited, path):
        '''Searches all possible paths from node i to node j.'''
        # Set current node as visited and store it in path 
        visiting = dict(visited)
        visiting[i] = True 
        aux = path[:]
        aux.append(i)
        # If current node is not same as destination, recursively
        # search adjacent nodes. 
        all_paths=[]
        if i != j:
            for u in self.adjacencyList[1].get(i, []):
                if visiting[u] == False:
                    all_paths += self.searchPaths(u, j, visiting, aux)

        else:
            print(aux)
            all_paths += [aux[:]]
        return all_paths



    def printAllPaths(self, i, j):
        '''Print all possible paths from node i to node j.'''
        # Set all nodes as not visited 
        visited = {n: False for n in self.nodes}
        # Create a list to store the path 
        path = []
        # Call recursive function to search for paths
        return self.searchPaths(i, j, visited, path)

    @property
    def adjacencyList(self):
        '''Returns the adjacency list.'''
        ingoing, outgoing = {}, {}
        for edge in self.edges.keys():
            i, j = edge[0], edge[1]
            outgoing[i] = outgoing.get(i, []) + [j]
            ingoing[j] = ingoing.get(j, []) + [i]
        ingoing = {k:set(v) for k,v in ingoing.items()}
        outgoing = {k:set(v) for k,v in outgoing.items()}
        return ingoing, outgoing