迪杰斯特拉算法(Dijkstra's algorithm)是一种解决带权有向图(或无向图)中单源最短路径(single-source shortest path)问题的贪心算法。它通过选定尚未确定最短路径的顶点中距离最小的顶点来扩展已确定最短路径的顶点集合,以此不断向图中的其他顶点扩展最短路径,直到扩展至终点或无法继续扩展为止。

基于Python实现迪杰斯特拉算法的最佳路径选择_优先队列

 

基于Python实现迪杰斯特拉算法的最佳路径选择_最短路径_02

目录

1、实现步骤

2、程序代码

3、运行结果


1、实现步骤

  1. 初始化:将源点的距离设为零,所有其他点的距离设为无穷大。
  2. 将源点加入到一个优先队列中,队列中元素的优先级根据距离排序,距离越小,优先级越高。
  3. 对于队列中的每个顶点,遍历它所有的邻居节点,并计算从源点到邻居节点的距离。如果这个距离比邻居节点已有的距离更短,更新邻居节点的距离,并将邻居节点加入到优先队列中。
  4. 标记当前顶点为已访问。
  5. 重复步骤3-4,直到优先队列为空或者找到目标节点。
  6. 如果找到目标节点,则可以通过反向查找每个节点的父节点,确定起点到目标节点的最短路径。

2、程序代码

#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
@author: ewb
"""


# 定义节点类
class Node:
    def __init__(self, name):
        self.name = name
        self.neighbours = {}
        self.distance = float("inf")
        self.visited = False
        self.parent = None

    def add_neighbour(self, neighbour, weight=0):
        self.neighbours[neighbour] = weight

    def get_neighbours(self):
        return self.neighbours.keys()


# 定义图类
class Graph:
    def __init__(self):
        self.nodes = {}

    def add_node(self, node):
        self.nodes[node.name] = node

    def get_node(self, name):
        if name in self.nodes:
            return self.nodes[name]
        else:
            return None

    def add_edge(self, start, end, weight=0):
        if start not in self.nodes:
            self.add_node(Node(start))
        if end not in self.nodes:
            self.add_node(Node(end))

        self.nodes[start].add_neighbour(self.nodes[end], weight)
        self.nodes[end].add_neighbour(self.nodes[start], weight)

    def get_nodes(self):
        return self.nodes.keys()

    def reset_nodes(self):
        for node in self.nodes.values():
            node.distance = float("inf")
            node.visited = False
            node.parent = None


# 定义迪杰斯特拉算法函数
def dijkstra(start_node, end_node):
    start_node.distance = 0
    queue = [start_node]
    while queue:
        node = queue.pop(0)
        node.visited = True
        for neighbour in node.get_neighbours():
            if not neighbour.visited:
                new_distance = node.distance + node.neighbours[neighbour]
                if new_distance < neighbour.distance:
                    neighbour.distance = new_distance
                    neighbour.parent = node
                queue.append(neighbour)
    path = [end_node]
    # 如果存在父节点
    if end_node.parent:
        while end_node.parent != start_node:
            path.append(end_node.parent)
            end_node = end_node.parent
    path.append(start_node)
    path.reverse()
    return path


if __name__ == '__main__':
    # 测试
    graph = Graph()
    graph.add_edge("A", "B", 7)
    graph.add_edge("B", "C", 8)
    graph.add_edge("B", "E", 7)
    graph.add_edge("A", "D", 5)
    graph.add_edge("D", "F", 6)
    graph.add_edge("F", "G", 11)
    # 开始节点
    start_node = graph.get_node("A")
    # 结束节点
    end_node = graph.get_node("F")
    path = dijkstra(start_node, end_node)
    print("节点{}到节点{}:\n最短距离为:{}\n最短路径为:".format(start_node.name, end_node.name, end_node.distance), end=" ")
    for index, node in enumerate(path):
        if index < len(path) - 1:
            print(node.name, ">", end=" ")
        else:
            print(node.name, end=" ")

3、运行结果

基于Python实现迪杰斯特拉算法的最佳路径选择_优先级_03

基于Python实现迪杰斯特拉算法的最佳路径选择_优先级_04