📜  Uniform-Cost Search(大图的 Dijkstra)(1)

📅  最后修改于: 2023-12-03 15:05:44.213000             🧑  作者: Mango

Uniform-Cost Search(大图的 Dijkstra)

Uniform-Cost Search(一致代价搜索)是一种用于解决加权图最短路径问题的算法,又被称为大图的 Dijkstra 算法。与 Dijkstra 算法相似,Uniform-Cost Search 也使用了优先队列来管理遍历过的节点,但是它以代价更小的路径优先遍历节点,而不是以最短距离优先遍历节点。Uniform-Cost Search 的优点在于可以处理图中存在负边权的情况。

算法流程
  1. 初始状态为起点,把起点加入到优先队列中,代价为零。

  2. 对于队列中的每个节点,选择队列中代价最小的节点进行遍历,同时更新从起点到该节点的最优代价和路径。

  3. 将遍历到的节点放入遍历过的集合中,标记为已经遍历过。

  4. 对于遍历到的节点,扩展它的相邻节点,如果相邻节点不在已经遍历的集合中,就把它加入到优先队列中。

  5. 对于已经遍历过的节点,更新它的代价和路径,如果更新后的代价更小,就重新放入优先队列中。

  6. 重复步骤 2-5,直到从起点到终点的最短路径被找到,或者队列为空为止。

代码实现

下面是 Uniform-Cost Search 的实现代码:

import heapq

def uniform_cost_search(graph, start, goal):
    """
    graph 是一个邻接表,表示图的结构和边权
    start 是起点,goal 是终点
    返回从起点到终点的最短路径和代价
    """
    # 用一个字典记录遍历过的节点和从起点到该节点的最小代价和路径
    explored = {start: (None, 0)}
    # 初始化优先队列,将起点放入队列中
    queue = [(0, start)]
    
    while queue:
        # 取出队列中代价最小的节点进行遍历
        cost, node = heapq.heappop(queue)
        # 如果遍历到终点,返回从起点到终点的最小代价和路径
        if node == goal:
            path = []
            while node is not None:
                path.append(node)
                node = explored[node][0]
            path.reverse()
            return path, explored[goal][1]
        
        # 遍历从当前节点能够到达的所有节点
        for neighbor, weight in graph[node].items():
            # 计算到达相邻节点的代价
            new_cost = explored[node][1] + weight
            # 如果相邻节点还没有被遍历过或者新的代价更小,就把它加入到优先队列中进行遍历
            if neighbor not in explored or new_cost < explored[neighbor][1]:
                explored[neighbor] = (node, new_cost)
                heapq.heappush(queue, (new_cost, neighbor))
    
    # 如果从起点无法到达终点,返回 None
    return None, float('inf')
时间复杂度

Uniform-Cost Search 的时间复杂度取决于图的大小和边的数量,最坏情况下是 $O(b^{1 + \lfloor C^/\epsilon \rfloor})$,其中 $b$ 是分支因子,$C^$ 是从起点到终点的最短距离,$\epsilon$ 是任意正数。因此 Uniform-Cost Search 不适用于大规模的图。

参考资料
  • Artificial Intelligence: A Modern Approach (3rd Edition) by Stuart Russell and Peter Norvig.