译自 Uninformed search algorithms in Python
版权所有,如需转载,请联系译者
图的搜索可以分为uninformed搜索和informed搜索,两者的区别是前者是的搜索是盲目的,它不知道目标节点在哪,而后者是启发式的搜索。
主要的uninformed 搜索分为以下三类:
- 深度优先搜索(DFS)
- 广度优先搜索(BFS)
- 一致代价搜索(UCS)
创建图
使用邻接矩阵的形式创建图,为简便起见,这里省去节点的其他信息,直接使用一个字典表示,key表示节点,value表示邻接节点:
small_graph = {
'A': ['B', 'C'],
'B': ['D', 'A'],
'C': ['A'],
'D': ['B']
}
深度优先搜索
深度优先搜索会优先检索第一个邻接节点,然后重复这个过程,直到到达分支的底部,然后回溯。DFS可以通过递归实现,也可以通过递归实现。
具体实现需要保存已经访问的节点,同时判断边缘条件:
def dfs(graph, start, goal):
visited = set()
stack = [start]
while stack:
node = stack.pop()
if node not in visited:
visited.add(node)
if node == goal:
return
for neighbor in graph[node]:
if neighbor not in visited:
stack.append(neighbor)
广度优先搜索
实际上,只需要将上面算法中的stack改为queue,即可实现广度优先搜索。深度优先搜索总是会展开最新的节点,而广度优先搜索总是展开最老的节点,这就是他们为什么一个使用栈,一个使用队列的原因。
from collections import deque
def bfs(graph, start, goal):
visited = set()
queue = [start]
while queue:
node = queue.pop()
if node not in visited:
visited.add(node)
if node == goal:
return
for neighbor in graph[node]:
if neighbor not in visited:
queue.appendleft(neighbor)
一致代价搜索(UCS)
该算法主要针对的是加权图,加权图每条边都有一个权值,权值低的边优先遍历,首先,我们创建一个加权图类:
class Graph:
def __init__(self):
self.edges = {}
self.weights = {}
def neighbors(self, node):
return self.edges[node]
def get_cost(self, from_node, to_node):
return self.weights[(from_node + to_node)]
UCS跟广度优先搜索类似,也使用一个queue实现,但是使用的是加权队列
from queue import PriorityQueue
当每条边的cost相同时,UCS实际上就是BFS。
def ucs(graph, start, goal):
visited = set()
queue = PriorityQueue()
queue.put((0, start))
while queue:
cost, node = queue.get()
if node not in visited:
visited.add(node)
if node == goal:
return
for i in graph.neighbors(node):
if i not in visited:
total_cost = cost + graph.get_cost(node, i)
queue.put((total_cost, i))
总结
UCS会检索一条权重之和最小的路径,而BFS会检索出一条边最少的路径。
网友评论