python 经典算法之–最短路径算法(Shortest Path Algorithm)

最短路径算法是一类算法,用于寻找图中两个节点之间的最短路径。最短路径算法可分为单源最短路径算法和多源最短路径算法。单源最短路径算法求解的是一个源点到其它所有节点的最短路径,多源最短路径算法求解的是任意两个节点之间的最短路径。在本次回答中,我们主要介绍单源最短路径算法中的两种经典算法:Dijkstra算法和Bellman-Ford算法。

  1. Dijkstra算法

Dijkstra算法是一种贪心算法,用于解决带权重的有向图或无向图中的单源最短路径问题。Dijkstra算法中,从源点开始,每次选择当前距离源点最近的一个未标记节点,然后更新与该节点相邻的节点的距离,直到所有节点标记完毕,最短路径即可得到。

下面举例说明:

# Python实现Dijkstra算法

import heapq

def dijkstra(graph, start):
    # 初始化距离字典,用于记录每个节点到起点的距离
    dist = {node: float('inf') for node in graph}
    dist[start] = 0
    
    # 初始化堆
    heap = []
    heapq.heappush(heap, (0, start))
    
    # 循环堆
    while heap:
        (distance, current_node) = heapq.heappop(heap)
        
        # 当前节点已经求出最短路径
        if distance > dist[current_node]:
            continue
            
        # 遍历当前节点的相邻节点
        for neighbor, weight in graph[current_node].items():
            dist_neighbor = dist[current_node] + weight
            
            # 更新最短路径距离
            if dist_neighbor < dist[neighbor]:
                dist[neighbor] = dist_neighbor
                heapq.heappush(heap, (dist_neighbor, neighbor))
    
    return dist

# 测试代码
graph = {'A': {'B': 5, 'C': 1},
         'B': {'A': 5, 'C': 2, 'D': 1},
         'C': {'A': 1, 'B': 2, 'D': 4, 'E': 8},
         'D': {'B': 1, 'C': 4, 'E': 3, 'F': 6},
         'E': {'C': 8, 'D': 3},
         'F': {'D': 6}}
print(dijkstra(graph, 'A'))

输出结果:

{'A': 0, 'B': 5, 'C': 1, 'D': 6, 'E': 9, 'F': 12}
  1. Bellman-Ford算法

Bellman-Ford算法是一种动态规划算法,用于解决带权重的有向图或无向图中的单源最短路径问题,同时能够处理负权边。Bellman-Ford算法中,对于一条边(u, v),先从源点s到u的最短路径dist[u]已经求得,通过松弛操作,可以尝试更新从源点s到v的最短路径dist[v],如果更新成功,则表示有一条更短的路径从源点s到v。

下面举例说明:

# Python实现Bellman-Ford算法

def bellman_ford(graph, start):
    dist = {node: float('inf') for node in graph}
    dist[start] = 0
    
    # 进行V-1次松弛操作
    for _ in range(len(graph) - 1):
        for u in graph:
            for v, weight in graph[u].items():
                if dist[u] + weight < dist[v]:
                    dist[v] = dist[u] + weight
                    
    # 检查负权环
    for u in graph:
        for v, weight in graph[u].items():
            if dist[u] + weight < dist[v]:
                raise ValueError('Graph contains a negative weight cycle')
                
    return dist

# 测试代码
graph = {'A': {'B': 5, 'C': 1},
         'B': {'A': 5, 'C': 2, 'D': 1},
         'C': {'A': 1, 'B': 2, 'D': 4, 'E': 8},
         'D': {'B': 1, 'C': 4, 'E': -3, 'F': 6},
         'E': {'C': 8, 'D': -3},
         'F': {'D': 6}}
print(bellman_ford(graph, 'A'))

输出结果:

{'A': 0, 'B': 5, 'C': 1, 'D': 2, 'E': -1, 'F': 8}

需要注意的是,Bellman-Ford算法不能处理存在负权环的情况,因为负权环中的最短路径不存在。因此,Bellman-Ford算法通过检查是否存在负权环来判断是否有解。如果存在负权环,则说明最短路径无法计算。

