我正在使用DFS算法,并希望将每个边缘标记为已访问,一种方法是查找节点并将其替换为一些标记,但如果我创建一个邻接列表来存储对应的值,那将会很昂贵访问的节点会增加查找时间,矩阵会占用大量空间。这样做的最佳算法是什么?
答案 0 :(得分:0)
您只需要维护一组顶点对。例如,Java HashMap<Pair<Vertex, Vertex>>
。在Python中,Set
的2元素元组。
当您枚举刚刚发现的新顶点的后代并将它们添加到DFS堆栈时,会发生对边的访问。如果您正在使用递归DFS,那么就像您在每个后代上进行递归调用一样。这是堆栈版本:
dfs(graph)
visitedVertices = \emptyset
visitedEdges = \emptyset
// Try all vertices as search roots
for each vertex r in graph
push r onto empty stack
while notEmpty(stack)
u = pop stack
if u not in visitedVertices
add u to visitedVertices
foreach v such that u->v is in graph
add (u,v) to visitedEdges // Visit the edge
push v on stack
话虽如此,我不确定你为什么要这样做。正确实现的DFS自然地遍历每个边缘一次。你可以通过查看上面的算法来证明这一点。只有在之前从未访问过(u,v)
时,才能访问u
。
也许你有一些其他线程正在观察搜索进度或实际上在你访问时向边缘添加其他信息?
答案 1 :(得分:0)
我不得不解决同样的问题。
在我的代码中,图表示为邻接表:graph [i]-是给定顶点i的节点列表。
我制作了一个集,其中存储了访问的边。边是大小为2的元组。
深度搜索优先:
def visit_and_print_node(node):
"""Node visitor"""
print(str(node))
def dsf_edges(graph, node_visitor_function=visit_and_print_node, starting_node=0):
"""
Performs depth-first search algorithm on the edges of the graph.
Note, here we visit edges, so it is OK for us to visit the same node more than once.
"""
visited_edges = set()
# next node to be visited is the last inserted element of the stack.
stack = []
next_nodes = graph[starting_node]
node_visitor_function(starting_node)
for node in next_nodes:
stack.append((starting_node, node))
while len(stack) > 0:
visited_edge = stack.pop()
if visited_edge in visited_edges:
continue
visited_node = visited_edge[1]
# visit node
node_visitor_function(visited_node)
visited_edges.add(visited_edge)
next_nodes = graph[visited_node]
for node in next_nodes:
if not (visited_node, node) in visited_edges:
stack.append((visited_node, node))
如果您要查看其他示例,请在边缘(使用队列而不是堆栈)或节点(每次访问一次节点)上使用BSF,请检查my git repository:
其他有用的链接: