谈到算法,图的操作是避免不了。
而我们一般谈到图时,又必定会谈到图的遍历。
图的遍历通常有 2 种,深度优先(DFS) 和广度优先(BFS)。
深度优先可以阅读我这篇博文:【小算法】图的遍历之深度优先(DFS)
本篇博文讲解广度优先(BFS)。
图的表示
图有两种表示方式
1. 临接矩阵
其实就是一个权重矩阵,用 1 代表两个结点有连接,0 表示没有连接,这样的表示方式通俗易懂,特别适合稠密图,也就是大多数结点是亮亮连接的情况。
2. 临接表
用一个数组储存所有的顶点的信息,每个顶点又用一个链表或者是数组存放与它相临的结点的信息。
这样的表示方式特别适合稀疏图,也就是比较少的结点之间相互有连接。
本文示例代码用 Python 表示,为了简便,用临接表这种形式表示
BFS 算法思路
其实 BFS 的思路非常简单。
如果你哪天钱包忘记在哪里了,以 BFS 的思路就是有层次地搜索。
先每个房间快速地瞄一眼,如果没有发现的话,那么就在每个房间的床上、桌子上快速瞄一眼。
如果还是不行的话,再在每个家具的每个柜子里快速瞄一眼。
然后,按照这样一层一层进行下去。
DFS 图例
上面是一张图,如果要遍历图中所有的结点,又不重复。
在实际编码中,如果要用 BFS 的方式去遍历一个图的话,通常我们会用一个队列来动态保存陆续访问的结点。
我们首先选择 A.
所以 A 先入队列。
A 有 2 个临接结点 B 和 C,所以 B 和 C 依次入队列。
并且将 A 从队列中弹出。
A 结点出队后,现在队列首个元素是 B 结点,B 结点有 4 个临接点 A、C、D、F。
因为 A 和 C 已经入队列过一次,所以不能再入,因此将 D、F 入列。
最后,将 B 结点及时弹出来。
B 结点弹出来后,C 结点就是队列的首元素,它有 A、B、E 3 个临结点,但是 A 和 B 已经入队列访问