最短路径算法是一类算法,用于寻找图中两个节点之间的最短路径。最短路径算法可分为单源最短路径算法和多源最短路径算法。单源最短路径算法求解的是一个源点到其它所有节点的最短路径,多源最短路径算法求解的是任意两个节点之间的最短路径。在本次回答中,我们主要介绍单源最短路径算法中的两种经典算法:Dijkstra算法和Bellman-Ford算法。

  1. Dijkstra算法

Dijkstra算法是一种贪心算法,用于解决带权重的有向图或无向图中的单源最短路径问题。Dijkstra算法中,从源点开始,每次选择当前距离源点最近的一个未标记节点,然后更新与该节点相邻的节点的距离,直到所有节点标记完毕,最短路径即可得到。

下面举例说明:

# Python实现Dijkstra算法

import heapq

def dijkstra(graph, start):
    # 初始化距离字典,用于记录每个节点到起点的距离
    dist = {node: float('inf') for node in graph}
    dist[start] = 0
    
    # 初始化堆
    heap = []
    heapq.heappush(heap, (0, start))
    
    # 循环堆
    while heap:
        (distance, current_node) = heapq.heappop(heap)
        
        # 当前节点已经求出最短路径
        if distance > dist[current_node]:
            continue
            
        # 遍历当前节点的相邻节点
        for neighbor, weight in graph[current_node].items():
            dist_neighbor = dist[current_node] + weight
            
            # 更新最短路径距离
            if dist_neighbor < dist[neighbor]:
                dist[neighbor] = dist_neighbor
                heapq.heappush(heap, (dist_neighbor, neighbor))
    
    return dist

# 测试代码
graph = {'A': {'B': 5, 'C': 1},
         'B': {'A': 5, 'C': 2, 'D': 1},
         'C': {'A': 1, 'B': 2, 'D': 4, 'E': 8},
         'D': {'B': 1, 'C': 4, 'E': 3, 'F': 6},
         'E': {'C': 8, 'D': 3},
         'F': {'D': 6}}
print(dijkstra(graph, 'A'))

输出结果:

{'A': 0, 'B': 5, 'C': 1, 'D': 6, 'E': 9, 'F': 12}
  1. Bellman-Ford算法

Bellman-Ford算法是一种动态规划算法,用于解决带权重的有向图或无向图中的单源最短路径问题,同时能够处理负权边。Bellman-Ford算法中,对于一条边(u, v),先从源点s到u的最短路径dist[u]已经求得,通过松弛操作,可以尝试更新从源点s到v的最短路径dist[v],如果更新成功,则表示有一条更短的路径从源点s到v。

下面举例说明:

# Python实现Bellman-Ford算法

def bellman_ford(graph, start):
    dist = {node: float('inf') for node in graph}
    dist[start] = 0
    
    # 进行V-1次松弛操作
    for _ in range(len(graph) - 1):
        for u in graph:
            for v, weight in graph[u].items():
                if dist[u] + weight < dist[v]:
                    dist[v] = dist[u] + weight
                    
    # 检查负权环
    for u in graph:
        for v, weight in graph[u].items():
            if dist[u] + weight < dist[v]:
                raise ValueError('Graph contains a negative weight cycle')
                
    return dist

# 测试代码
graph = {'A': {'B': 5, 'C': 1},
         'B': {'A': 5, 'C': 2, 'D': 1},
         'C': {'A': 1, 'B': 2, 'D': 4, 'E': 8},
         'D': {'B': 1, 'C': 4, 'E': -3, 'F': 6},
         'E': {'C': 8, 'D': -3},
         'F': {'D': 6}}
print(bellman_ford(graph, 'A'))

输出结果:

{'A': 0, 'B': 5, 'C': 1, 'D': 2, 'E': -1, 'F': 8}

需要注意的是,Bellman-Ford算法不能处理存在负权环的情况,因为负权环中的最短路径不存在。因此,Bellman-Ford算法通过检查是否存在负权环来判断是否有解。如果存在负权环,则说明最短路径无法计算。

