Dijkstra的算法只是BFS,你还可以计算节点权重吗?

时间:2017-03-25 19:20:46

标签: python algorithm graph dijkstra

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

我注意到这看起来很像面包第一次搜索,所以我尝试修改BFS以在节点添加到队列时更新节点分数。这似乎完全相同,但没有明确跟踪探索的vs未探测队列中的节点。

这只是实施细节的问题吗?这些都是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

用于两个示例的图和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)],
}

2 个答案:

答案 0 :(得分: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 -> B -> E步数的路径为真。 但是,Dijkstra算法会发现A to E的最短路径为A -> C -> D -> E,因为图形边缘的权重

BFS与A to E的距离为20个单位,而来自A to E的Dijkstra算法的最短距离为16

答案 1 :(得分:1)

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

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,我们只是更新优先级(距离),使其更快访问。 proirity队列中的节点只有一个条目。

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