最短路径算法介绍及python代码实现

最短路径算法

最短路径算法是用来在加权图中找到两个顶点之间的最短路径,即路径上的边的权重之和最小的问题。这里将介绍几种常见的最短路径算法:

1. Dijkstra算法

Dijkstra算法是一种广泛使用的最短路径算法,适用于处理带有非负权重的图。它通过贪心策略逐步确定从起点到图中所有其他顶点的最短路径。

算法步骤:

  1. 将起点的最短路径设为0,其他所有顶点的最短路径设为无穷大。
  2. 创建一个未访问顶点集合,包含所有顶点。
  3. 从未访问顶点集合中选择一个顶点(通常是具有当前已知最短路径的顶点)作为当前顶点。
  4. 将当前顶点从未访问集合中移除。
  5. 更新当前顶点的所有邻居顶点的最短路径。如果通过当前顶点到达邻居顶点的路径更短,则更新邻居顶点的最短路径。
  6. 重复步骤3-5,直到未访问顶点集合为空或找到目标顶点。

时间复杂度:

  • 使用简单的数组和队列实现时,时间复杂度为O(V^2),其中V是顶点数。
  • 使用优先队列(如二叉堆)可以优化到O((V+E)logV),其中E是边数。

2. Bellman-Ford算法

Bellman-Ford算法可以处理带有负权重边的图,但不能处理负权重循环。

算法步骤:

  1. 初始化所有顶点的最短路径为无穷大,起点的最短路径为0。
  2. 进行V-1次迭代,每次迭代更新图中所有边的最短路径。
  3. 如果在迭代中发现通过某个顶点可以找到更短的路径,则更新该路径。
  4. 检查是否存在负权重循环。可以通过进行额外一次迭代来检查,如果发现路径长度在这次迭代中仍然减少,则存在负权重循环。

时间复杂度:

  • O(VE),适用于边数远大于顶点数的稀疏图。

3. Floyd-Warshall算法

Floyd-Warshall算法用于计算图中所有顶点对之间的最短路径。

参考链接

算法步骤:

  1. 初始化一个矩阵,其中矩阵[i][j]表示顶点i到顶点j的最短路径长度。
  2. 对于每对顶点i和j,如果i直接到j的路径存在,则设置矩阵[i][j]为该路径的长度;否则设置为无穷大。
  3. 对于每个顶点k,更新矩阵,考虑通过顶点k进行路径转换的可能性。
  4. 如果矩阵[i][k] + 矩阵[k][j] < 矩阵[i][j],则更新矩阵[i][j]。

时间复杂度:

  • O(V^3),适用于密集图。

4. A*搜索算法

A*算法是一种启发式搜索算法,通常用于图搜索和路径规划问题。它使用一个启发式函数来估计从当前顶点到目标顶点的距离。

算法步骤:

  1. 使用一个优先队列(通常是最小堆)来存储待扩展的顶点,优先级基于f(n) = g(n) + h(n),其中g(n)是从起点到顶点n的实际成本,h(n)是从顶点n到目标顶点的估计成本。
  2. 从起点开始,将起点加入优先队列。
  3. 当优先队列非空时,取出具有最低f(n)值的顶点。
  4. 如果取出的顶点是目标顶点,则找到了最短路径。
  5. 否则,将该顶点的所有邻居顶点加入优先队列,并更新它们的g(n)和f(n)值。

时间复杂度:

  • 依赖于启发式函数的质量,理想情况下可以达到接近线性的时间复杂度。

每种算法都有其适用场景,选择哪种算法取决于具体问题的性质,如边的权重是否为非负、图的稠密程度、是否需要计算所有顶点对之间的最短路径等。

5.具体案例分析

示例:使用字典的方式构建有向图,并搜索图中的路径。
图很容易通过列表和词典来构造。比如说,这有一张简单的图:
 A -> B
 A -> C
 A -> D
 B -> E
 C -> D
 C -> F
 D -> B
 D -> E
 D -> G
 E ->
 F -> D
 F -> G
 G -> E
这个图有7个节点(A-G)和12个弧。它可以通过下面的Python数据结构来表示:
graph = {‘A’: [‘B’, ‘C’,‘D’],
‘B’: [ ‘E’],
‘C’: [‘D’,‘F’],
‘D’: [‘B’,‘E’,‘G’],
‘E’: [],
‘F’: [‘D’,‘G’]
‘G’: [‘E’]}

Alt

6.完整代码实现

# 找到一条从start到end的路径
def findPath(graph,start,end,path=[]):   
    path = path + [start]
    if start == end:
        return path 
    for node in graph[start]:
        if node not in path:
            newpath = findPath(graph,node,end,path)
            if newpath:
                return newpath
    return None
 
# 找到所有从start到end的路径
def findAllPath(graph,start,end,path=[]):
    path = path +[start]
    if start == end:
        return [path]
 
    paths = [] #存储所有路径    
    for node in graph[start]:
        if node not in path:
            newpaths = findAllPath(graph,node,end,path) 
            for newpath in newpaths:
                paths.append(newpath)
    return paths
 
# 查找最短路径
def findShortestPath(graph,start,end,path=[]):
    path = path +[start]
    if start == end:
        return path
    
    shortestPath = []
    for node in graph[start]:
        if node not in path:
            newpath = findShortestPath(graph,node,end,path)
            if newpath:
                if not shortestPath or len(newpath)<len(shortestPath):
                    shortestPath = newpath
    return shortestPath
 
# 主程序
graph = {'A': ['B', 'C','D'],
         'B': [ 'E'],
         'C': ['D','F'],
         'D': ['B','E','G'],
         'E': [],
         'F': ['D','G'],
         'G': ['E']}
 
onepath = findPath(graph,'A','G')
print('一条路径:',onepath)
 
allpath = findAllPath(graph,'A','G')
print('\n所有路径:',allpath)
 
shortpath = findShortestPath(graph,'A','G')
print('\n最短路径:',shortpath)
一条路径: ['A', 'C', 'D', 'G']

所有路径: [['A', 'C', 'D', 'G'], ['A', 'C', 'F', 'D', 'G'], ['A', 'C', 'F', 'G'], ['A', 'D', 'G']]

最短路径: ['A', 'D', 'G']
  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值