递归函数查找到特定目标的所有路径

时间:2019-03-23 17:53:29

标签: python recursion path longest-path

我需要找到到达给定目标的最长路径。数据是ID的字典,其值是指向该ID的所有ID的列表。同样值得注意的是,每个ID只能指向另一个ID。

我试图编写一个递归函数,它将遍历每个可能的路径,并将每个唯一的路径选项存储到另一个列表中,从中我将找到最长的路径。

def create(main, vec, id):
    if (id not in INFO):
        return(main, vec, id)
    else:
        for source in INFO[id]:
            vec.append(source)
            main.append(vec)
            main, vec, id = create(main, vec, source)
        return main,vec,id

和最长的功能

def longest(main):
    longest = 0
    long_list = 0
    for list in main:
        if len(list) > longest:
            long_list = list
            longest = len(list)
    return long_list

做事

INFO = {
    'D4': ['B2','B6'],
    'B6': ['D3'],
    'D3': ['F1','A2'],
    'A2': ['G8'],
    'A1': ['C3'],
    'B2': ['E3','A1']}
main, vec, id = create([],[],'D4')
print(longest(main))

我得到的主要是路径相互堆叠。我将如何修复代码,以便路径不会堆叠。 我希望让主体看起来像

[['B2'],
['B2','E3'],
['B2','A1'],
['B2','A1','C3'],
['B6'],
['B6','D3'],
['B6','D3','F1'],
['B6','D3','A2'],
['B6','D3','A2','G8']]

编辑:

将行main, vec, id = create(main,[],'D4')更改为main, vec, id = create([],[],'D4'),以阐明main是列表列表。

1 个答案:

答案 0 :(得分:0)

由于您的方法具有递归特性,因此很难跟踪当前节点和起始节点(根)之间的路径。

但是,当您只对最长的路径感兴趣时,它肯定会链接根和休假(这些节点没有链接到任何其他节点)。

在下面的代码中,当到达其中一个叶子时,即currentNode not in INFOtrue时,我向上走并记录路径,直到到达根为止。

def create(pathListRef, currentNode, rootNode):
    # pathListRef is the reference to the list containing the paths between all leaves and the root.
    # currentNode holds the current node, e.g. "D3"
    # rootNode holds reference to the root node, i.e. "D4"

    if (currentNode not in INFO):
        # We have reached on of the leaves

        reverseNode = currentNode
        # reverseNode is used to keep track of at which node we are when traveling back to the root.

        path = []
        # holds the relative path between the leave and reverseNode

        while reverseNode is not rootNode:
            # As long as we have not reached the root

            path.insert(0, reverseNode)
            # Prepend (like append, but at the start of the list) the reverseNode to the relative path

            reverseNode = list(INFO.keys())[[i for i,x in enumerate(list(INFO.values())) if reverseNode in x][0]]
            # Get the node linked with the reverseNode and move forward to that one. In essence get the key, where the value contains (since it is a list) the reverseNode.

        pathListRef.append(path)
        # We are at the root, so add the relative path to the final paths list
        return

    # This is only executed when we are not at the leave yet (since we return when we are at a leave)
    for source in INFO[currentNode]:
        create(pathListRef, source, rootNode)

它的用法如下:

myList = []
startNode = "D4"
create(myList, startNode, startNode)
print(myList)  # -> [['B2', 'E3'], ['B2', 'A1', 'C3'], ['B6', 'D3', 'F1'], ['B6', 'D3', 'A2', 'G8']]

通过使用longest()函数,您将得到:

print(longest(myList))  # -> ['B6', 'D3', 'A2', 'G8']

顺便说一句,可以将您的longest()函数缩短为以下函数。此外,如果不仅只有一条最长的代码,此代码还会返回多个路径。

def longest(main):
    return [x for x in main if len(x) == max([len(x) for x in main])]