图的遍历-广度优先

Posted ThinkingLog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图的遍历-广度优先相关的知识,希望对你有一定的参考价值。

昨天聊了图的深度优先遍历,思想大概就是我沿着一条路走到黑,直到无路可走,再退回来,找其他可以走的路,直到回到起点。

那今天说的广度优先算法呢,思路会略有不同,他就不会想深度优先算法那样,沿着一条路走到黑,而是我每一个可走的路都看一下,但不深入,先放在那里。等所有的路口都看一遍,然后再深入一点,到每个路口的下一层。这样所有的路口都一样的逐级深入。

举个例子,这就好像你要在房间里面找钥匙。深度优先遍历,就是你从第一个房间开始一查到底,把第一个房间所有的抽屉柜子犄角旮旯都看一遍。都没有,再去找第二个房间。

而广度优先算法呢,则是你先到一二三房间扫一眼,先看看桌面上都有么。然后再深入一点,看看一二三房间的地上都有钥匙么。然后再深入一点,看看一二三房间的抽屉里都有么。最后再深入一点,看看一二三房间抽屉中的衣服兜里面有钥匙么。

从这个例子就可以看出来,大家都是遍历,但思路上面会有一些不一样的地方。用图像表示广度优先算法会是这样。

左边是一个图,右边是从A节点开始以广度优先方式遍历的顺序。他会先遍历第一层A,然后遍历第二层B,F,然后是第三层C,I,G,E,最后是D,H。这是大家普遍逐层深入的思想。

那这样广度优先的遍历思想要用什么方法实现呢?我们可以尝试把自己导入到这个图中,假装自己就站在A点,然后要走完所有的点。在A点的时候,我们处理完A点的遍历任务,看到了两条岔路,分别是去B点和F点,于是我应该先把这两个点记在小本本上,告诉自己一会要先去这两个点。

然后我去到了B,到了B点之后发现这个点没有被遍历过,就先处理一下操作,看到了B点的另外三个岔路口,到C,I,G。那这时候我不是会去选择走哪个,而是先记下来这三个点一会再去,因为我之前记得还要先去F点。

到了F也是一样的,处理遍历任务,然后看到两个另外的岔路G和E,先记载小本本上,发现G之前已经安排了,那么就把剩下的E记下来。

就这样我会一直根据自己小本本上记录的点,按顺序一个一个的走完,直到发现小本本上再也没有要去的地方了。这样遍历就完成了。

那么这个记录的小本本,就是先进先出的队列,先记在上面的先去,后记在上面的后去。图遍历的时候,这个队列大概会是如下图这个样子。

最后贴一下代码,广度优先遍历的代码如下

class EdgeNode: def __init__(self, adjvex = None, nxt = None,weight=None): self.adjvex = adjvex self.weight = weight self.nxt = nxt# 结点class VertexNode: def __init__(self,data = None, firstedge = None): self.data = data self.firstedge = firstedge# 邻接表class Adgraph: def __init__(self): self.vertex_list = []
def build(self,vex_list,adj_matrix): """ 通过邻接矩阵构造图 :param vex_list: 节点数据 :param adj_matrix: 邻接矩阵 """ for i in vex_list: self.vertex_list.append(VertexNode(i))
for i in range(len(vex_list)): for j in range(len(vex_list)): v = adj_matrix[i][j] if v == 0: continue elif v == INFINITY: continue else: edge_node = EdgeNode(j,weight=v) vex_node = self.vertex_list[i] e = vex_node.firstedge if e is None: vex_node.firstedge = edge_node else: while e.nxt is not None: e = e.nxt
e.nxt = edge_nodedef BFS(ad_graph): # 遍历过程中使用的队列 q = queue.Queue() # 初始化遍历标记表 visit_list = [] for i in range(len(ad_graph.vertex_list)): visit_list.append(False) # 遍历所有的节点 for i in range(len(ad_graph.vertex_list)):
if not visit_list[i]: visit_list[i] = True # 标记节点已遍历过 vetex = ad_graph.vertex_list[i] print(vetex.data) # 进行节点操作,可以换成其他操作 q.put(vetex) # 将遍历过的节点加入队列
while not q.empty(): # 对栈内节点进行操作 v = q.get() # 从栈中获取节点 e = v.firstedge # 获取节点的边 while e is not None: if not visit_list[e.adjvex]: # 判断边连接的节点是否遍历过,如果没有进一步操作 visit_list[e.adjvex] = True # 标记遍历 print(ad_graph.vertex_list[e.adjvex].data) # 打印节点,可以换成其他操作 q.put(ad_graph.vertex_list[e.adjvex]) # 将节点放入队列 e = e.nxt


以上是关于图的遍历-广度优先的主要内容,如果未能解决你的问题,请参考以下文章

图的深度/广度优先遍历C语言程序

数据结构C语言版 图的广度优先遍历和深度优先遍历 急急急 会查重

C语言实现图的广度优先搜索遍历算法

什么是图的深度优先遍历?什么是图的广度优先遍历?

图的广度遍历和深度遍历

图的遍历:深度优先遍历,广度优先遍历