Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 使用bfs或dfs打印置换_Algorithm_Permutation_Breadth First Search_Depth First Search - Fatal编程技术网

Algorithm 使用bfs或dfs打印置换

Algorithm 使用bfs或dfs打印置换,algorithm,permutation,breadth-first-search,depth-first-search,Algorithm,Permutation,Breadth First Search,Depth First Search,我正在尝试使用递归打印字符串的所有排列,如下所示。但我想知道我们是否也可以使用bfs或dfs来完成这一点,我认为是对的吗 如果是的话,你能给我一个想法吗? 我的想法是:如果string=“abcd” 开始节点:“a” 结束节点:“d” 中间节点:“b”和“c” 然后,我们可以将起始节点更改为“b”、“c”和“d” 我很难将其可视化,以便将其放入算法中 #include <stdio.h> void swap(char *s, int i, int j) { char tem

我正在尝试使用递归打印字符串的所有排列,如下所示。但我想知道我们是否也可以使用bfs或dfs来完成这一点,我认为是对的吗

如果是的话,你能给我一个想法吗? 我的想法是:如果string=“abcd” 开始节点:“a” 结束节点:“d” 中间节点:“b”和“c”

然后,我们可以将起始节点更改为“b”、“c”和“d”

我很难将其可视化,以便将其放入算法中

#include <stdio.h>

void swap(char *s, int i, int j)
{
    char temp = s[i];
    s[i] = s[j];
    s[j] = temp;
}

void foo(char *s, int j, int len)
{
    int i;
    if (j == len-1) {
        printf("%s\n", s);
        return;
    }
    for (i=j;i<len;i++) {
        swap(s, i, j);
        foo(s, j+1, len);
        swap(s, i, j);
    }
}

int main()
{
    char s[] = "abc";
    foo(s, 0, strlen(s));
}

队列实现是

您的算法似乎已经实现了回溯,这是排列的正确方法之一。还有基于尾部反转的非递归算法(找不到链接,我想我记不清它的确切名称)或QuickPerm算法:


DFS和BFS只访问每个顶点一次。因此,如果您真的想使用它们,那么作为顶点,您应该查看排列(整个字符串,如“abcd”、“abdc”等),而不是单独的字符,如“a”、“b”等。从一些初始顶点(如“abcd”)开始,您应该尝试交换每对字符,并查看是否已访问该顶点。您可以将访问的顶点集存储在
无序集
中。例如,在“abcd”中,如果交换“b”和“c”,则会得到“acbd”等。该算法应该生成每个置换,因为对于Heap的算法,每个步骤只交换一对顶点就足够了:

您的算法似乎已经实现了回溯,这是置换的正确方法之一。还有基于尾部反转的非递归算法(找不到链接,我想我记不清它的确切名称)或QuickPerm算法:


DFS和BFS只访问每个顶点一次。因此,如果您真的想使用它们,那么作为顶点,您应该查看排列(整个字符串,如“abcd”、“abdc”等),而不是单独的字符,如“a”、“b”等。从一些初始顶点(如“abcd”)开始,您应该尝试交换每对字符,并查看是否已访问该顶点。您可以将访问的顶点集存储在
无序集
中。例如,在“abcd”中,如果交换“b”和“c”,则得到“acbd”等。此算法应产生每个置换,因为对于Heap的算法,每个步骤只交换一对顶点就足够了:

您可以阅读本文:

虽然这是C++实现,但是您可以很容易地将它转换成C版本


顺便说一下,您的方法可以称为dfs

您可以阅读这篇文章:

虽然这是C++实现,但是您可以很容易地将它转换成C版本


顺便说一下,您的方法可以称为dfs

如果您严格地想要模拟图形遍历算法……这里有一种直观的(可能不是最优雅的)方法:

  • 将字符串视为一个图形,其中每个字符与其他每个字符相连

  • 不要试图找到从源到目标的“路径”,而是将问题框架为:“找到特定长度的所有路径-从每个源”

  • 因此,从第一个字符开始,使用它作为“源”;然后查找长度=整个字符串长度的所有路径。。。然后使用下一个字符作为源

    下面是python的一个实现:

    def permutations(s):
        g = _str_to_graph(s) # {'a': ['b', 'c'], 'b': ['c', 'a'], 'c': ['a', 'b'] }
        branch = []
        visited = set()
        for i in s: # use every character as a source
            dfs_all_paths_of_certain_length(i, len(s), branch, visited, g)
    
    def _str_to_graph(s):
        from collections import defaultdict
        g = defaultdict(list)
        for i in range(len(s)):
            for j in range(len(s)):
                if i != j:
                    g[s[i]].append(s[j])
        return g
    
    def dfs_all_paths_of_certain_length(u, ll, branch, visited, g):
        visited.add(u)
        branch.append(u)
        if len(branch) == ll: # if length of branch equals length of string, print the branch
            print("".join(branch))
        else:
            for n in g[u]:
                if n not in visited:
                    dfs_all_paths_of_certain_length(n, ll, branch, visited, g)
        # backtrack
        visited.remove(u)
        branch.remove(u)
    

    如果您严格地想要模拟图形遍历算法……这里有一种直观的(可能不是最优雅的)方法:

  • 将字符串视为一个图形,其中每个字符与其他每个字符相连

  • 不要试图找到从源到目标的“路径”,而是将问题框架为:“找到特定长度的所有路径-从每个源”

  • 因此,从第一个字符开始,使用它作为“源”;然后查找长度=整个字符串长度的所有路径。。。然后使用下一个字符作为源

    下面是python的一个实现:

    def permutations(s):
        g = _str_to_graph(s) # {'a': ['b', 'c'], 'b': ['c', 'a'], 'c': ['a', 'b'] }
        branch = []
        visited = set()
        for i in s: # use every character as a source
            dfs_all_paths_of_certain_length(i, len(s), branch, visited, g)
    
    def _str_to_graph(s):
        from collections import defaultdict
        g = defaultdict(list)
        for i in range(len(s)):
            for j in range(len(s)):
                if i != j:
                    g[s[i]].append(s[j])
        return g
    
    def dfs_all_paths_of_certain_length(u, ll, branch, visited, g):
        visited.add(u)
        branch.append(u)
        if len(branch) == ll: # if length of branch equals length of string, print the branch
            print("".join(branch))
        else:
            for n in g[u]:
                if n not in visited:
                    dfs_all_paths_of_certain_length(n, ll, branch, visited, g)
        # backtrack
        visited.remove(u)
        branch.remove(u)
    

    您可能正在寻找回溯:相似:@user3386109:抱歉,这是完全相反的。@nomanguigt问题不同,但答案是适用的。您可能正在寻找回溯:相似:@user3386109:抱歉,这是完全相反的。@nomanguigt问题不同,但是答案是适用的。谢谢你的逻辑。我想知道为什么人们否决了这个问题。我已经在问题中为您的逻辑添加了相关代码。如果您能看到一些代码,那将非常有用。。。(注意:我没有否决你)谢谢你的逻辑。我想知道为什么人们否决了这个问题。我已经在问题中为您的逻辑添加了相关代码。如果您能看到一些代码,那将非常有用。。。(注:我没有否决你)请总结链接的内容。一旦它消失了,你的答案就没用了。请总结一下链接的内容。一旦它消失了,你的答案就变得无用了。