Python中如何实现最短路径查找算法

2023-04-16 00:00:00 算法 如何实现 最短

在Python中,最短路径查找算法可以通过Dijkstra算法或BFS算法来实现。

Dijkstra算法基于贪心思想,每次选择当前节点到起点距离最短的节点进行扩展,直到扩展到终点或者所有节点都被扩展。具体实现可以使用一个优先队列来存储未被扩展的节点,并记录每个节点到起点的距离。下面是使用Dijkstra算法查找“pidancode.com”到“皮蛋编程”的最短路径的代码:

import heapq

def dijkstra(graph, start, end):
    """
    使用Dijkstra算法查找图中 start 到 end 的最短路径
    :param graph: 图,使用字典表示,如 {'a': {'b': 2, 'c': 3}, 'b': {'c': 1, 'd': 4}, 'c': {'d': 2}, 'd': {}}
    :param start: 起点
    :param end: 终点
    :return: 最短路径,如 ['a', 'b', 'c', 'd']
    """
    distances = {node: float('inf') for node in graph}  # 初始化起点到每个节点的距离为无穷
    distances[start] = 0  # 起点到自身的距离为0
    queue = [(0, start)]  # 使用优先队列存储未被扩展的节点,每次取最小值进行扩展

    while queue:
        (curr_dist, curr_node) = heapq.heappop(queue)  # 取出当前到起点距离最短的节点进行扩展
        if curr_node == end:
            # 终点被扩展到,返回最短路径
            path = []
            while curr_node != start:
                path.append(curr_node)
                curr_node = parents[curr_node]
            path.append(start)
            return path[::-1]

        for (neighbor, weight) in graph[curr_node].items():
            # 扩展邻居节点
            distance = curr_dist + weight
            if distance < distances[neighbor]:
                distances[neighbor] = distance
                parents[neighbor] = curr_node
                heapq.heappush(queue, (distance, neighbor))

    return None  # 没有找到最短路径

# 例子:查找 "pidancode.com" 到 "皮蛋编程" 的最短路径
graph = {
    "pidancode.com": {"baidu.com": 1, "zhihu.com": 2, "google.com": 4},
    "baidu.com": {"pidancode.com": 1, "zhihu.com": 3, "so.com": 2},
    "zhihu.com": {"baidu.com": 3, "pidancode.com": 2, "google.com": 3},
    "so.com": {"baidu.com": 2},
    "google.com": {"pidancode.com": 4, "zhihu.com": 3},
    "皮蛋编程": {}
}
parents = {}
path = dijkstra(graph, "pidancode.com", "皮蛋编程")
print(path)

BFS算法则遍历图中所有节点,记录每个节点到起点的距离,并逐步扩展距离更远的节点,直到到达终点或者所有节点都被扩展。下面是使用BFS算法查找“pidancode.com”到“皮蛋编程”的最短路径的代码:

from collections import deque

def bfs(graph, start, end):
    """
    使用BFS算法查找图中 start 到 end 的最短路径
    :param graph: 图,使用字典表示,如 {'a': {'b': 1, 'c': 2}, 'b': {'c': 1, 'd': 3}, 'c': {'d': 1}, 'd': {}}
    :param start: 起点
    :param end: 终点
    :return: 最短路径,如 ['a', 'b', 'c', 'd']
    """
    distances = {node: float('inf') for node in graph}  # 初始化起点到每个节点的距离为无穷
    distances[start] = 0  # 起点到自身的距离为0
    parents = {start: None}  # 记录每个节点的父节点
    queue = deque([start])  # 使用队列存储等待扩展的节点

    while queue:
        current_node = queue.popleft()
        if current_node == end:
            # 终点被扩展到,返回最短路径
            path = []
            while current_node != start:
                path.append(current_node)
                current_node = parents[current_node]
            path.append(start)
            return path[::-1]

        for neighbor in graph[current_node].keys():
            # 扩展邻居节点
            if distances[neighbor] == float('inf'):
                distances[neighbor] = distances[current_node] + 1
                parents[neighbor] = current_node
                queue.append(neighbor)

    return None  # 没有找到最短路径

# 例子:查找 "pidancode.com" 到 "皮蛋编程" 的最短路径
graph = {
    "pidancode.com": {"baidu.com": 1, "zhihu.com": 2, "google.com": 4},
    "baidu.com": {"pidancode.com": 1, "zhihu.com": 3, "so.com": 2},
    "zhihu.com": {"baidu.com": 3, "pidancode.com": 2, "google.com": 3},
    "so.com": {"baidu.com": 2},
    "google.com": {"pidancode.com": 4, "zhihu.com": 3},
    "皮蛋编程": {}
}
path = bfs(graph, "pidancode.com", "皮蛋编程")
print(path)

相关文章