我有一个简单的递归函数,它提供对选项列表的每个可能组合的深度优先搜索:

def twoCharacters_dfs(options, used):
    for i in range(len(options)):
        used.append(options.pop(0))
        print("used=", used)
        twoCharacters_dfs(options, used)
    if len(used) == 0:
        return
    options.append(used.pop())

twoCharacters_dfs(['q', 'w', 'e', 'r'], [])

输出(由于长度缩短)如下所示:
used= ['q']
used= ['q', 'w']
used= ['q', 'w', 'e']
used= ['q', 'w', 'e', 'r']
used= ['q', 'w', 'r']
used= ['q', 'w', 'r', 'e']
used= ['q', 'e']
used= ['q', 'e', 'r']
used= ['q', 'e', 'r', 'w']
used= ['q', 'e', 'w']
used= ['q', 'e', 'w', 'r']
....
used= ['w']
....
used= ['e']
....
used= ['r']
....

这一切都很好,并且按我想要的方式工作。但我有兴趣将其从深度优先转换为广度优先,因此输出看起来更像是:
used= ['q']
used= ['w']
used= ['e']
used= ['r']
used= ['q', 'w']
used= ['q', 'e']
used= ['q', 'r']
used= ['w', 'q']
used= ['w', 'e']
used= ['w', 'r']
....

我在某种程度上能够(只有一个硬编码的固定长度列表)迭代地执行它,但需要一个递归解决方案,以便它可以用于任何长度的选项。我还特意避免提供我所寻求的功能的 python 库,因为我想了解事物是如何工作的,并将构建我自己的东西作为学习练习。

我觉得有一个简单的解决方案,但我无法将广度优先算法概念化到我的代码中。

更新

在尝试递归 BFS 解决方案之前,我想创建一个迭代 BFS 解决方案,因为它似乎更容易实现。事实证明,我也很难做到这一点。
def twoCharacters_bfs_iterative(options, used):
    for option in options:
        print("using option = ", option)

    for option1 in options:
        list2 = options[:]
        list2.remove(option1)
        for option2 in list2:
            print("using option = ", option1, option2)

    for option1 in options:
        list2 = options[:]
        list2.remove(option1)
        for option2 in list2:
            list3 = list2[:]
            list3.remove(option2)
            for option3 in list3:
                print("using option = ", option1, option2, option3)

这实现了我想要的输出(上面列出),但仅适用于我知道长度的集合。我想将它扩展为任意长度的列表,但我无法做到这一点。我想如果我能让迭代解决方案工作,递归解决方案就不会落后了。

最佳答案

编辑:我没有从示例中注意到需要所有排列。遵循使用列表作为队列的函数:

def bfs(options):
    queue = [([c], [*options[:i], *options[i+1:]]) for i,c in enumerate(options)]
    while len(queue) > 0:
        head, tail = queue[0]
        print(head)
        queue.extend([([*head, c], [*tail[:i], *tail[i+1:]]) for i,c in enumerate(tail)])
        del queue[0]

其工作原理如下(64 行,已截断):
>>> bfs(['q','w','e','r'])
['q']
['w']
['e']
['r']
['q', 'w']
['q', 'e']
...
['r', 'w']
['r', 'e']
['q', 'w', 'e']
['q', 'w', 'r']
['q', 'e', 'w']
...
['r', 'q', 'e', 'w']
['r', 'w', 'q', 'e']
['r', 'w', 'e', 'q']
['r', 'e', 'q', 'w']
['r', 'e', 'w', 'q']

还,
def bfs(options):
    queue = [([c], [*options[:i], *options[i+1:]]) for i,c in enumerate(options)]
    for head, tail in queue:
        queue.extend([([*head, c], [*tail[:i], *tail[i+1:]]) for i,c in enumerate(tail)])
    return [head for head, tail in queue]

此版本返回一个列表而不是打印。

遵循上一个答案,不考虑排列:

正如其他人在评论中所说的那样,这是不自然的。遵循“递归”函数:
def bfs(options, level=0):
    if level == 0:
        for c in options:
            print([c])
        for i in range(1,len(options)):
            bfs(options, i)
    else:
        for i,c in enumerate(options):
            for j,g in enumerate(options[i+1:]):
                if i+1+j+level <= len(options):
                    print([c,*options[i+1+j:i+1+j+level]])

最后一行中的 * 需要 Python3,但您可以将其删除。

预期的输出是:
['q']
['w']
['e']
['r']
['q', 'w']
['q', 'e']
['q', 'r']
['w', 'e']
['w', 'r']
['e', 'r']
['q', 'w', 'e']
['q', 'e', 'r']
['w', 'e', 'r']
['q', 'w', 'e', 'r']

另一个版本:
def bfs(options, level=0):
    for i,c in enumerate(options):
        for j,g in enumerate(options[i+1:]):
            if i+1+j+level <= len(options):
                print([c,*options[i+1+j:i+1+j+level]])
            if level == 0:
                break
    if level < len(options):
        bfs(options, level + 1)

关于Python:将列表的所有组合的深度优先搜索转换为广度优先搜索,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48333927/

10-12 19:24