如果我在'grid'上运行dijskstra的algroithm,那么使用优先级队列是没有意义的吗?
网格就像这样的地图: 顶点:
___________________
|A|_|_|_|_|_|_|_|_|_|
|C|B|_|_|_|_|E|_|_|_|
|_|_|_|_|_|_|_|_|_|_|
|_|_|_|_|_|_|_|_|_|_|
|_|_|_|_|_|_|_|_|_|_|
|_|_|_|_|_|_|_|_|_|_|
|_|_|_|_|_|_|_|_|_|_|
|D|_|_|_|_|_|F|_|_|_|
|_|_|_|_|_|_|_|_|_|_|
边缘:
A <-> C
C <-> B
C <-> D
D <-> F
B <-> E
E <-> F
换句话说,一个地图,其中每条边连接到与其水平或垂直的顶点,但不能对角连接(例如,不允许从A到B或A到F的边)。
此外,边缘的权重对于它们在网格中的位置是直观的。例如,A - 的边缘权重为A - 。 C是1,C - 是H. B为1,C - 是H. D为6,B - 为0。 E为5且D - F和E - 为0。 F都是6。
我之前实现了dijsktra的算法用于这样的图形,我现在需要对其进行优化以使其尽可能快。我目前的实施(红宝石):
def self.dj_start(g,source, goal)
t = Time.now
visited, distances, paths, already_queued = {}, {}, {}, {}
curr = g.verticies[source]
queue = [] #
queue.push(curr)
already_queued[curr] = true
distances[curr] = 0
paths[curr] = curr
@count = 0
while(!queue.empty?)
run_dijkstra(g, visited, distances, paths, queue, already_queued, goal)
end
t = Time.now - t
print "ran dijkstra in #{t}s count = #{@count}\n"
return [paths, distances]
end
def self.run_dijkstra(g, visited, distances, paths, queue, already_queued, goal)
curr = g.verticies[queue.delete_at(0)]
visited[curr] = true
curr.edges.each do |e|
@count+=1
if !already_queued[e.vertex] && !visited[e.vertex]
queue.push(e.vertex)
already_queued[e.vertex] = true
end
nd = e.weight+distances[curr]
if distances[e.vertex].nil? || nd < distances[e.vertex]
distances[e.vertex] = nd
paths[e.vertex] = curr
if e.vertex.eql?(goal) # minor optimization
queue = []
return 1 # Code for exit due to this very minor optimization
end
end # end distance check
end
端
我打算用优先级队列重写它,但我不认为有必要这样做。或者我错过了什么?
答案 0 :(得分:0)
通常使用广度优先搜索来解决类似问题,其中每个单元格是图形中的顶点。你正在解决的问题仍然是有效位置的数量与网格中的单元格数量相比真的很低,所以也许你的方法可行。请注意,边缘权重(即,您需要在位置之间移动的最小单元格数)应以某种方式提供给您的程序。如果不是这种情况,你将不得不使用BFS计算这些,因此Dijkstra没有任何意义。
话虽如此,我会回答你的问题。如果以您在此处显示的方式提供边缘,则有理由使用优先级队列。它将使算法的计算复杂度降低一个数量级。这对于较大的网格来说是显而易见的。
顺便说一下,有一个真正很酷的宝石用于实现斐波那契堆的红宝石。虽然使用斐波那契堆来制作grpahs可能是一个巨大的过度杀戮,但是你在这里展示的尺寸我总是很高兴有一个基于斐波那契堆的dijkstra。
希望这个答案有所帮助。