譯自 Uninformed search algorithms in Python
版權全部,如需轉載,請聯繫譯者node
圖的搜索能夠分爲uninformed搜索和informed搜索,二者的區別是前者是的搜索是盲目的,它不知道目標節點在哪,然後者是啓發式的搜索。python
主要的uninformed 搜索分爲如下三類:git
深度優先搜索(DFS)github
廣度優先搜索(BFS)算法
一致代價搜索(UCS)app
使用鄰接矩陣的形式建立圖,爲簡便起見,這裏省去節點的其餘信息,直接使用一個字典表示,key表示節點,value表示鄰接節點:code
small_graph = { 'A': ['B', 'C'], 'B': ['D', 'A'], 'C': ['A'], 'D': ['B'] }
深度優先搜索會優先檢索第一個鄰接節點,而後重複這個過程,直到到達分支的底部,而後回溯。DFS能夠經過遞歸實現,也能夠經過遞歸實現。orm
具體實現須要保存已經訪問的節點,同時判斷邊緣條件:blog
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)
該算法主要針對的是加權圖,加權圖每條邊都有一個權值,權值低的邊優先遍歷,首先,咱們建立一個加權圖類:
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會檢索出一條邊最少的路徑。