【问题标题】:Is Dijkstra's Algorithm just BFS where you also tally node weights?Dijkstra 的算法只是 BFS,您还计算节点权重吗?
【发布时间】:2017-08-18 15:41:05
【问题描述】:

对于在线课程,我的任务是实施 Dijkstra 算法。我按照描述完成了算法,您在其中维护已探索和未探索节点的列表,并在您遍历图形时更新其未探索邻居的距离分数(并将节点移动到已探索列表)。

我注意到这看起来很像面包优先搜索,因此我尝试修改 BFS 以在将节点添加到队列时更新节点分数。这似乎工作完全相同,但没有明确跟踪探索队列和未探索队列中的哪些节点。

这只是实现细节的问题吗?这些都是 Dijkstra 算法的例子还是不同的例子?

Dijkstra 示例:

def dijkstra(graph, source):
    explored_set = set()
    all_nodes = set(graph.keys())
    node_distances = create_distance_dict(graph)
    node_distances[source] = 0
    while explored_set != all_nodes:
        current_node = min_distance(node_distances, explored_set)
        explored_set.add(current_node)
        update_distances(graph, node_distances, current_node)
    return node_distances

def min_distance(distances_dict, explored_set):
    """ Helper function returns lowest distance node not yet explored """
    minimum = float("infinity")
    for node in distances_dict.keys():
        if node not in explored_set and distances_dict[node] <= minimum:
            minimum, min_index = distances_dict[node], node
    return min_index


def update_distances(graph, distances_dict, current_node):
    """ Helper function updates neighbor's distances """
    for n in graph[current_node]:
        if distances_dict[n[0]] > distances_dict[current_node] + n[1]:
            distances_dict[n[0]] = distances_dict[current_node] + n[1]

基于 bfs 的搜索示例

def search(graph, source, nodeDistances):
    nodeDistances[source] = 0
    queue = deque([source])
    while len(queue) != 0:
        n = queue.popleft()
        for m in graph[n]:
        # Iterate each node connected to n
            if m and nodeDistances[m[0]] > nodeDistances[n] + m[1] :
            # Compare current m score and update if n + n-m edge is shorter
                nodeDistances[m[0]] = nodeDistances[n] + m[1]
                # add m to search queue
                queue.extend([m[0]])

    return nodeDistances

两个示例都使用了 Graph 和 nodeDistances 结构:

nodeDistances = {
    1: 0,
    2: float("infinity"),
    3: float("infinity"),
    4: float("infinity"),
    5: float("infinity"),
    6: float("infinity"),
    7: float("infinity"),
    8: float("infinity"),
    }
graph = {
    1: [(2,1),(8,2)],
    2: [(1,1),(3,1)],
    3: [(2,1),(4,1)],
    4: [(3,1),(5,1)],
    5: [(4,1),(6,1)],
    6: [(5,1),(7,1)],
    7: [(6,1),(8,1)],
    8: [(7,1),(1,2)],
}

【问题讨论】:

  • Dijkstra 的算法不过是 BFS,它使用优先级队列而不是普通队列。
  • @ShreyashSSarnayak 不,BFS 一次评估一个步骤,而 Djikstra 的算法评估加权边缘。它们不是一回事
  • @NoticeMeSenpai 请看wikipedia page
  • @ShreyashSSarnayak 请看一下:stackoverflow.com/questions/3818079/…
  • @NoticeMeSenpai 一个通用的 BFS 可以做到这一点。但这是在他检查更新距离nodeDistances[m[0]] &gt; nodeDistances[n] + m[1] 的地方修改的。这将给出最短路径。

标签: python algorithm graph dijkstra


【解决方案1】:

简短的回答是:不,Dijkstra 的算法不是广度优先搜索。

正如 Stack Overflow 帖子中所述:Why use Dijkstra's Algorithm if Breadth First Search (BFS) can do the same thing faster?

Dijkstra 算法分析图的加权边,同时 BFS 分析最短距离一步一步

以下图为例(不按比例绘制):

        10
  A --------- B 
5  \          |
    C -- D    |
       3  \   | 10
           \  |
         8  \ |
             E

在上面,BFS 会发现从A to E 到的最短路径是A -&gt; B -&gt; E,这对于步数来说是正确的。 然而,Dijkstra 算法会发现从A to E 到的最短路径是A -&gt; C -&gt; D -&gt; E,因为图的边的权重

BFS 到 A to E 的距离是 20 个单位,而通过 Dijkstra 算法到 A to E 的最短距离是 16

【讨论】:

  • 是的,我明白这一点。我想我的问题更多是参考我在原始帖子中展示的修改后的 BFS,其中算法会在 BFS 遍历图形时更新连接节点之间的最小距离。
【解决方案2】:

你写的算法是单源最短路径。

Dijkstra 的算法只不过是 SSSP,我们使用优先级队列而不是普通队列。

唯一的区别是节点被访问的次数。

n = queue.popleft()
for m in graph[n]:
    if m and nodeDistances[m[0]] > nodeDistances[n] + m[1] :
        nodeDistances[m[0]] = nodeDistances[n] + m[1]
        queue.extend([m[0]])

在 Dijkstra 中,我们只是更新了优先级(距离),使其更快地访问。优先队列中的一个节点将只有一个条目。

在 SSSP 中,您可能会在其邻居更新后多次将节点添加到队列中,使其更新多次,并通过将其添加到队列中来更新其邻居。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-11
    • 2011-10-11
    • 1970-01-01
    • 2021-12-24
    • 1970-01-01
    相关资源
    最近更新 更多