美文网首页工具癖算法个人专题
深度优先搜索(DFS)两点之间的可行路径

深度优先搜索(DFS)两点之间的可行路径

作者: dalalaa | 来源:发表于2018-08-26 21:26 被阅读67次

    DFS是面试中常见的算法,在求路径问题中非常好用。

    下面以一个图为例:


    一个简单的无权图

    假如我们的目标是求点1到点6的所有路径,可以采用深度优先搜索法:
    先将节点1加入路径,然后从1的后置节点中选择一个节点,1有两个后置节点,分别是2和3;
    这里先选择2,路径为[1,2];
    然后再从2的后置节点中选择,只能选择4,路径为[1,2,4];
    从4的后置节点中选择5,路径为[1,2,4,5];
    从5的后置节点中选择6,路径为[1,2,4,5,6]形成一条完整的从1到6的路径。

    这个问题可以由“求从1到6的所有路径”拆解成“从2到6的所有路径”和“从3到6的所有路径”两个问题,然后再往下依次拆解,这种形式的问题可以很方便地采用递归算法解决。

    为了演示DFS算法的递归实现,要先将这个图转化为压缩邻接矩阵的形式

    graph = [
    [2,3],
    [4],
    [4,6],
    [5],
    [6],
    ]
    

    然后进行DFS搜索

    paths = []
    path = []
    def dfs(start,index,end,graph):
        path.append(index)
        if index == end:
            paths.append(path.copy())
            path.pop()
    
        else:
            for item in graph[index-1]:
                if item not in path:
                    dfs(start,item,end,graph)
            path.pop()
    
    dfs(1,1,6,graph)
    for i,p in enumerate(paths):
        print("path %d" % i + str(p))
    
    output:
    path 0[1, 2, 4, 5, 6]
    path 1[1, 3, 4, 5, 6]
    path 2[1, 3, 6]
    

    递归过程比较难理解,可以在代码中加入print语句,就可以很直观地查看到搜索过程了:

    paths = []
    path = []
    def dfs(start,index,end,graph):
        path.append(index)
        if index == end:
            paths.append(path.copy())
            path.pop()
            print("找到终点%d,得到路径,往前回溯一位,查看节点%d是否有其他路径" % (index,path[-1]))
    
        else:
            print("依次搜索节点%d,%d的后置节点有 %s"% (index,index,str(graph[index-1])))
            for item in graph[index-1]:
                print("搜索节点%d的后置节点%d" % (index,item))
                if item not in path:
                    dfs(start,item,end,graph)
            path.pop()
            if path != []:
                print("节点%d的后置节点搜索完毕,往前回溯一位,查看节点%d处是否有其他路径" % (index,path[-1]))
            else:
                print("循环结束,已无其他路径!")
    dfs(1,1,6,graph)
    for i,p in enumerate(paths):   
        print("path %d" % i + str(p))
    
    依次搜索节点1,1的后置节点有 [2, 3]
    搜索节点1的后置节点2
    依次搜索节点2,2的后置节点有 [4]
    搜索节点2的后置节点4
    依次搜索节点4,4的后置节点有 [5]
    搜索节点4的后置节点5
    依次搜索节点5,5的后置节点有 [6]
    搜索节点5的后置节点6
    找到终点6,得到路径,往前回溯一位,查看节点5是否有其他路径
    节点5的后置节点搜索完毕,往前回溯一位,查看节点4处是否有其他路径
    节点4的后置节点搜索完毕,往前回溯一位,查看节点2处是否有其他路径
    节点2的后置节点搜索完毕,往前回溯一位,查看节点1处是否有其他路径
    搜索节点1的后置节点3
    依次搜索节点3,3的后置节点有 [4, 6]
    搜索节点3的后置节点4
    依次搜索节点4,4的后置节点有 [5]
    搜索节点4的后置节点5
    依次搜索节点5,5的后置节点有 [6]
    搜索节点5的后置节点6
    找到终点6,得到路径,往前回溯一位,查看节点5是否有其他路径
    节点5的后置节点搜索完毕,往前回溯一位,查看节点4处是否有其他路径
    节点4的后置节点搜索完毕,往前回溯一位,查看节点3处是否有其他路径
    搜索节点3的后置节点6
    找到终点6,得到路径,往前回溯一位,查看节点3是否有其他路径
    节点3的后置节点搜索完毕,往前回溯一位,查看节点1处是否有其他路径
    循环结束,已无其他路径!
    path 0[1, 2, 4, 5, 6]
    path 1[1, 3, 4, 5, 6]
    path 2[1, 3, 6]
    

    如此一来,是不是一目了然?

    相关文章

      网友评论

      • 侯明昊啦啦啦:怎么加入权重?
        dalalaa:不太清楚你的需求……我刚写了个有权图的例子:https://www.jianshu.com/p/3419960503cb,你看看能不能解决你的疑问?

      本文标题:深度优先搜索(DFS)两点之间的可行路径

      本文链接:https://www.haomeiwen.com/subject/kvioiftx.html