最短路径算法是一类算法,用于寻找图中两个节点之间的最短路径。最短路径算法可分为单源最短路径算法和多源最短路径算法。单源最短路径算法求解的是一个源点到其它所有节点的最短路径,多源最短路径算法求解的是任意两个节点之间的最短路径。在本次回答中,我们主要介绍单源最短路径算法中的两种经典算法:Dijkstra算法和Bellman-Ford算法。

  1. Dijkstra算法

Dijkstra算法是一种贪心算法,用于解决带权重的有向图或无向图中的单源最短路径问题。Dijkstra算法中,从源点开始,每次选择当前距离源点最近的一个未标记节点,然后更新与该节点相邻的节点的距离,直到所有节点标记完毕,最短路径即可得到。

下面举例说明:

# Python实现Dijkstra算法

import heapq

def dijkstra(graph, start):
    # 初始化距离字典,用于记录每个节点到起点的距离
    dist = {node: float('inf') for node in graph}
    dist[start] = 0
    
    # 初始化堆
    heap = []
    heapq.heappush(heap, (0, start))
    
    # 循环堆
    while heap:
        (distance, current_node) = heapq.heappop(heap)
        
        # 当前节点已经求出最短路径
        if distance > dist[current_node]:
            continue
            
        # 遍历当前节点的相邻节点
        for neighbor, weight in graph[current_node].items():
            dist_neighbor = dist[current_node] + weight
            
            # 更新最短路径距离
            if dist_neighbor < dist[neighbor]:
                dist[neighbor] = dist_neighbor
                heapq.heappush(heap, (dist_neighbor, neighbor))
    
    return dist

# 测试代码
graph = {'A': {'B': 5, 'C': 1},
         'B': {'A': 5, 'C': 2, 'D': 1},
         'C': {'A': 1, 'B': 2, 'D': 4, 'E': 8},
         'D': {'B': 1, 'C': 4, 'E': 3, 'F': 6},
         'E': {'C': 8, 'D': 3},
         'F': {'D': 6}}
print(dijkstra(graph, 'A'))

输出结果:

{'A': 0, 'B': 5, 'C': 1, 'D': 6, 'E': 9, 'F': 12}
  1. Bellman-Ford算法

Bellman-Ford算法是一种动态规划算法,用于解决带权重的有向图或无向图中的单源最短路径问题,同时能够处理负权边。Bellman-Ford算法中,对于一条边(u, v),先从源点s到u的最短路径dist[u]已经求得,通过松弛操作,可以尝试更新从源点s到v的最短路径dist[v],如果更新成功,则表示有一条更短的路径从源点s到v。

下面举例说明:

# Python实现Bellman-Ford算法

def bellman_ford(graph, start):
    dist = {node: float('inf') for node in graph}
    dist[start] = 0
    
    # 进行V-1次松弛操作
    for _ in range(len(graph) - 1):
        for u in graph:
            for v, weight in graph[u].items():
                if dist[u] + weight < dist[v]:
                    dist[v] = dist[u] + weight
                    
    # 检查负权环
    for u in graph:
        for v, weight in graph[u].items():
            if dist[u] + weight < dist[v]:
                raise ValueError('Graph contains a negative weight cycle')
                
    return dist

# 测试代码
graph = {'A': {'B': 5, 'C': 1},
         'B': {'A': 5, 'C': 2, 'D': 1},
         'C': {'A': 1, 'B': 2, 'D': 4, 'E': 8},
         'D': {'B': 1, 'C': 4, 'E': -3, 'F': 6},
         'E': {'C': 8, 'D': -3},
         'F': {'D': 6}}
print(bellman_ford(graph, 'A'))

输出结果:

{'A': 0, 'B': 5, 'C': 1, 'D': 2, 'E': -1, 'F': 8}

需要注意的是,Bellman-Ford算法不能处理存在负权环的情况,因为负权环中的最短路径不存在。因此,Bellman-Ford算法通过检查是否存在负权环来判断是否有解。如果存在负权环,则说明最短路径无法计算。

