【发布时间】:2021-04-18 02:00:50
【问题描述】:
我正在使用 BFS 在 ruby 中实现一个函数,我想知道如何在无向图中打印起始值和结束值之间的最短路径
图表 在这个例子中,图有十个顶点。每个节点代表一个顶点,它有一个存储相邻节点(边)的数组。
$ irb
graph.to_s
1. 1 -> [2 3 4 5 8 9 10]
2. 2 -> [1 4 5 6 7 8 10]
3. 3 -> [1 4 6]
4. 4 -> [1 2 3 6 7 8 9 10]
5. 5 -> [1 2 8 9 10]
6. 6 -> [2 3 4 7 8 9 10]
7. 7 -> [2 4 6 8 9]
8. 8 -> [1 2 4 5 6 7 9 10]
9. 9 -> [1 4 5 6 7 8]
10. 10 -> [1 2 4 5 6 8]
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
预期输出
2,1,9 或 2,4,9 等
BFS
def bfs_shortest_path(graph, start=2, search=9)
if graph.nodes[start].nil? || graph.nodes[search].nil?
return nil
end
visited = Set.new
search_queue = Queue.new
search_queue.enq(start)
while !search_queue.empty? do
current_node_key = search_queue.deq
current_node = graph.nodes[current_node_key]
visited.add(current_node_key)
if current_node.value == search
return current_node # I would like to return the PATH Eg. 2,1,9
end
adjacent_nodes_array = current_node.adjacent_nodes.map{|x| x.value}
adjacent_nodes_array.each do |value|
if !visited.include?(value)
search_queue.enq(value)
graph.nodes[value].concat_to_path(current_node.path_from_start)
end
end
end
end
节点
class Node
attr_reader :value
attr_reader :adjacent_nodes
def initialize(value)
@value = value
@adjacent_nodes = []
end
def add_edge(node)
@adjacent_nodes.push(node)
end
def to_s
"#{@value} -> [#{@adjacent_nodes.map(&:value).sort.join(" ")}]"
end
end
图表
class Graph
attr_reader :nodes
def initialize
@nodes = {}
end
def add_node(node)
@nodes[node.value] = node
end
def add_edge(node1,node2)
if @nodes[node1.value].adjacent_nodes.map(&:value).include? (node2.value)
puts "#{node1.value} and #{node2.value} already have an edge"
elsif node1.value == node2.value
puts "node1.value == node2.value"
else
@nodes[node1.value].add_edge(@nodes[node2.value])
@nodes[node2.value].add_edge(@nodes[node1.value])
end
end
def to_s
@nodes.keys.sort.each_with_index do |key,index|
puts "#{index + 1}. #{@nodes[key].to_s}"
end
end
end
生成图表
def generate_random_graph
g = Graph.new
[*1..10].shuffle.each do |node_value|
g.add_node(Node.new(node_value))
end
40.times do
key1 = g.nodes.keys.sample
key2 = g.nodes.keys.sample
g.add_edge(g.nodes[key1],g.nodes[key2])
end
return g
end
测试
graph = generate_random_graph
graph.to_s
bfs_shortest_path(graph,2,9)
【问题讨论】:
-
你也可以发布
Graph结构吗?这意味着您将编写的节点初始化部分! -
您应该在入队时记录一个顶点已被访问过。 (这包括在循环之前将起始顶点设置为已访问。)同时记录父顶点,即导致顶点入队的
current_node_key。然后当你找到结束顶点时,你可以跟随父母回到起点重新创建路径。请注意,您可以使用父列表来跟踪已访问的顶点。已访问具有父节点的顶点。 -
@MaruthiAdithya 完成谢谢
-
@ggorlen 完成。通过函数 generate_random_graph。谢谢
-
@ggorlen 完美!谢谢
标签: ruby algorithm breadth-first-search