【发布时间】:2015-07-17 05:55:35
【问题描述】:
我正在尝试实现 DFS,但是,根据 A StackOverFlow link about DFS,DFS 仅使用堆栈。
这是我当前的实现:
def DFS_graph_recursive(graph, start, end, stack):
#Stack to push the node when we are entering the node
stack.append(start)
while(end not in stack):
for i in graph.edges[start]:
#check if this is inside the stack, to make sure that it doesn't try to go back
if (i not in stack):
#Recursive Call
DFS_graph_recursive(graph, i, end, stack)
#Pop the stack when we are leaving this node, but need to make sure if end is inside
if(end not in stack):
stack.pop()
有几个问题,时间复杂度看起来不像 O(|E|)。第一个while循环是O(|E|),但是,我需要检查我的下一个节点是否已经在堆栈中,以避免返回,如果这个堆栈很大,我假设i not in stack需要O( n) 进行计算,使得该算法在复杂度上看起来像 O(|E|^2)。
if(end not in stack),使算法在时间复杂度方面变得更糟,因为对于每次边搜索,它都需要检查 end 是否在堆栈中,这意味着如果我们找到了解决方案,我们不想弹出堆栈.这进一步将时间复杂度增加到 O(|E|^2 + |E|)。有没有办法只用一个while循环来做到这一点?
就空间复杂度而言,最坏的情况应该是 O(|V|) 我们有一棵分支因子为 1 的长树。
如果它是一种二叉树类型,我可以轻松实现 O(|E|) 解决方案,它具有向下到子节点的有向路径。问题是,由于问题是无向图,假设有两个顶点,A 和 B。如果 A 连接到 B,则 B 连接到 A。所以如果我不检查if (i not in stack),我会被卡住从A到B,B到A...等来回
【问题讨论】:
-
递归调用不需要栈
-
我没有,但我需要跟踪路径,而且它保证它不会让我在两个节点之间来回走动。
-
您打算如何跟踪路径?如果你真的想要,你可以将遇到的节点推送到一个全局列表中。
-
堆栈基本上是跟踪路径。全局路径不是正确的方法,因为时间复杂度没有改变。
-
在算法节点的“标准教科书描述”中有一个与之相关的color。在运行算法之前,您首先将它们标记为白色,然后在将它们从队列中弹出时将它们标记为灰色。当您完成某个节点的循环时,您将其标记为黑色。每当您从队列中弹出一个节点时,您都会检查它的颜色。如果它不是白色的,您已经访问过它,您可以忽略它。如果它是灰色的,你就知道你找到了一个循环。检查颜色显然是 O(1) 并且标记所有节点只增加 O(|V|) 所以复杂度不会增加。
标签: python algorithm graph-algorithm