数据结构与算法--迪杰斯特拉算法 Python实现迪杰斯特拉算法 一步一步带你用Python实现迪杰斯特拉算法

基本概述

  • 应用场景:
    在这里插入图片描述
    (1)分析一下,虽然还是求最短路径,但是是到各个点的最短路径,假如从G点出发,除了能直接到达的:A、B、E、F,如果要到达D点就有两种选择:一是GBD,二是GFD,选择出一条最短路径

  • 迪杰斯特拉算法介绍:
    在这里插入图片描述

  • 迪杰斯特拉算法过程:

在这里插入图片描述
在这里插入图片描述

图解

在这里插入图片描述

Python实现

# 迪杰斯特拉算法

class VisitedVertex(object):
    def __init__(self, length: int, index: int):
        """
        :param length: 表示顶点的个数
        :param index: 出发顶点对应的下标,比如G顶点,下标就是6
        """
        self.index = index  # 传入的顶点序号,打印时需要用到
        self.ver = None  # 为了便于打印顶点封装一个对象
        
        # 记录各个顶点是否访问过 1表示访问过,0表示未访问过,会动态更新
        self.already_array = [0] * length
        # 每个下标对应的值为前一个顶点的下标,会动态更新
        self.pre_visited = [0] * length
        # 记录出发顶点到其他所有顶点的距离,比如G为出发点,就记录G到其他顶点的距离,会动态更新,求的最短距离会存放在dis
        # 初始化 dis数组
        self.dis = [float('inf')] * length
        # 设置出发顶点被访问过为1
        self.already_array[index] = 1
        # 设置出发顶点的访问距离为0
        self.dis[index] = 0

    def is_visited(self, index: int):
        """
        判断index顶点是否被访问过
        :param index: 传入的顶点
        :return: 如果访问过,就返回True,否则返回False
        """
        return self.already_array[index] == 1

    def update_dis(self, index: int, length: int):
        """
        更新出发顶点到index顶点的距离
        :param index: 传入的index
        :param length: 传入的length
        :return:
        """
        self.dis[index] = length

    def update_pre(self, pre: int, index: int):
        """
        更新顶点的前驱为index结点
        :param pre:
        :param index:
        :return:
        """
        self.pre_visited[pre] = index

    def get_dis(self, index: int):
        """
        返回出发顶点到index顶点的距离
        :param index:
        :return:
        """
        return self.dis[index]

    # 继续选择并返回新的访问顶点,比如这里的G完后,就是A点作为新的访问顶点(注意不是出发顶点)
    def update_arr(self):
        min_val = float('inf')
        index = 0
        for i in range(len(self.already_array)):
            if self.already_array[i] == 0 and self.dis[i] < min_val:
                min_val = self.dis[i]
                index = i
        # 更新 index 顶点被访问过
        self.already_array[index] = 1
        return index

    # 显示最后的结果,即将三个数组的情况输出
    def show_result(self):
        print('===================')
        # 输出already_array
        for item in self.already_array:
            print(item, end=' ')
        print()
        # 输出pre_visited
        for item in self.pre_visited:
            print(item, end=' ')
        print()
        # 输出dis
        for item in self.dis:
            print(item, end=' ')
        print()
        # 为了好看最后的最短距离,处理一下
        self.ver = Graph(vertex, matrix)
        count: int = 0
        for item in self.dis:
            if item != float('inf'):
                print('{}到{}的最短距离为{}'.format(self.ver.vertex[self.index],self.ver.vertex[count],self.dis[count]))
            count += 1
        print()


class Graph(object):
    def __init__(self, vertex: [], matrix: []):
        self.vertex = vertex  # 传入顶点数组
        self.matrix = matrix  # 传入邻接矩阵
        self.vv = None  # 已经访问顶点的集合

    def show_djs(self):
        self.vv.show_result()

    def show_graph(self):  # 显示图
        for col in self.matrix:
            print(col)

    # 迪杰斯特拉算法实现
    def djs(self, index: int):
        self.vv = VisitedVertex(len(self.vertex), index)
        self.update(index)  # 更新index下标顶点到周围顶点的距离和前驱结点
        for j in range(1, len(self.vertex)):
            index = self.vv.update_arr()  # 选择并返回新的访问顶点
            self.update(index)  # 更新index下标顶点到周围顶点的距离和前驱结点

    # 更新index下标顶点到周围顶点的距离和周围顶点的前驱顶点
    def update(self, index):
        length: int = 0
        # 根据遍历邻接矩阵的 matrix[index]
        for j in range(len(self.matrix[index])):
            # length 含义:出发顶点到index顶点的距离+从index顶点到j顶点的距离的和
            length = self.vv.get_dis(index) + self.matrix[index][j]
            # 如果j顶点没有被访问过,并且length小于出发顶点到j顶点的距离,就需要更新
            if not self.vv.is_visited(j) and length < self.vv.get_dis(j):
                self.vv.update_pre(j, index)  # 更新j顶点的前驱为index顶点
                self.vv.update_dis(j, length)  # 更新出发顶点到j顶点的距离


if __name__ == '__main__':
    # 顶点
    vertex: [] = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
    # 邻接矩阵
    matrix: [] = [[0 for col in range(len(vertex))] for row in range(len(vertex))]
    # 用来表示一个极大的数
    F: float = float('inf')
    matrix[0] = [F, 5, 7, F, F, F, 2]
    matrix[1] = [5, F, F, 9, F, F, 3]
    matrix[2] = [7, F, F, F, 8, F, F]
    matrix[3] = [F, 9, F, F, F, 4, F]
    matrix[4] = [F, F, 8, F, F, 5, 4]
    matrix[5] = [F, F, F, 4, 5, F, 6]
    matrix[6] = [2, 3, F, F, 4, 6, F]
    # 创建Graph对象
    g = Graph(vertex, matrix)
    g.show_graph()
    # 测试迪杰斯特拉算法
    g.djs(6)
    g.show_djs()
''' 输出结果
[inf, 5, 7, inf, inf, inf, 2]
[5, inf, inf, 9, inf, inf, 3]
[7, inf, inf, inf, 8, inf, inf]
[inf, 9, inf, inf, inf, 4, inf]
[inf, inf, 8, inf, inf, 5, 4]
[inf, inf, inf, 4, 5, inf, 6]
[2, 3, inf, inf, 4, 6, inf]
===================
1 1 1 1 1 1 1 
6 6 0 5 6 6 0 
2 3 9 10 4 6 0 
G到A的最短距离为2
G到B的最短距离为3
G到C的最短距离为9
G到D的最短距离为10
G到E的最短距离为4
G到F的最短距离为6
G到G的最短距离为0
'''
发布了146 篇原创文章 · 获赞 37 · 访问量 7843

猜你喜欢

转载自blog.csdn.net/storyfull/article/details/104014963
今日推荐