前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【小算法】图的遍历之深度优先(DFS)

【小算法】图的遍历之深度优先(DFS)

作者头像
Frank909
发布2020-01-13 14:44:20
8920
发布2020-01-13 14:44:20
举报
文章被收录于专栏:Frank909Frank909

谈到算法,图的操作是避免不了。

而我们一般谈到图时,又必定会谈到图的遍历。

图的遍历通常有 2 种,深度优先(DFS) 和广度优先(BFS)。

本篇博文讲解深度优先(DFS)。

图的表示

图有两种表示方式

在这里插入图片描述
在这里插入图片描述

1. 临接矩阵

在这里插入图片描述
在这里插入图片描述

其实就是一个权重矩阵,用 1 代表两个结点有连接,0 表示没有连接,这样的表示方式通俗易懂,特别适合稠密图,也就是大多数结点是亮亮连接的情况。

2. 临接表

在这里插入图片描述
在这里插入图片描述

用一个数组储存所有的顶点的信息,每个顶点又用一个链表或者是数组存放与它相临的结点的信息。

这样的表示方式特别适合稀疏图,也就是比较少的结点之间相互有连接。

本文示例代码用 Python 表示,为了简便,用临接表这种形式表示

DFS 算法思路

其实 DFS 的思路非常简单。

如果你哪天钱包忘记在哪里了,以 DFS 的思路就是,一个房间一个房间找。

先选定一个房间,大致扫一眼,发现没有。

然后,就选择房间里面的办公桌,桌子上没有的话,再去桌子上的柜子里面找。

如果桌子没有,就去床上着。

如果翻遍了所有的角落,也没有那就换个房间。

DFS 图例

在这里插入图片描述
在这里插入图片描述

上面是一张图,如果要遍历图中所有的结点,又不重复。

可以先选择一个顶点作为根结点,然后沿着路径一条一条遍历下去。

关键词是递归,因为递归需要终止条件,所以另外需要用一个数组记录已经访问过的结点,当一个结点它的临结点都已经访问时,它就需要回溯,这样能避免重复及陷入死循环。

我们首先选择 A.

在这里插入图片描述
在这里插入图片描述

A 有 2 个临接结点 B 和 C,我们选择先从 B 出发,所以此时路径是

代码语言:javascript
复制
A--->B
在这里插入图片描述
在这里插入图片描述

现在在 B 结点位置,B 有 3 个临接结点,C、D、F,按照优先往右边走的原则,我们选择 F,所以此时的路径是

代码语言:javascript
复制
A--->B--->F
在这里插入图片描述
在这里插入图片描述

F 也有 3 个临接点B,D,E,按照从最右边的顺序遍历,我们选择 E,现在路径是:

代码语言:javascript
复制
A--->B--->F--->E
在这里插入图片描述
在这里插入图片描述

同样的逻辑,在 E 点会选择右边的 C,这时候路径是

代码语言:javascript
复制
A--->B--->F--->E--->C
在这里插入图片描述
在这里插入图片描述

到达 C 点时,情况有些不同,它的临接点 A 和 B 都已经访问过了,代表这条路径到头了,需要向上回溯。

回溯的过程也是顺着路径往回撤,路径是

代码语言:javascript
复制
A--->B--->F--->E--->C--->E
在这里插入图片描述
在这里插入图片描述

E 有 2 个临接点,因为 C 点已经访问了,所以 E 可以访问 D.

在这里插入图片描述
在这里插入图片描述

到了 D 点,D 的临接点都已经访问过,所以 D 也需要往回溯,这种回溯是递归的,最终会回溯到节点 A.

A 是从 B 出发的,按照算法逻辑,这个时候应该从 C 出发了,但是 C 已经被访问了,所以最终整个遍历就结束了。

Python 代码

dfs.py

代码语言:javascript
复制
# G 是临接表的方式表达图形
G={}
G[0] = {1,2}
G[1] = {2,3,5}
G[2] = {0,1,3}
G[3] = {2,4,5}
G[4] = {1,3,5}
G[5] = {1,3,4}

# 记录访问过的结点
visited = [False,False,False,False,False,False]
# 结点的别名
names=['A','B','C','D','E','F']

def dfs(v):
    # 打印访问的点
    print("--->",names[v])
    visited[v] = True
    for i,value in enumerate(G[v]):
        # 如果可以访问,最沿着路径一直访问
        if not visited[value]:
            dfs(value) 



if __name__ == "__main__":
    # 打印图
    print("Graphy:",G)
    dfs(0)

最终结果如下:

代码语言:javascript
复制
Graphy: {0: {1, 2}, 1: {2, 3, 5}, 2: {0, 1, 3}, 3: {2, 4, 5}, 4: {1, 3, 5}, 5: {1, 3, 4}}
---> A
---> B
---> C
---> D
---> E
---> F

可以看到,代码可以正常执行,大家亲手实践一下吧。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-09-27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 图的表示
    • 1. 临接矩阵
      • 2. 临接表
      • DFS 算法思路
      • DFS 图例
      • Python 代码
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档