如何实现迪杰斯特拉算法?

177 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 26 天,点击查看活动详情

作者: 千石
支持:点赞、收藏、评论
欢迎各位在评论区交流

前言

本文内容来自我平时学习的一些积累,如有错误,还请指正

在题目实战部分,我将代码实现和代码解释设置在了解题思路的下方,方便各位作为参考刷题

一些话

本文内容来自我平时学习的一些积累,如有错误,还请指正

正文

介绍

Dijkstra算法是一种用于解决单源最短路径问题的贪心算法,它以源点为中心向外层层扩展,直到到达目标节点为止。

以下是Dijkstra算法的步骤:

  1. 将源点加入到集合S中,S中包含已找到最短路径的节点,初始化所有其他节点的距离为无穷大。
  2. 对于源点的每个邻居节点,更新它们的最短距离。即如果从源点到邻居节点的距离小于当前已知的最短距离,则更新该节点的最短距离。
  3. 在所有未访问节点中,选择最小距离的节点,并将其添加到S中。
  4. 重复步骤2和3,直到目标节点被加入到S中,或者所有可达节点的最短路径都被找到。
  5. 最终得到的结果就是源点到目标节点的最短路径。

Dijkstra算法的时间复杂度为O(E log V),其中E是边数,V是节点数。它的优点是对于任何非负权重的图,它都可以找到最短路径。

简单实现

定义一个图,用邻接矩阵表示

graph = [[0, 6, 3, 999, 999],
         [6, 0, 2, 5, 999],
         [3, 2, 0 ,3 ,4],
         [999 ,5 ,3 ,0 ,2],
         [999 ,999 ,4 ,2 ,0]]

定义一个函数,用来找到最小距离的顶点

def find_min(dist, visited):
    min_dist = float('inf')
    min_index = -1
    for i in range(len(dist)):
        if dist[i] < min_dist and not visited[i]:
            min_dist = dist[i]
            min_index = i
    return min_index

定义一个函数,用来实现Dijkstra算法

def dijkstra(graph, start):
    n = len(graph) # 图的顶点数
    dist = [float('inf')] * n # 存储源点到各个顶点的距离
    visited = [False] * n # 标记各个顶点是否已经找到最短路径
    path = [-1] * n # 存储各个顶点的前驱节点

    dist[start] = 0 # 源点到自己的距离为0

    for i in range(n): # 循环n次,每次找到一个最短路径的顶点
        u = find_min(dist, visited) # 找到当前未访问的最近的顶点u
        visited[u] = True # 标记u已经访问过了

        for v in range(n): # 遍历u的邻居v,更新dist和path
            if graph[u][v] != 999 and not visited[v]: # 如果v是u的邻居,并且还没有访问过
                if dist[u] + graph[u][v] < dist[v]: # 如果通过u到达v比原来更近,则更新dist和path
                    dist[v] = dist[u] + graph[u][v]
                    path[v] = u
    
    return dist,path

测试一下结果,假设源点是0号顶点

dist,path=dijkstra(graph,start=0)
print("源点到各个顶点的最短距离为:",dist)
print("各个顶点的前驱节点为:",path)

image.png