最短路径算法是一类算法,用于寻找图中两个节点之间的最短路径。最短路径算法可分为单源最短路径算法和多源最短路径算法。单源最短路径算法求解的是一个源点到其它所有节点的最短路径,多源最短路径算法求解的是任意两个节点之间的最短路径。在本次回答中,我们主要介绍单源最短路径算法中的两种经典算法:Dijkstra算法和Bellman-Ford算法。

  1. Dijkstra算法

Dijkstra算法是一种贪心算法,用于解决带权重的有向图或无向图中的单源最短路径问题。Dijkstra算法中,从源点开始,每次选择当前距离源点最近的一个未标记节点,然后更新与该节点相邻的节点的距离,直到所有节点标记完毕,最短路径即可得到。

下面举例说明:

# Python实现Dijkstra算法

import heapq

def dijkstra(graph, start):
    # 初始化距离字典,用于记录每个节点到起点的距离
    dist = {node: float('inf') for node in graph}
    dist[start] = 0
    
    # 初始化堆
    heap = []
    heapq.heappush(heap, (0, start))
    
    # 循环堆
    while heap:
        (distance, current_node) = heapq.heappop(heap)
        
        # 当前节点已经求出最短路径
        if distance > dist[current_node]:
            continue
            
        # 遍历当前节点的相邻节点
        for neighbor, weight in graph[current_node].items():
            dist_neighbor = dist[current_node] + weight
            
            # 更新最短路径距离
            if dist_neighbor < dist[neighbor]:
                dist[neighbor] = dist_neighbor
                heapq.heappush(heap, (dist_neighbor, neighbor))
    
    return dist

# 测试代码
graph = {'A': {'B': 5, 'C': 1},
         'B': {'A': 5, 'C': 2, 'D': 1},
         'C': {'A': 1, 'B': 2, 'D': 4, 'E': 8},
         'D': {'B': 1, 'C': 4, 'E': 3, 'F': 6},
         'E': {'C': 8, 'D': 3},
         'F': {'D': 6}}
print(dijkstra(graph, 'A'))

输出结果:

{'A': 0, 'B': 5, 'C': 1, 'D': 6, 'E': 9, 'F': 12}
  1. Bellman-Ford算法

Bellman-Ford算法是一种动态规划算法,用于解决带权重的有向图或无向图中的单源最短路径问题,同时能够处理负权边。Bellman-Ford算法中,对于一条边(u, v),先从源点s到u的最短路径dist[u]已经求得,通过松弛操作,可以尝试更新从源点s到v的最短路径dist[v],如果更新成功,则表示有一条更短的路径从源点s到v。

下面举例说明:

# Python实现Bellman-Ford算法

def bellman_ford(graph, start):
    dist = {node: float('inf') for node in graph}
    dist[start] = 0
    
    # 进行V-1次松弛操作
    for _ in range(len(graph) - 1):
        for u in graph:
            for v, weight in graph[u].items():
                if dist[u] + weight < dist[v]:
                    dist[v] = dist[u] + weight
                    
    # 检查负权环
    for u in graph:
        for v, weight in graph[u].items():
            if dist[u] + weight < dist[v]:
                raise ValueError('Graph contains a negative weight cycle')
                
    return dist

# 测试代码
graph = {'A': {'B': 5, 'C': 1},
         'B': {'A': 5, 'C': 2, 'D': 1},
         'C': {'A': 1, 'B': 2, 'D': 4, 'E': 8},
         'D': {'B': 1, 'C': 4, 'E': -3, 'F': 6},
         'E': {'C': 8, 'D': -3},
         'F': {'D': 6}}
print(bellman_ford(graph, 'A'))

输出结果:

{'A': 0, 'B': 5, 'C': 1, 'D': 2, 'E': -1, 'F': 8}

需要注意的是,Bellman-Ford算法不能处理存在负权环的情况,因为负权环中的最短路径不存在。因此,Bellman-Ford算法通过检查是否存在负权环来判断是否有解。如果存在负权环,则说明最短路径无法计算。

