对于在线课程,我完成了实施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)],
}
答案 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中,您可能会在其邻居更新后多次将节点添加到队列中,使其多次更新,并通过将其添加到队列来进行邻居更新。