python中的dijkstra实现 - 输出并不总是正确的

时间:2018-05-07 09:05:55

标签: python optimization graph-theory

我使用基于堆的优先级dict实现了dijkstra的最短路径算法。它有以下方法:smallest() - 仅返回具有最小值的dict中的最小键。 pop_smallest()返回堆中具有最小值的最小键,并从堆dict中弹出它。 我在github上的一些测试中测试了代码,有些测试是正确的,有些则没有。我已经看到了这个算法的更多实现,但我想在我看到比我更好的其他人之前让我的方法正确。

我是初学者,您可能已经形成了一个眼睛来识别我的代码中的错误。亲切的问候, 编辑:我不知道是否允许我发布其他网站的链接,但本网站包含我使用的测试:https://github.com/beaunus/stanford-algs/tree/master/testCases/course2/assignment2Dijkstra 上下文是这个实现是关于图表的课程的一个任务的一部分。分配是计算到第7个节点,第35个节点等的距离。如果其中一些是错误的,那么很明显代码中出现了问题。 为了更清楚,input_random_10_16测试输出不同的答案。并非所有距离都是正确的。

  • 我的实施产出:[878,405,785,534,909,328,708,957,830,911]
  • 正确答案是:[588,405,675,521,909,328,418,957,830,839]

有些距离是正确的,有些距离不正确。

编辑:我最终重新制作了一个通过所有测试的不同实现。这是堆实现。我也想做一些没有使用堆的天真实现。我在网上搜索了不同的天真实现,我发现有几个输出与此实现相同的错误结果。 这怎么可能?一个很好的实现也发布在github上,当我的图表上使用了很多人时,这些错误的结果就输出了。

def dijkstra(graph, s):
    processed = set([s])
    vertexes = set([])
    distances = {}
    ans = []
    heap = priority_dict()
    for i in graph:
        vertexes.add(i)
        distances[i] = 0
        if i not in processed:
            heap[i] = float('inf')
    while processed != vertexes:
        for i in processed:
            neigh = graph[i]
            for j in heap:
                if j in neigh:
                    score = distances[i] + graph[i][j]
                    if score < heap[j]:
                        heap[j] = score
        smallest_value = heap[heap.smallest()]
        smallest_key = heap.pop_smallest()
        processed.add(smallest_key)
        distances[smallest_key] = smallest_value
        for j in graph[smallest_key]:
            if j in heap:
                old_val = heap[j]
                new_val = min(old_val, distances[smallest_key] + graph[smallest_key][j])
                heap[j] = new_val
    list_ = [7,37,59,82,99,115,133,165,188,197]
    for i in list_:
        ans.append(distances[i])
    return ans

1 个答案:

答案 0 :(得分:2)

算法的某些部分似乎有误: 实际上源不应该在开始时处理。它应该只是距离为0的唯一顶点。然后它将被选为第一个smallest_key。因此,不再需要计算所有分数的while循环的开头。需要执行更新的唯一部分是更新循环结束时smallest_key的邻居的距离。

def dijkstra(graph, s):
    processed = set([])
    vertexes = set([])
    distances = {}
    ans = []
    heap = priority_dict()
    for i in graph:
        vertexes.add(i)
        distances[i] = 0
        if i != s:
            heap[i] = float('inf')
        else:
            heap[i] = 0 
    while processed != vertexes:
        smallest_value = heap[heap.smallest()]
        smallest_key = heap.pop_smallest()
        processed.add(smallest_key)
        distances[smallest_key] = smallest_value
        for j in graph[smallest_key]:
            if j in heap:
                old_val = heap[j]
                new_val = min(old_val, distances[smallest_key] + graph[smallest_key][j])
                heap[j] = new_val
    list_ = [7,37,59,82,99,115,133,165,188,197]
    for i in list_:
        ans.append(distances[i])
    return ans