1

译自 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)

一致代价搜索

该算法主要针对的是加权图,加权图每条边都有一个权值,权值低的边优先遍历,首先,我们创建一个加权图类:

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会检索出一条边最少的路径。


fireflow
434 声望9 粉丝

« 上一篇
json4s使用指南