输入的图如下所示:
用python字典将每个节点,及相连节点重构:
graph = {
'A':['B','C'],
'B':['A','C','D'],
'C':['A','B','D'],
'D':['B','C','E','F'],
'E':['C','D'],
'F':['D']
}
BFS,DFS大致思路一致,唯一不同点在于:BFS使用“队列”实现;DFS使用“栈”实现。即,代码方面,BFS中的queue使用pop(0)实现,DFS中的queue使用pop(-1)或pop()实现。
BFS代码:
graph = {
'A':['B','C'],
'B':['A','C','D'],
'C':['A','B','D'],
'D':['B','C','E','F'],
'E':['C','D'],
'F':['D']
}
def BFS(graph , s): #graph:图 , s:输入一个图的起始节点
queue = [] # 创建一个队列
queue.append(s) # 将起始节点放入队列中
seen = set() # 用来存储所有已经经过的节点
seen.add(s)
while queue:
vertex = queue.pop(0) # 弹出队列最前面的一个节点
nodes = graph[vertex] # 找到vertex的相邻的节点
for w in nodes: # 对于所有节点
if w not in seen:
queue.append(w)
seen.add(w)
print(vertex)
测试:输入节点‘A’:
BFS(graph , 'A')
------------- 输出-------------------
A
B
C
D
E
F
输入节点‘E':
BFS(graph , 'E')
--------------输出-----------
E
C
D
A
B
F
-----------------------------------------------------------------------------------------------------------------------------
DFS:由于跟BFS不同处在于,BFS使用的队列;DFS使用的栈。上述代码,可以直接修改。
DFS代码:
graph = {
'A':['B','C'],
'B':['A','C','D'],
'C':['A','B','D'],
'D':['B','C','E','F'],
'E':['C','D'],
'F':['D']
}
def DFS(graph , s): #graph:图 , s:输入一个图的起始节点
stack= [] # 创建一个栈
stack.append(s) # 将起始节点放入队列中
seen = set() # 用来存储所有已经经过的节点
seen.add(s)
while stack:
vertex = stack.pop() # 弹出栈最上面的节点
nodes = graph[vertex] # 找到vertex的相邻的节点
for w in nodes: # 对于所有节点
if w not in seen:
stack.append(w)
seen.add(w)
print(vertex)
只需要讲pop函数改成pop(-1)或者pop()即可。
测试DFS:
DFS(graph , 'A')
---------------输出-------------
A
C
D
F
E
B
DFS(graph , 'E')
--------------输出-------------
E
D
F
B
A
C
------------------------------------------------------------------------------------------------------------------------------
扩展:从图的一个节点走到另一个节点的,最短距离,最短路径
若,每个边表示了不同的长度,即:A-B的长度为5。利用BFS,求解,从一个节点到另一个节点的最短距离。
分析:
例如,求A到D的最短距离,当没有长度表示时,A到D的最短距离为2,即A-B-D,A-C-D.
但加上长度后,距离就不同了。
BFS使用的队列,从A出发,A与B,C相邻1条边,A与D,E距离两条边。
故,求解路径最短问题,要用到“优先队列”(priority queue)。
优先队列:
例如,有A,C,D分别入队,其中A-1(序号),C-5,D-3。如下图,A,C,D入队
A入队:
C入队:
D入队:
当D入队后,由于D的序号为3,C的序号为5,故D要排到C前面。
回到求解最短距离的问题:
例如,以A为起始点,依次将各节点放入优先队列中。
A到A的距离为0,故A,0。B到A的距离为5,故B,5。再调整位置:调整过程为内部调整。
再弹出C-1,此时外面的点为A,0-C,1。此时由C到B依然有连线,故再插入队列一个B,3(3表示,从A出发,经过C,再到B,即1+2=3),由优先队列特性可得:
构建列表,表示该节点,从哪个节点而来:
其中,B是由C而来,因为优先队列,先弹出的C,再是B。
此时寻找B的下一个节点,有A,C,D,由于A,C已经弹出,故只有D。且,距离为B中距离的3,加上B-D距离1,故优先队列插入D,4:
再调整位置:
同时,parent也做调整:
继续寻找与D相连的节点:
排除BC。 同时算出到E,F的距离分别是7,10.
队列插入E,F:
调整:
并修改parent:
下一步优先队列弹出B,D,由于B,D已经做过,故丢弃:
继续弹出E,7:
接着弹出E,9
E,9丢弃。最后拿出F
注意:F是跟D相连。
找到从A到F的最短距离:
在parent中一步一步寻找。
A-C-B-D-F
代码:
import headpq
使用headpq库。
数字代表该节点与key节点之间的距离。