DFS和BFS笔记

图源:B站大佬正月点灯笼讲B/D FS时用的图:https://www.bilibili.com/video/BV1Ks411579J/?spm_id_from=333.788.videocard.1

BFS

先记录广度优先搜索,我理解的广度优先搜索,即是从某点(父结点)出发,按层次遍历后续子节点。如上图所示,我们选取A点为父结点,则接下来应当遍历与A节点直接相邻的B, C节点,我们按顺序将节点记录在python列表中:[A, B, C](注:假设先看的B节点),至此A节点处理完毕,我们按顺序处理B节点,发现B节点直接相连的节点是C, D, 而C节点已经被看过了,所以将D节点放入列表中:[A, B, C, D], 依次类推,最终列表应当是[A, B, C, D, E, F]。可以发现我们是按照列表序遍历子节点的,所以BFS可以用queue描述。python3代码如下

def BFS(graph: dict, sNode):
    nodeLs = [sNode] # 用列表表示一个queue
    checkSet = {sNode} # 查询集,用作查询当前节点是否已经被查询过
    while nodeLs:
        pNode = nodeLs.pop(0) # 从队列中取出本次需要查询的节点
        cNode = graph[pNode]
        for node in cNode: # 循环查询父结点的子节点,将未被查询的节点加入队列中
            if node not in checkSet:
                nodeLs.append(node)
                checkSet.add(node)
        print(pNode)


if __name__ == "__main__":
    graph = {
        'A' : ['B', 'C'],
        'B' : ['A', 'C', 'D'],
        'C' : ['A', 'B', 'D', 'E'],
        'D' : ['B', 'C', 'E', 'F'],
        'E' : ['C', 'D'],
        'F' : ['D']
    }
    BFS(graph, 'A')

紧接着,我们用BFS解决一个最短路径问题,如图所示,如何找到A-F的一条最短路径,形象上看,从A到F的过程中,每一层我们如果只走一次,这应当就是最短路径吧。比如说,A-C-E-D-F这就不算最短路径,因为由遍历过程可知,D和E的父亲是兄弟节点,同一层我们走了两个节点,再看A-B-D-F, 这条路径就是按照完全辈分递减的顺序走的,有了这个思路,我们在BFS的时候,如果将每个节点的父亲节点都记录下来,是不是就方便我们找最短路径了啊,比如我们用python字典结构记录这种关系:{A:None, B:A, C:A, D:B, E:C, F:D}, A是我们选定的创始节点,因此他没有父亲,我们将他的父亲设置为None,从A-F,我们按照父子关系倒推:F-D-B-A-None, 所以其中一条最短路径就是A-B-D-F, 路径长度3。
python3代码如下:

def BFS(graph: dict, sNode):
    nodeLs = [sNode] # 列表表示一个queue
    checkSet = {sNode} # 查询集,用作查询当前节点是否已经被查询过
    parent = {sNode:None} # 父亲备忘录,祖先的父亲设置为None
    while nodeLs:
        pNode = nodeLs.pop(0) # 从队列中取出本次需要查询的节点
        cNode = graph[pNode]
        for node in cNode: # 循环查询父结点的子节点,将未被查询的节点加入队列中
            if node not in checkSet:
                nodeLs.append(node)
                checkSet.add(node)
                parent[node] = pNode
    return parent


if __name__ == "__main__":
    graph = {
        'A' : ['B', 'C'],
        'B' : ['A', 'C', 'D'],
        'C' : ['A', 'B', 'D', 'E'],
        'D' : ['B', 'C', 'E', 'F'],
        'E' : ['C', 'D'],
        'F' : ['D']
    }

    start = 'F'
    end = 'A'
    parent = BFS(graph,end)
    path = [start]
    while True:
        start = parent[start]
        if parent[start]:
            path.append(start)
        else:
            path.append(end)
            break
    print(path)

还是用这个图

DFS

DFS, 既深度优先遍历,通俗的讲就是先一条路莽到头,然后没路走了在回溯,找新的路。BFS是用队列描述的,而DFS则是用栈来描述。如上图所示,我们还是将A点设置为祖宗节点,首先我们看A节点,发现A节点有两条路B,C,我们将B,C依次压到栈里:[B, C], 然后弹出一个C, 发现C有两条路D,E,我们将其压倒栈里:[B, D, E], 然后我们弹出E, 代表我们走E这条路,走完发现此路不通,好害怕,迷路啦,心慌慌。这时栈哥哥站出来说,没事,人家刚就给你弹出一条路,还有一条给你留着呢,接着,栈弹出D,查看D,发现F这条路,将F压进栈:[B, F], 然后再接着弹出一个F, 发现没路了,回溯到栈中再弹一个B, 此时发现与B有关的节点都遍历完了,栈也空了,旅行结束,最终路线为A, C, E, D, F, B 。
python3代码如下:

def DFS(graph: dict, sNode):
    nodeLs = [sNode] # 列表表示一个stack
    checkSet = {sNode} # 查询集,用作查询当前节点是否已经被查询过
    while nodeLs:
        pNode = nodeLs.pop() # 从队列中取出本次需要查询的节点
        cNode = graph[pNode]
        for node in cNode: # 循环查询父结点的子节点,将未被查询的节点加入队列中
            if node not in checkSet:
                nodeLs.append(node)
                checkSet.add(node)
        print(pNode)


if __name__ == "__main__":
    graph = {
        'A' : ['B', 'C'],
        'B' : ['A', 'C', 'D'],
        'C' : ['A', 'B', 'D', 'E'],
        'D' : ['B', 'C', 'E', 'F'],
        'E' : ['C', 'D'],
        'F' : ['D']
    }
    DFS(graph, 'A')

这里先记录这么多,下期在深入说一下BFS的带权最短路径的查找方法,我先去学习啦。。。。。。。。。。再啰嗦一句,如有看官,请帮忙找错,指正一下,万分感谢
另外再在次放一下图源链接:图源-正月点灯笼大佬的b站视频(DFS/BFS)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值