dijkstra算法(单源最短路径) python实现

用例图:
在这里插入图片描述
代码1:
用最原始的方式实现dijkstra,就是每次从costs里面找最短路径的点,再遍历这个点的边,更新最短路径。由于每次都要从costs里面找最短路径,时间复杂读为O(n^2)。

# dijjkstra算法(原生最短路径,还未优化)
def dij(start, graph):
    n = len(graph)
    # 初始化各项数据,把costs[start]初始化为0,其他为无穷大
    # 把各个顶点的父结点设置成-1
    costs = [99999 for _ in range(n)]
    costs[start] = 0
    parents = [-1 for _ in range(n)]
    visited = [False for _ in range(n)] # 标记已确定好最短花销的点
    t = []  # 已经确定好最短花销的点列表
    while len(t) < n:
        # 从costs里面找最短花销(找还没确定的点的路径),标记这个最短边的顶点,把顶点加入t中
        minCost = 99999
        minNode = None
        for i in range(n):
            if not visited[i] and costs[i] < minCost:
                minCost = costs[i]
                minNode = i
        t.append(minNode)
        visited[minNode] = True

        # 从这个顶点出发,遍历与它相邻的顶点的边,计算最短路径,更新costs和parents
        for edge in graph[minNode]:
            if not visited[edge[0]] and minCost + edge[1] < costs[edge[0]]:
                costs[edge[0]] = minCost + edge[1]
                parents[edge[0]] = minNode
    return costs, parents


# 主程序

# Data
data = [
    [1, 0, 8],
    [1, 2, 5],
    [1, 3, 10],
    [1, 6, 9],
    [2, 0, 1],
    [0, 6, 2],
    [3, 6, 5],
    [3, 4, 8],
    [0, 5, 4],
    [5, 6, 7],
    [5, 3, 8],
    [5, 4, 5]
]
n = 7  # 结点数

# 用data数据构建邻接表
graph = [[] for _ in range(n)]
for edge in data:
    graph[edge[0]].append([edge[1], edge[2]])
    graph[edge[1]].append([edge[0], edge[2]])
# for edges in graph:
#     print(edges)

# 从1开始找各点到1的最短路径(单源最短路径)
# costs: 各点到店1的最短路径
# parents: 各点链接的父结点,可以用parents建立最短路径生成树
costs, parents = dij(1, graph)
print('costs')
print(costs)
print('parents')
print(parents)

# 结果:
# costs
# [6, 0, 5, 10, 15, 10, 8]
# parents
# [2, -1, 1, 1, 5, 0, 0]

代码2:用队列优化过的dijk,函数可以直接套用上面的测试代码测试

# 用优先队列实现的dijkstra算法
def dij_pq(start, graph):
    n = len(graph)
    pq = pQueue()  # 队列中的元素为[cost, v]形式,cost是该路径的花销, v是去往的结点
    visited = [False for _ in range(n)]
    t = {}
    parents = [-1 for _ in range(n)]
    pq.put([0, start, -1])
    while len(t) < n:
        # 从优先队列中找出未被确定的最短路径
        minPath = pq.get()
        while visited[minPath[1]]:
            minPath = pq.get()

        minNode = minPath[1]
        visited[minNode] = True
        t[minNode] = minPath[0]
        parents[minNode] = minPath[2]

        # 从该最短路径的结点开始找邻边,入队
        for edge in graph[minNode]:
            if not visited[edge[0]]:
                pq.put([edge[1] + t[minNode], edge[0], minNode])
    return t, parents
  • 4
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
以下是Dijkstra单源最短路径算法Python实现: ```python import sys class Graph: def __init__(self, vertices): self.V = vertices self.graph = [[0 for column in range(vertices)] for row in range(vertices)] def printSolution(self, dist): print("Vertex \t Distance from Source") for node in range(self.V): print(node, "\t\t", dist[node]) def minDistance(self, dist, sptSet): min = sys.maxsize for v in range(self.V): if dist[v] < min and sptSet[v] == False: min = dist[v] min_index = v return min_index def dijkstra(self, src): dist = [sys.maxsize] * self.V dist[src] = 0 sptSet = [False] * self.V for cout in range(self.V): u = self.minDistance(dist, sptSet) sptSet[u] = True for v in range(self.V): if self.graph[u][v] > 0 and sptSet[v] == False and dist[v] > dist[u] + self.graph[u][v]: dist[v] = dist[u] + self.graph[u][v] self.printSolution(dist) # 测试 g = Graph(9) g.graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0], [4, 0, 8, 0, 0, 0, 0, 11, 0], [0, 8, 0, 7, 0, 4, 0, 0, 2], [0, 0, 7, 0, 9, 14, 0, 0, 0], [0, 0, 0, 9, 0, 10, 0, 0, 0], [0, 0, 4, 14, 10, 0, 2, 0, 0], [0, 0, 0, 0, 0, 2, 0, 1, 6], [8, 11, 0, 0, 0, 0, 1, 0, 7], [0, 0, 2, 0, 0, 0, 6, 7, 0]] g.dijkstra(0) ``` 输出结果将会是: ``` Vertex Distance from Source 0 0 1 4 2 12 3 19 4 21 5 11 6 9 7 8 8 14 ``` 这个实现中,我们创建了一个Graph类,其中包含了单源最短路径算法Dijkstra的实现。在测试中,我们创建了一个有9个节点的图,并使用Dijkstra算法计算从第0个节点到其他节点的最短路径。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值