You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dijkstra单源最短路径Python实现距离计算错误排查

Dijkstra算法实现首次迭代后结果错误排查

我正在尝试实现Dijkstra算法,求解源顶点1到所有其他顶点的最短距离,具体实现代码如下:

from ast import literal_eval


p = {}
with open(r'dijk.txt') as file:
    for line in file:
            line_content = line.split()
            p[int(line_content[0])] = [literal_eval(edge) for edge in line_content[1:]]
    source_vertex = next(iter(p.keys()))


print("Vertex 1's paths:", p[1])
print("1st value for vertex 1:", p[1][0])
print("1st neighbour of vertex 1:",p[1][0][0])
print("Distance of 1st neighbour of vertex 1:",p[1][0][1])


X = [1]
Y = [1]
A = {}
A[1] = 0
for i in range(2,201):
    A[i] = 100000000
    Y.append(i)


while X != Y:
    b = {}
    for eachvertex in X:
        b2 = 0
        for eachneighbour in p[eachvertex]:
            if eachneighbour[0] not in X:
                b2 = A[eachvertex]+eachneighbour[1]
                b[eachneighbour[0]] = b2
    vertex_to_be_added = min(b, key = b.get)
    X.append(vertex_to_be_added)
    A[vertex_to_be_added] = min(b.values())
    print("Vertex added :",vertex_to_be_added, "and distance :",min(b.values()))
    X.sort()

本次测试使用的数据源可通过链接获取:LinkToData

该代码在while循环第一次迭代时运行正常,但后续迭代计算得到的新增顶点最短距离结果不正确。


核心逻辑错误定位

代码共有两处直接导致结果错误的逻辑问题:

  • 跨集合边的距离值被随意覆盖
    每次循环都会重新初始化空字典b,遍历已加入最短路径集合X的所有顶点的出边时,只要边的另一端不在X中,就直接把计算出的距离写入b,完全不判断这个邻居顶点是否已经在b里存了更小的候选距离。
    举个例子:顶点2、3都已在X中,两者都连向未加入X的顶点4:从顶点2到4的候选距离是10,从顶点3到4的候选距离是5。如果遍历顺序是先处理顶点2再处理顶点3,b[4]会先被赋值10,再被更小的5覆盖,结果暂时正确;但如果遍历顺序反过来,先处理顶点3算出距离5,再处理顶点2算出距离10,原本更小的5就会被10覆盖,直接导致后续选最小距离出错。
    正确逻辑是:计算出到未入集合邻居的距离后,只有当该邻居不在b中,或者新计算的距离比b中已存的距离更小时,才更新b里的值,否则保留原有更小的距离。
  • 新顶点的最短距离赋值错误
    选出本轮要加入X的顶点后,代码直接给该顶点的最短距离A[vertex_to_be_added]赋值为min(b.values()),也就是整个b字典里的全局最小值,这是完全错误的。min(b.values())只对应本轮所有候选顶点里距离最小的那个值,不是当前选中顶点自己的候选距离。比如本轮b中顶点4的候选距离是5、顶点5的候选距离是3,全局最小值3对应顶点5,选中顶点5加入时赋值3是对的;但如果后续轮次里b中顶点4的候选距离是10、顶点6的候选距离是2,全局最小值是2对应顶点6,此时如果选中顶点4加入,代码会错误把顶点4的距离赋值为2,结果完全错乱。
    正确逻辑是:新顶点加入X时,它的最短距离直接取b[vertex_to_be_added],也就是该顶点自己在候选字典里对应的距离值即可。

另外循环内定义的b2 = 0没有任何实际作用,可以直接删除。


修正后的核心循环参考
while X != Y:
    b = {}
    for eachvertex in X:
        for eachneighbour in p[eachvertex]:
            neighbor_id = eachneighbour[0]
            if neighbor_id not in X:
                current_dist = A[eachvertex] + eachneighbour[1]
                # 仅当邻居无记录或新距离更小时才更新候选值
                if neighbor_id not in b or current_dist < b[neighbor_id]:
                    b[neighbor_id] = current_dist
    vertex_to_be_added = min(b, key = b.get)
    X.append(vertex_to_be_added)
    # 赋值为当前顶点对应的候选距离
    A[vertex_to_be_added] = b[vertex_to_be_added]
    print("Vertex added :", vertex_to_be_added, "and distance :", A[vertex_to_be_added])
    X.sort()

内容的提问来源于stack exchange,提问作者v1998199904

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 05:09:21