最短路径 迪杰斯特拉算法

def myDijkstra(statr:int, lst:list):
    """
    :param statr:  开始的地点
    :param lst:  各个城市之间的距离,  二维数组,就是用行列坐标表示图形上两点之间的距离。
    :return:  到各个城市的最短距离
    """
    # city 未被当作中间节点的城市列表
    city = [x for x in range(len(lst)) if x != statr]
    # 城市顺序
    cityorder = [statr]
    citylength = lst[statr]    # len1 是一一维列表,里面包含着 成市 n 到各个城市的初始距离
    # 用循环判断,城市n 到其他城市中最短的距离
    while len(city):
        idenx1 =city[0]
        for i in city:
            if citylength[i] < citylength[idenx1]:
                idenx1 = i
        # 将做过中间节点的移出city
        city.remove(idenx1)
        # 添加到城市最近列表
        cityorder.append(idenx1)
        # 更新成市 n 到各个城市之间的最短距离
        for i in city:
            # 当新的路线距离更进时,会更新 个城市直接的距离
            if citylength[idenx1]+lst[idenx1][i] < citylength[i]:
                citylength[i] = citylength[idenx1]+lst[idenx1][i]
    return citylength


if __name__ == '__main__':
    max = 999999  # max即表示为无法直达

    graph = [
        [5, max, 10, max, 30, 100],
        [max, max, 5, max, max, max],
        [max, 15, max, 50, max, max],
        [max, max, max, max, max, 10],
        [max, max, max, 20, max, 60],
        [max, 15, max, max, max, max],
    ]
    inf = 999999
    mgraph = [[0, 1, 12, inf, inf, inf],
              [inf, 0, 9, 3, inf, inf],
              [inf, inf, 0, inf, 5, inf],
              [inf, inf, 4, 0, 13, 15],
              [inf, inf, inf, inf, 0, 4],
              [inf, inf, inf, inf, inf, 0]]

    len1 = myDijkstra(0,graph)
    print(len1)
    len2 = myDijkstra(0, mgraph)
    print(len2)






def startwith(start: int, mgraph: list) -> list:
    passed = [start]
    # 初始化数组,一共有多少个城市 并为城市编号
    nopass = [x for x in range(len(mgraph)) if x != start]
    print('nopass',nopass)
    # 到直接各个点之间的最短距离,不能直接到达的距离就是 10086
    dis = mgraph[start]
    print(dis)
    # 执行循环,找出初始位置到各个点的最短路径
    while len(nopass):
        idx = nopass[0]
        for i in nopass:
            if dis[i] < dis[idx]:
                idx = i

        nopass.remove(idx)
        # 还有那个的点未被访问
        print("111111",nopass)
        passed.append(idx)
        # 最短路径的走法
        print("22222",passed)

        for i in nopass:
            if dis[idx] + mgraph[idx][i] < dis[i]:
                dis[i] = dis[idx] + mgraph[idx][i]
    return dis

def dijkstra(graph, start_Node, path, cost, max):
    """
    graph:二维数组,就是用行列坐标表示图形上两点之间的距离。
    start_Node:起始点
    path[i] 表示vi节点的前一个节点,即中转点。
    cost[i] 表示V0到Vi的已知最短路径长度
    mid_Node:中转点,以已求得V0到Vi的最短路径的Vi作为中转点。
    NEXT_Node:尝试优化的点,以中转点为中心,检测NEXT_Node直达V0方案,和经过mid_Node中转到V0的方案哪个更优
    check_Node:索引,搜索cost数组里最短路径的点,最短的点会赋值给mid_Node,作为中转点。
    """
    lenth = len(graph)
    v = [0] * lenth  # V数组初始化为0,用于标记该点是否已取得最短路径
    # 初始化 path,cost,V
    for i in range(lenth):
        if i == start_Node:
            v[start_Node] = 1
        else:
            cost[i] = graph[start_Node][i]  # cost获取起点至其他点的直达权重
            path[i] = (start_Node if (cost[i] < max) else -1)  # 前置点为起点或-1(无法直达起点)

    # print v, cost, path
    for i in range(1, lenth):  # 遍历的数等于除去起点的点的数量
        minCost = max  # 初始值取最大
        mid_Node = -1
        for check_Node in range(lenth):  # 搜索一个到起点V0最近的点,作为中转点mid_Node
            if v[check_Node] == 0 and cost[check_Node] < minCost:  # mid_Node点未取得最短路径,且路径权重小于最小值,则获取w,也就是先取得
                minCost = cost[check_Node]
                mid_Node = check_Node

        if mid_Node == -1: break  # 找不到权重小于max的点
        # 剩下都是不可通行的节点,跳出循环
        v[mid_Node] = 1  # check_Node已取得最短路径
        for NEXT_Node in range(lenth):
            if v[NEXT_Node] == 0 and (graph[mid_Node][NEXT_Node] + cost[mid_Node] < cost[
                NEXT_Node]):  # 检查所有未遍历的点NEXT_Node,检测前面获取的mid_Node对NEXT_Node的影响
                cost[NEXT_Node] = graph[mid_Node][NEXT_Node] + cost[mid_Node]  # 更新权值
                path[NEXT_Node] = mid_Node  # 更新路径
        # for 更新其他节点的权值(距离)和路径
    return path

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值