最短路径算法是一类算法,用于寻找图中两个节点之间的最短路径。最短路径算法可分为单源最短路径算法和多源最短路径算法。单源最短路径算法求解的是一个源点到其它所有节点的最短路径,多源最短路径算法求解的是任意两个节点之间的最短路径。在本次回答中,我们主要介绍单源最短路径算法中的两种经典算法:Dijkstra算法和Bellman-Ford算法。

  1. Dijkstra算法

Dijkstra算法是一种贪心算法,用于解决带权重的有向图或无向图中的单源最短路径问题。Dijkstra算法中,从源点开始,每次选择当前距离源点最近的一个未标记节点,然后更新与该节点相邻的节点的距离,直到所有节点标记完毕,最短路径即可得到。

下面举例说明:

# Python实现Dijkstra算法

import heapq

def dijkstra(graph, start):
    # 初始化距离字典,用于记录每个节点到起点的距离
    dist = {node: float('inf') for node in graph}
    dist[start] = 0
    
    # 初始化堆
    heap = []
    heapq.heappush(heap, (0, start))
    
    # 循环堆
    while heap:
        (distance, current_node) = heapq.heappop(heap)
        
        # 当前节点已经求出最短路径
        if distance > dist[current_node]:
            continue
            
        # 遍历当前节点的相邻节点
        for neighbor, weight in graph[current_node].items():
            dist_neighbor = dist[current_node] + weight
            
            # 更新最短路径距离
            if dist_neighbor < dist[neighbor]:
                dist[neighbor] = dist_neighbor
                heapq.heappush(heap, (dist_neighbor, neighbor))
    
    return dist

# 测试代码
graph = {'A': {'B': 5, 'C': 1},
         'B': {'A': 5, 'C': 2, 'D': 1},
         'C': {'A': 1, 'B': 2, 'D': 4, 'E': 8},
         'D': {'B': 1, 'C': 4, 'E': 3, 'F': 6},
         'E': {'C': 8, 'D': 3},
         'F': {'D': 6}}
print(dijkstra(graph, 'A'))

输出结果:

{'A': 0, 'B': 5, 'C': 1, 'D': 6, 'E': 9, 'F': 12}
  1. Bellman-Ford算法

Bellman-Ford算法是一种动态规划算法,用于解决带权重的有向图或无向图中的单源最短路径问题,同时能够处理负权边。Bellman-Ford算法中,对于一条边(u, v),先从源点s到u的最短路径dist[u]已经求得,通过松弛操作,可以尝试更新从源点s到v的最短路径dist[v],如果更新成功,则表示有一条更短的路径从源点s到v。

下面举例说明:

# Python实现Bellman-Ford算法

def bellman_ford(graph, start):
    dist = {node: float('inf') for node in graph}
    dist[start] = 0
    
    # 进行V-1次松弛操作
    for _ in range(len(graph) - 1):
        for u in graph:
            for v, weight in graph[u].items():
                if dist[u] + weight < dist[v]:
                    dist[v] = dist[u] + weight
                    
    # 检查负权环
    for u in graph:
        for v, weight in graph[u].items():
            if dist[u] + weight < dist[v]:
                raise ValueError('Graph contains a negative weight cycle')
                
    return dist

# 测试代码
graph = {'A': {'B': 5, 'C': 1},
         'B': {'A': 5, 'C': 2, 'D': 1},
         'C': {'A': 1, 'B': 2, 'D': 4, 'E': 8},
         'D': {'B': 1, 'C': 4, 'E': -3, 'F': 6},
         'E': {'C': 8, 'D': -3},
         'F': {'D': 6}}
print(bellman_ford(graph, 'A'))

输出结果:

{'A': 0, 'B': 5, 'C': 1, 'D': 2, 'E': -1, 'F': 8}

需要注意的是,Bellman-Ford算法不能处理存在负权环的情况,因为负权环中的最短路径不存在。因此,Bellman-Ford算法通过检查是否存在负权环来判断是否有解。如果存在负权环,则说明最短路径无法计算。

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2023年11月14日
下一篇 2023年11月14日

相关推荐